【python爬虫】aiohttp模块的基本使用样例

引出:(下列代码无法异步)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import asyncio
import requests
import time

urls = [
'http://127.0.0.1:5000/lab',
'http://127.0.0.1:5000/blob',
'http://127.0.0.1:5000/count'
]


async def get_page(url):
print("正在下载", url)
# request发起的请求时同步的,所以无法异步,那么我们必须使用异步的网络请求 aiohttp:基于异步的网络请求
response = requests.get(url)
print(response.text)
print(url, "下载完毕")


if __name__ == "__main__":
tasks = []
for url in urls:
# 拿到任务对象
c = get_page(url)
# 创建task
task = asyncio.ensure_future(c)
tasks.append(task)
start = time.time()
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait(tasks))
print("%.2f second" % (time.time() - start))

前文提到asyncio中不能有同步长耗时请求(会让异步失效),所以必须使用一个异步的http请求框架

1
pip install aiohttp

示例代码: 网站代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
from flask import Flask
# 构造app Flask对象 以__name__作为参数
app = Flask(__name__)
import time

# 通过app.route()指定路由
@app.route("/blob")
def blob():
time.sleep(2)
return 'blob'


@app.route("/lab")
def lab():
time.sleep(2)
return 'lab'


@app.route("/count")
def count():
time.sleep(2)
return 'count'


if __name__ == "__main__":
app.run()

request发起的请求时同步的,所以无法异步,那么我们必须使用异步的网络请求 aiohttp:基于异步的网络请求 创建aiohttp.ClientSession对象(必须通过async with aiohttp.ClientSession()方法创建)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
import asyncio
import time
# 安装: pip install aiohttp
# 使用该模块中的ClientSession发送请求
import aiohttp

urls = [
'http://127.0.0.1:5000/lab',
'http://127.0.0.1:5000/blob',
'http://127.0.0.1:5000/count'
]


async def get_page(url):
print("正在下载", url)
# request发起的请求时同步的,所以无法异步,那么我们必须使用异步的网络请求 aiohttp:基于异步的网络请求
# 创建aiohttp.ClientSession对象(必须通过async with aiohttp.ClientSession()方法创建)
async with aiohttp.ClientSession() as session:
# 通过await挂起
# get/post都可以,用法与requests一致
# headers也是一样的编写方法 params/data
# 但是proxies被proxy取代,且只能用一个字符串'http://ip:port'
# 必须使用async with await session.get() as response获取响应对象
async with await session.get(url=url) as response:
# text()返回的是字符串
# read()返回的是二进制响应数据
# json()返回的是json数据

# 在获取响应数据之前一定要记得用await挂起
page_text = await response.text()
print(page_text)
print(url, "下载完毕")


if __name__ == "__main__":
tasks = []
# 批量创建任务future
for url in urls:
# 拿到任务对象
c = get_page(url)
# 创建task
task = asyncio.ensure_future(c)
tasks.append(task)
# 记录用时
start = time.time()
# 获取事件循环对象
loop = asyncio.get_event_loop()
# 包装事件循环任务并将其添加到事件循环事件
loop.run_until_complete(asyncio.wait(tasks))
print("%.2f second" % (time.time() - start))