爬虫实战| 1宅男女神(秀人网专区)—让人心情愉悦的图片爬取 ![通俗易懂]

爬虫实战| 1宅男女神(秀人网专区)—让人心情愉悦的图片爬取 ![通俗易懂]目标是宅男女神的美女图片板块下的秀人板块,页面上全部是该网站收录的美女图片分类,大概浏览了一下,发现各个杂志社的图片(妹子)质量最高,其中以秀人为首,所以决定爬取所有秀人板块下的图片.目标网页截图该网页这里显示只有5页,后面的页面在点击下一页后出现.为了过审还是打码了,本来都是穿着衣服的正经妹妹,兄弟们可别误会了~首先利用Chrome抓包第一步先利用抓包工具来判断我们要爬取的网站是动态数据还是静态数据.这里可以清楚的看到,当我们发起请求之后,所有我们需要的东西都已经加载

大家好,又见面了,我是你们的朋友全栈君。

目标是宅男女神的美女图片板块下的秀人板块, 页面上全部是该网站收录的美女图片分类, 大概浏览了一下, 发现各个杂志社的图片(妹子) 质量最高, 其中以秀人为首, 所以决定爬取所有秀人板块下的图片.

目标网页截图

在这里插入图片描述
该网页这里显示只有5页, 后面的页面在点击下一页后出现.
为了过审还是打码了, 本来都是穿着衣服的正经妹妹, 兄弟们可别误会了~

首先利用Chrome抓包

第一步先利用抓包工具来判断我们要爬取的网站是动态数据还是静态数据.

这里可以清楚的看到,当我们发起请求之后, 所有我们需要的东西都已经加载并缓存好了, 并没有什么反爬措施, 这一步分析后,我们可以直接写代码,看看我们分析的对不对.

在这里插入图片描述

from lxml import etree
import os
import requests
headers = { 
   
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36',
}

response = requests.get('目标网址', headers=headers)
# 这里直接拿会全部是乱码, encoding成utf-8显示正常
response.encoding = 'utf-8'
page_text = response.text
print(page_text)

在这里插入图片描述

发现确实是我们需要的网页信息, 现在就可以对页面进行分析, 用xpath拿到我们想要的数据
发现我们每个妹妹都在li标签里, 并且需要拼接的url和title也可以在li标签里找到.
在这里插入图片描述

from lxml import etree
import os
import requests
# 该网站没什么反爬手段, 直接用最简单的header反而效果好
headers = { 
   
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36',
}

response = requests.get('目标网址', headers=headers)
# 这里直接拿会全部是乱码, encoding成utf-8显示正常
response.encoding = 'utf-8'
page_text = response.text
print(page_text)

tree = etree.HTML(page_text) # 
li_list = tree.xpath("//div[@id='listdiv']//li")

for li in li_list:
    img_list = []
    img_dict = { 
   }
    task_list = []
	# 拼接每个妹妹的url, 并给每个妹妹创建一个文件夹
    box_url = host + li.xpath('.//div[2]/a/@href')[0]
    file_name = li.xpath('.//div[2]/a/text()')[0]
    if not os.path.exists('./' + file_name):
        os.mkdir(file_name)

详情页分析

现在主页面的信息我们都已经拿到了, 下一步就是进入每一个妹妹详情页面, 去下载图片
在这里插入图片描述

对详情页面分析, 发现每一页都会有三张图片, 并且下面需要翻页, 经测试如果翻到最后一页再点下一页会跳转到第一页, 这里找发现在第一页会显示每个妹妹图集里有多少张图
在这里插入图片描述
用xpath拿出来, 用正则把数字提取出来.到这一步我们的页面分析已经结束了, 直接上代码, 因为这么写下载速度很慢, 所以代码有几个版本, 包括线性的和协程的来对比和优化.

线性翻页下载图片

