在我们写普通的爬虫程序时,经常会用到requests库用以请求网页并获得服务器响应。而在协程中,由于requests库提供的相关方法不是可等待对象(awaitable),使得无法放在await后面,因此无法使用requests库在协程程序中实现请求。官方专门提供了一个aiohttp库,用来实现异步网页请求等功能,就是异步版的requests库。
1, aiohttp基本用法
在官方文档中,推荐使用ClientSession()
函数来调用网页请求等相关方法。
首先,我们需要引入aiohttp
模块。然后,我们在协程中使用ClientSession()
的get()
或request()
方法来请求网页。(其中async with
是异步上下文管理器,其封装了异步实现等功能)
使用requests库发起get请求示例如下:
def hello(url):
resp = requests.get(url)
return resp.text()
url = "http://httpbin.org/get"
print(hello(url))
使用aiohttp库实现则相对复杂的多:
async def hello(url):
async with ClientSession() as session:
async with session.get(url) as resp:
print(resp.status)
resp = await resp.text()
print(resp)
loop = asyncio.get_event_loop()
url = "http://httpbin.org/get"
loop.run_until_complete(hello(url))
步骤如下:
(1)使用async以及await关键字将函数异步化。
(2)使用ClientSession作为主要的接口发起请求。ClientSession允许在多个请求之间保存cookie以及相关对象信息。Session(会话)在使用完毕之后需要关闭,关闭Session是另一个异步操作,所以每次都需要使用async with关键字。
建立了客户端session,可以用它发起请求。这里是又一个异步操作的开始。上下文管理器的with语句可以保证在处理session的时候,总是能正确的关闭它。
(3)在hello()中实际上有两个异步操作:首先异步获取响应,然后异步读取响应的内容。
(4)让程序正常的跑起来,需要将他们加入事件循环中。所以你需要创建一个asyncio loop的实例,然后将任务加入其中。
有get请求当然有post请求,并且post请求也是一个协程:
session.post('http://httpbin.org/post', data=b'data')
除此以外,aiohttp还支持以下方法:
session.put('http://httpbin.org/put', data=b'data')
session.delete('http://httpbin.org/delete')
session.head('http://httpbin.org/get')
session.options('http://httpbin.org/get')
session.patch('http://httpbin.org/patch', data=b'data')
注意:
不要为每次的连接都创建一次session,一般情况下只需要创建一个session,然后使用这个session执行所有的请求。
每个session对象,内部包含了一个连接池,并且将会保持连接和连接复用(默认开启)可以加快整体的性能。
2,aiohttp高级功能
2.1 URL传参数
我们经常需要通过 get 在url中传递一些参数,参数将会作为url问号后面的一部分发给服务器。在aiohttp的请求中,允许以dict的形式来表示问号后的参数。举个例子,如果你想传递 key1=value1 key2=value2 到 httpbin.org/get 我们有以下几种实现方式。
方式一:使用字典传递参数
from aiohttp import ClientSession
params = {'key1': 'value1', 'key2': 'value2'}
async def http_request():
async with ClientSession() as session: ##获取session