网络爬虫,这种io高密集型的应用由于大部分的时间在等待响应方面,所以CPU的使用率一直不高,速度也不快,为了解决这些问题,我们使用异步的方式来进行爬虫程序。
串行的时候,如果我们要爬一个网站,那么我们通常都是一页的内容完成了,再到下一页,这样的话,CPU的90%以上的时间用在了等待网页响应上面。
异步的话,我们可以同时发起多个请求,一个请求发起了之后就不等待这个请求的响应,马上发起第二个请求,第三个请求......
然后响应过来的内容我们再一个个进行处理,这样的效率就高了很多。
举个栗子:
首先我们搭建一个flask的服务器,故意降低它的响应速度:
from flask import Flask
import time
app = Flask(__name__)
@app.route('/')
def hello_world():
# 休眠三秒,展示异步的速度
time.sleep(3)
return 'Hello World!'
if __name__ == '__main__':
app.run(threaded=True)
首先我们使用python 3.5以上版本的async、await以及异步http请求库aiohttp:
import asyncio
import time
import aiohttp
start = time.time()
async def get(url):
async with aiohttp.ClientSession() as session:
async with session.get(url) as res:
print(res.status)
text = await res.text()
return text
async def hello():
url = "http://127.0.0.1:5000/"
print('Waiting for',url)
res = await get(url)
print('Result:',res)
loop = asyncio.get_event_loop()
tasks = [asyncio.ensure_future(hello()) for i in range(5)]
loop.run_until_complete(asyncio.wait(tasks))
end = time.time()
print('Cost time:',end-start)
使用python的第三方库:gevent也可以实现网络异步:
from gevent import monkey
# 猴子补丁一定要先打,不然就会报错
monkey.patch_all()
import gevent
import requests
import time
def get(url):
print("Get from: ",url)
r = requests.session()
res = r.get(url)
print(res.status_code,url,res.text)
def synchronous_times(url):
start = time.time()
for i in range(5):
get(url)
end = time.time()
print("同步执行的时间:", start-end)
def asynchronous_times(url):
start = time.time()
gevent.joinall([gevent.spawn(get,url) for i in range(5)])
end = time.time()
print("异步执行的时间:", start-end)
synchronous_times("http://127.0.0.1:5000/")
asynchronous_times("http://127.0.0.1:5000/")
以上就使用aiohttp、genvent实现了异步的网络请求。
网友评论