from lxml import etree
import os
import requests
# 该网站没什么反爬手段, 直接用最简单的header反而效果好
headers = { 

'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36',
}
host = '目标网站host'
response = requests.get('目标网址', headers=headers)
# 这里直接拿会全部是乱码, encoding成utf-8显示正常
response.encoding = 'utf-8'
page_text = response.text
print(page_text)
tree = etree.HTML(page_text) # 
li_list = tree.xpath("//div[@id='listdiv']//li")
for li in li_list:
img_list = []
img_dict = { 
}
task_list = []
# 拼接每个妹妹的url, 并给每个妹妹创建一个文件夹
box_url = host + li.xpath('.//div[2]/a/@href')[0]
file_name = li.xpath('.//div[2]/a/text()')[0]
if not os.path.exists('./' + file_name):
os.mkdir(file_name)
# 这里进入详情页
page_detail = requests.get(url=box_url, headers=headers).text
detail_tree = etree.HTML(page_detail)
# 拿到一个图集中有多少图片的信息
NumbersOfImage = int(re.findall('(\d+)', (detail_tree.xpath('//*[@id="dinfo"]/span/text()')[0]))[0])
# 下载图片(如果图片列表里不到最大图片数量就一直翻页下载)
while len(img_list) != NumbersOfImage:
# 因为每页三张, 用一个for loop解析下载
for i in detail_tree.xpath('//*[@id="hgallery"]/img'):
img_dict = { 
}
img_dict['title'] = './' + file_name + '/' + i.xpath('./@alt')[0] + '.jpg'
img_dict['src'] = i.xpath('./@src')[0]
# 利用requests content下载到二进制数据, 并保存
bytes_img = requests.get(url=img_dict['src'], headers=headers).content
with open(img_dict['title'], 'wb') as fp:
fp.write(bytes_img)
img_list.append(img_dict)
print(img_dict['title'], "下载完成", img_dict['src'])
# 翻页部分, 利用xpath拿到下一页标签中的url 与host进行拼接,形成下一页的url
next_page = host + detail_tree.xpath('//*[@id="pages"]/a[last()]/@href')[0]
new_page_detail = requests.get(url=next_page, headers=headers).text
new_page_detail_tree = etree.HTML(new_page_detail)
detail_tree = new_page_detail_tree
print(next_page)

在这里插入图片描述
在这里插入图片描述

这里拿到了我们想要的结果, 每页下载图片, 然后翻页, 但是这么下载的速度实在是太慢了, 一个妹妹的全部图集一张一张的下载完, 全站的图片不知道哪年才能拿到
在这里插入图片描述
这里这个妹妹图片只有35张耗时17秒, 大部分妹妹的图集都超过70张, 所以现在想办法用asyncio协程来优化一下下载速度

第一次优化

