钢铁知识库,一个学习python爬虫、数据分析的知识库。人生苦短,快用python。
之前我们使用requests库爬取某个站点的时候,每发出一个请求,程序必须等待网站返回响应才能接着运行,而在整个爬虫过程中,整个爬虫程序是一直在等待的,实际上没有做任何事情。
像这种占用磁盘/内存IO、网络IO的任务,大部分时间是CPU在等待的操作,就叫IO密集型任务。对于这种情况有没有优化方案呢,当然有,那就是使用aiohttp库实现异步爬虫。
aiohttp是什么
我们在使用requests请求时,只能等一个请求先出去再回来,才会发送下一个请求。明显效率不高阿,这时候如果换成异步请求的方式,就不会有这个等待。一个请求发出去,不管这个请求什么时间响应,程序通过await挂起协程对象后直接进行下一个请求。
解决方法就是通过 aiohttp + asyncio,什么是aiohttp?一个基于 asyncio 的异步 HTTP 网络模块,可用于实现异步爬虫,速度明显快于 requests 的同步爬虫。
requests和aiohttp区别
区别就是一个同步一个是异步。话不多说直接上代码看效果。
安装aiohttp
pip install aiohttp
- requests同步示例:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# author: 钢铁知识库
import time
import requests
# 同步请求
def main():
start = time.time()
for i in range(5):
res = requests.get('http://httpbin.org/delay/2')
print(f'当前时间:{datetime.datetime.now()}, status_code = {res.status_code}')
print(f'requests同步耗时:{time.time() - start}')
if __name__ == '__main__':
main()
'''
当前时间:2022-09-05 15:44:51.991685, status_code = 200
当前时间:2022-09-05 15:44:54.528918, status_code = 200
当前时间:2022-09-05 15:44:57.057373, status_code = 200
当前时间:2022-09-05 15:44:59.643119, status_code = 200
当前时间:2022-09-05 15:45:02.167362, status_code = 200
requests同步耗时:12.785893440246582
'''
可以看到5次请求总共用12.7秒,再来看同样的请求异步多少时间。
- aiohttp异步示例:
#!/usr/bin/env python
# file: day6-9同步和异步.py
# author: 钢铁知识库
import asyncio
import time
import aiohttp
async def async_http():
# 声明一个支持异步的上下文管理器
async with aiohttp.ClientSession() as session:
res = await session.get('http://httpbin.org/delay/2')
print(f'当前时间:{datetime.datetime.now()}, status_code = {res.status}')
tasks = [async_http() for _ in range(5)]
start = time.time()
# Python 3.7 及以后,不需要显式声明事件循环,可以使用 asyncio.run()来代替最后的启动操作
asyncio.run(asyncio.wait(tasks))
print(f'aiohttp异步耗时:{time.time() - start}')
'''
当前时间:2022-09-05 15:42:32.363966, status_code = 200
当前时间:2022-09-05 15:42:32.366957, status_code = 200
当前时间:2022-09-05 15:42:32.374973, status_code = 200
当前时间:2022-09-05 15:42:32.384909, status_code = 200
当前时间:2022-09-05 15:42:32.390318, status_code = 200
aiohttp异步耗时:2.5826876163482666
'''
两次对比可以看到执行过程,时间一个是顺序执行,一个是同时执行。这就是同步和异步的区别。
aiohttp使用介绍
接下来我们会详细介绍aiohttp库的用法和爬取实战。aiohttp 是一个支持异步请求的库,它和 asyncio 配合使用,可以使我们非常方便地实现异步请求操作。asyncio模块,其内部实现了对TCP、UDP、SSL协议的异步操作,但是对于HTTP请求,就需要aiohttp实现了。
aiohttp分为两部分,一部分是Client,一部分是Server。下面来说说aiohttp客户端部分的用法。
基本实例
先写一个简单的案例
#!/usr/bin/env python
# -*- codi