Python爬虫入门教程 7-100 蜂鸟网图片爬取之二
简介
今天玩点新鲜的,使用一个新库 aiohttp
,利用它提高咱爬虫的爬取速度。
安装模块常规套路
pip install aiohttp
运行之后等待,安装完毕,想要深造,那么官方文档必备 :
接下来就可以开始写代码了。
我们要爬取的页面,这一次选取的是
http://bbs.fengniao.com/forum/forum_101_1_lastpost.html
打开页面,我们很容易就获取到了页码
好久没有这么方便的看到页码了。
尝试用
aiohttp
访问这个页面吧,模块的引入,没有什么特殊的,采用 import
即可如果我们需要 使用
asyncio + aiohttp
异步io 编写爬虫,那么需要注意,你需要异步的方法前面加上async
接下来,先尝试去获取一下上面那个地址的网页源码。
代码中,先声明一个fetch_img_url的函数,同时携带一个参数,这个参数也可以直接写死。
with
上下文不在提示,自行搜索相关资料即可 (`・ω・´)
aiohttp.clientsession() as session:
创建一个session
对象,然后用该session
对象去打开网页。session
可以进行多项操作,比如post
, get
, put
等
代码中 await response.text()
等待网页数据返回
asyncio.get_event_loop
创建线程,run_until_complete
方法负责安排执行 tasks
中的任务。tasks
可以为单独的函数,也可以是列表。
import aiohttp import asyncio async def fetch_img_url(num): url = f'http://bbs.fengniao.com/forum/forum_101_{num}_lastpost.html' # 字符串拼接 # 或者直接写成 url = 'http://bbs.fengniao.com/forum/forum_101_1_lastpost.html' print(url) headers = { 'user-agent': 'mozilla/5.0 (windows nt 10.0; wow64) applewebkit/537.36 (khtml, like gecko) chrome/63.0.3239.26 safari/537.36 core/1.63.6726.400 qqbrowser/10.2.2265.400', } async with aiohttp.clientsession() as session: # 获取轮播图地址 async with session.get(url,headers=headers) as response: try: html = await response.text() # 获取到网页源码 print(html) except exception as e: print("基本错误") print(e) # 这部分你可以直接临摹 loop = asyncio.get_event_loop() tasks = asyncio.ensure_future(fetch_img_url(1)) results = loop.run_until_complete(tasks)
上面代码最后一部分也可以写成
loop = asyncio.get_event_loop() tasks = [fetch_img_url(1)] results = loop.run_until_complete(asyncio.wait(tasks))
好了,如果你已经成果的获取到了源码,那么距离最终的目的就差那么一丢丢了。
修改代码为批量获取10页。
只需要修改tasks
即可,在此运行,看到如下结果
tasks = [fetch_img_url(num) for num in range(1, 10)]
下面的一系列操作和上一篇博客非常类似,找规律。
随便打开一个页面
http://bbs.fengniao.com/forum/forum_101_4_lastpost.html
点击一张图片,进入内页,在点击内页的一张图片,进入到一个轮播页面
再次点击进入图片播放页面
最后我们在图片播放页面,找到源码中发现了所有的图片链接,那么问题出来了,如何从上面的第一个链接,转变成轮播图的链接???
下面的源码是在 http://bbs.fengniao.com/forum/pic/slide_101_10408464_89383854.html
右键查看源码。
继续分析吧~~~~ ヾ(=・ω・=)o
http://bbs.fengniao.com/forum/forum_101_4_lastpost.html 转变成下面的链接? http://bbs.fengniao.com/forum/pic/slide_101_10408464_89383854.html
继续看第一个链接,我们使用f12开发者工具,去抓取一个图片看看。
图片中标黄色框的位置,发现了我们想要的数字,那么好了,我们只需要通过正则表达式把他们匹配出来就好了。
代码在下面####
的位置,需要注意的是,我采用的原始的正则匹配,在编写正则表达式的过程中,我发现一步竟然没有完整匹配,只能分成两个步骤了,你可以看一下具体的细节o(╥﹏╥)o
- 查找所有的图片
<div class="piclist">
- 获取我们想要的两部分数字
async def fetch_img_url(num): url = f'http://bbs.fengniao.com/forum/forum_101_{num}_lastpost.html' print(url) headers = { 'user-agent': 'mozilla/5.0 (windows nt 10.0; wow64) applewebkit/537.36 (khtml, like gecko) chrome/63.0.3239.26 safari/537.36 core/1.63.6726.400 qqbrowser/10.2.2265.400', } async with aiohttp.clientsession() as session: # 获取轮播图地址 async with session.get(url,headers=headers) as response: try: ############################################### url_format = "http://bbs.fengniao.com/forum/pic/slide_101_{0}_{1}.html" html = await response.text() # 获取到网页源码 pattern = re.compile('<div class="piclist">([\s\s.]*?)</div>') first_match = pattern.findall(html) href_pattern = re.compile('href="/forum/(\d+?)_p(\d+?)\.html') urls = [url_format.format(href_pattern.search(url).group(1), href_pattern.search(url).group(2)) for url in first_match] ############################################## except exception as e: print("基本错误") print(e)
代码完成,我们已经获取到,我们想要的url了,下面继续读取url内部信息,然后匹配我们想要的图片链接
async def fetch_img_url(num): # 去抄上面的代码 async with aiohttp.clientsession() as session: # 获取轮播图地址 async with session.get(url,headers=headers) as response: try: #去抄上面的代码去吧 ################################################################ for img_slider in urls: try: async with session.get(img_slider, headers=headers) as slider: slider_html = await slider.text() # 获取到网页源码 try: pic_list_pattern = re.compile('var piclist = \[(.*)?\];') pic_list = "[{}]".format(pic_list_pattern.search(slider_html).group(1)) pic_json = json.loads(pic_list) # 图片列表已经拿到 print(pic_json) except exception as e: print("代码调试错误") print(pic_list) print("*"*100) print(e) except exception as e: print("获取图片列表错误") print(img_slider) print(e) continue ################################################################ print("{}已经操作完毕".format(url)) except exception as e: print("基本错误") print(e)
图片最终的json已经拿到,最后一步,下载图片,当当当~~~~,一顿迅猛的操作之后,图片就拿下来了
async def fetch_img_url(num): # 代码去上面找 async with aiohttp.clientsession() as session: # 获取轮播图地址 async with session.get(url,headers=headers) as response: try: # 代码去上面找 for img_slider in urls: try: async with session.get(img_slider, headers=headers) as slider: # 代码去上面找 ########################################################## for img in pic_json: try: img = img["downloadpic"] async with session.get(img, headers=headers) as img_res: imgcode = await img_res.read() # 图片读取 with open("images/{}".format(img.split('/')[-1]), 'wb') as f: f.write(imgcode) f.close() except exception as e: print("图片下载错误") print(e) continue ############################################################### except exception as e: print("获取图片列表错误") print(img_slider) print(e) continue print("{}已经操作完毕".format(url)) except exception as e: print("基本错误") print(e)
图片会在你提前写好的images
文件夹里面快速的生成
tasks
最多可以开1024协程,但是建议你开100个就ok了,太多并发,人家服务器吃不消。
以上操作执行完毕,在添加一些细节,比如保存到指定文件夹,就ok了。
推荐阅读
-
Python爬虫入门教程 6-100 蜂鸟网图片爬取之一
-
Python爬虫入门教程 64-100 反爬教科书级别的网站-汽车之家,字体反爬之二
-
Python新手爬虫二:爬取搜狗图片(动态)
-
Python爬虫入门教程 7-100 蜂鸟网图片爬取之二
-
Python爬虫入门教程 26-100 知乎文章图片爬取器之二
-
Python爬虫入门教程 25-100 知乎文章图片爬取器之一
-
Python爬虫入门教程 8-100 蜂鸟网图片爬取之三
-
Python爬虫入门教程 64-100 反爬教科书级别的网站-汽车之家,字体反爬之二
-
python爬虫练习(二) 使用selenium +浏览器Firefox驱动爬取美女图片
-
Python新手爬虫二:爬取搜狗图片(动态)