from lxml import etree
import os
import requests
import re
import time
import asyncio
import aiohttp
# 协成下载
# asyncio不支持requests, 所以这里要用到aiohttp来下载, 和requests用法相似
sem = asyncio.Semaphore(20)
async def down_load(path, url):
with(await sem):
async with aiohttp.ClientSession() as sess:
async with await sess.get(url=url, headers=headers) as response:
img_bytes = await response.read()
with open(path, 'wb') as img:
img.write(img_bytes)
print(path, " 下载成功 ", url)
# 该网站没什么反爬手段, 直接用最简单的header反而效果好
headers = { 

'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36',
}
host = '目标网站host'
response = requests.get('目标网站', headers=headers)
# 这里直接拿会全部是乱码, encoding成utf-8显示正常
response.encoding = 'utf-8'
page_text = response.text
tree = etree.HTML(page_text)  #
li_list = tree.xpath("//div[@id='listdiv']//li")
for li in li_list:
img_list = []
img_dict = { 
}
task_list = []
# 拼接每个妹妹的url, 并给每个妹妹创建一个文件夹
box_url = host + li.xpath('.//div[2]/a/@href')[0]
file_name = li.xpath('.//div[2]/a/text()')[0]
if not os.path.exists('./' + file_name):
os.mkdir(file_name)
# 这里进入详情页
page_detail = requests.get(url=box_url, headers=headers).text
detail_tree = etree.HTML(page_detail)
# 拿到一个图集中有多少图片的信息
NumbersOfImage = int(re.findall('(\d+)', (detail_tree.xpath('//*[@id="dinfo"]/span/text()')[0]))[0])
# 下载图片(如果图片列表里不到最大图片数量就一直翻页下载)
while len(img_list) != NumbersOfImage:
# 因为每页三张, 用一个for loop解析下载
for i in detail_tree.xpath('//*[@id="hgallery"]/img'):
img_dict = { 
'title': './' + file_name + '/' + i.xpath('./@alt')[0] + '.jpg', 'src': i.xpath('./@src')[0]}
# 利用requests content下载到二进制数据, 并保存
# bytes_img = requests.get(url=img_dict['src'], headers=headers).content
# with open(img_dict['title'], 'wb') as fp:
# fp.write(bytes_img)
img_list.append(img_dict)
# 翻页部分, 利用xpath拿到下一页标签中的url 与host进行拼接,形成下一页的url
next_page = host + detail_tree.xpath('//*[@id="pages"]/a[last()]/@href')[0]
new_page_detail = requests.get(url=next_page, headers=headers).text
new_page_detail_tree = etree.HTML(new_page_detail)
detail_tree = new_page_detail_tree
print(next_page)
# 建立协程任务
loop = asyncio.get_event_loop()
for img_url in img_list:
c = down_load(img_url['title'], img_url['src'])
task = asyncio.ensure_future(c)
# task.add_done_callback(parse)
task_list.append(task)
loop.run_until_complete(asyncio.wait(task_list))
print("单个妹妹图集耗时: ", time.time() - start)
exit()

在这里插入图片描述
这里发现如果用协成来下载的话, 速度比之前快很多, 变成了4秒钟左右, 但是翻页等操作还是线性的,还是会占用大块的时间, 现在想办法把对一个页面里所有妹妹的图集请求变成协成的, 最终代码如下

最终版本

import requests
import time
import asyncio
import aiohttp
from lxml import etree
import re
import os
host = '目标网站host'
headers = { 

'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36'
}
sem = asyncio.Semaphore(20)
async def RealDownLoad(img_url, filename):
with(await sem):
async with aiohttp.ClientSession() as sess:
for url in img_url:
async with await sess.get(url=url['url'], headers=headers) as response:
img_bytes = await response.read()
with open('./'+filename + '/' + url['path'], 'wb') as img:
img.write(img_bytes)
print(url)
async def DownLoad(page_url, filename):
img_url = []
for page in page_url:
async with aiohttp.ClientSession() as sess:
async with await sess.get(url=page, headers=headers) as response:
page_detail = await response.text()
detail_tree = etree.HTML(page_detail)
for i in detail_tree.xpath('//*[@id="hgallery"]/img'):
img = { 
'url': i.xpath('./@src')[0], 'path': i.xpath('./@alt')[0] + '.jpg'}
img_url.append(img)
return await RealDownLoad(img_url, filename)
async def GetInDetailPage(boxes):
page_url = []
for i in range(15):
page_url.append(boxes['url'] + str(i) + ".html")
return await DownLoad(page_url, boxes['file_name'])
async def main():
tasks = []
url = '目标网站'
response = requests.get(url=url, headers=headers)
response.encoding = 'utf-8'
page_text = response.text
box_url_list = []
box_task_list = []
tree = etree.HTML(page_text)
li_list = tree.xpath("//div[@id='listdiv']//li")
for li in li_list:
box = { 
}
box_url = host + li.xpath('.//div[2]/a/@href')[0]
file_name = li.xpath('.//div[2]/a/text()')[0]
if not os.path.exists('./' + file_name):
os.mkdir(file_name)
box['url'] = box_url
box['file_name'] = file_name
box_url_list.append(box)
for boxes in box_url_list:
c = GetInDetailPage(boxes)
tasks.append(asyncio.ensure_future(c))
await asyncio.wait(tasks)
loop = asyncio.get_event_loop()
start = time.time()
loop.run_until_complete(main())
print("用时: ", time.time()-start)
exit()

