持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第2天,点击查看活动详情 朱颜渐老,白发知多少.
又到了每天学习写文章的时候了,又搬出来崔老师的爬虫书,继续学习 要实现异步机制的爬虫,那自然和协成脱不了关系
协成的基本原理
1.引入 话说啊,有这么一个网站,我是网站 这个网站等待五秒才有结果,这是因为啊,服务器强制等了五秒才返回响应,如果我们发送一个请求,都要经过五秒或者更长时间时才能得到相应的响应时,我们的爬虫的效率就会非常低. 举个例子
import requests
import logging
import time
logging.basicConfig(level=logging.INFO,format='%(levelname)s:%(message)s')
total_number = 10
url = "https://www.httpbin.org/delay/5"
start_time = time.time()
for i in range(1,total_number):
logging.info('scraping %s',url)
response = requests.get(url)
end_time = time.time()
logging.info("total time %s",end_time - start_time)
得到的结果 如图所示
每个请求都等了5秒 仅仅十个请求就花了63秒
所以我们需要更好的解决方案.
协程实现
使用Python 3.4 以后才加入的功能 协程和 async关键字 3.5以上async已成为关键字
import asyncio
import requests
import time
start = time.time()
async def requeset():
url = "https://www.httpbin.org/delay/5"
print("wait for",url)
response = requests.get(url)
print('get response from',url,'response',response)
task = [asyncio.ensure_future(requeset()) for i in range(10)]
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait(task))
end = time.time()
print("total time %s",end - start)
来查看结果
好家伙,68秒了,代码写的猛如虎,一看自己原地杵
其实我们上面的代码依然是顺序执行了,并不是异步的,所以才会出现这种情况. 我们需要 了解一下 await 将协程挂起 await用来声明程序挂起。
比如异步程序执行到某一步时需要等待的时间很长,就将此挂起,去执行其他的异步程序。
await 后面只能跟异步程序或有__await__属性的对象,因为异步程序与一般程序不同。 aiohttp是一个为Python提供异步HTTP 客户端/服务端编程,asyncio可以实现单线程并发IO操作,其实现了TCP、UDP、SSL等协议,aiohttp就是基于asyncio实现的http框架。
import asyncio
import requests
import time
import aiohttp
start = time.time()
async def get(url):
session = aiohttp.ClientSession()
response = await session.get(url)
await response.text()
await session.close()
return response
async def requeset():
url = "http://www.httpbin.org/delay/5"
print("wait for", url)
response = await get(url)
print('get response from', url, 'response', response)
task = [asyncio.ensure_future(requeset()) for i in range(10)]
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait(task))
end = time.time()
print("total time %s", end - start)
得到结果
只有6秒了,很好我们完成了我们的期望