在这里插入图片描述
最终版本下载了目标页面宅男女神->美女图片->秀人网 下所有妹妹的图集(20个图集), 总用时不到30秒钟.
这段代码是只爬了”目标网址”的第一页, 没加翻页的函数, 有想法的朋友可以自己加一个翻页的方法.

其实这样类型的爬虫用scrapy框架中的crawl spider是最好的, 想看的朋友可以给我留言.

总结

写的不是很好, 包括对asyncio库的运用, 整体代码的封装等等, 后面还会持续更新爬虫方面的实例, 希望能给也在学习爬虫相关知识的朋友一点点启发, 喜欢的朋友也请点个赞吧,谢谢!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/136799.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • 笔记本没有声音,f1一直亮_为什么笔记本按f1不静音

    笔记本没有声音,f1一直亮_为什么笔记本按f1不静音某个平凡的晚上,博主正准备听会儿音乐却发现怎么也打不开声音,通知键盘左上的F1健一直亮着。几经搜寻终找到如下解决方案:win+r出对话框,然后输出services.msc后会出现如下的界面,然后找到LenovoHotkeyClientLoader,点进去选择重启然后再按F1灯就灭了,还能外放了以上只是经过本人试验的有效方法之一,大家可在遇到类似情况时试一试,有其他更好方法的朋友欢迎在评论区补充。…

  • M语言编程_所有编程语言大全

    M语言编程_所有编程语言大全一直对技术有很强的兴趣,终于,决定要写自己的语言(m语言)。那就先从最简单的开始:解释执行器。一套完整的语言包含的肯定不止解释执行器了,还要有编译器和IDE,也就还要有语法高亮、智能提示等,不过还没

  • navicate premium 15 激活码【2021免费激活】「建议收藏」

    (navicate premium 15 激活码)好多小伙伴总是说激活码老是失效,太麻烦,关注/收藏全栈君太难教程,2021永久激活的方法等着你。IntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,下面是详细链接哦~https://javaforall.cn/100143.htmlMLZPB5EL5Q-eyJsaWNlbnNlSW…

  • 巩固知识体系!淘宝秒杀脚本java

    巩固知识体系!淘宝秒杀脚本java一轮:第一轮面试官(是一位女性,喜欢钻研一些细节性的东西)自我介绍1、HashMap和ArrayList的原理解释下。2、Netty原理介绍下。3.了解过NIO,BIO,AIO么?介绍下异同,代码中如何使用?4.分布式锁用过么?用什么函数?什么使用场景?5.能介绍下垃圾回收机制么?6.redis的数据结构介绍下。项目中用过哪些?什么场景7.幂等性是什么?如何保障?8.交易系统中的数据一致性咋保障?二轮:第二轮面试官(年龄看起来不大,人很好说话,给人一种很舒服的感觉)

  • 关于ie下阻止ActiveX控件

    关于ie下阻止ActiveX控件
    最近,公司的项目上有个部分要用到ActiveX控件。可是在访问的时候,就会弹出”Internetexplorer已经阻止站点用不安全方式使用ActiveX控件”一句。查了好多资料,除了更改ie的安全设置,没有其他方法。
    更改ie安全设置,需要更改的几个地方:
    首先,Internet选项–>安全
    1.选中Internet –“自定义级别”– “ActiveX控件和插件 “–“对未标记为可安全执行脚本的ActiveX控件初始化并执行脚本”(启用

  • Java的运行机制(一)

    Java的运行机制(一)前言:还是那句话,第一、凡是涉及到概念性内容的时候,我都会到官网去确认内容的真实性!第二、我喜欢偏向于原理学习。在java介绍里面,我认为知道这是一门完全面向对象的语言就足够了。我的导师说C++是认为程序员是很强大的,开放了所有的功能权限;Java是认为程序员不是那么全能的,有些危险的操作,不会让你执行。不知道您是否也这么认为呢?目录一、类的结构二、运行机制1、编译方式…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号