协程是干什么的?
协程可以提高任务执行的效率!它的执行原理就是当计算机在执行某个任务的时候,如果需要等待(比如爬取网站需要等待网站响应等),可以先去执行其他的任务,等等待结束(网站响应)时,再回来继续任务。本质上就是减少等待的时间,提高爬取的效率。
代码解析:
使用简单代码讲解
接下来来看看这么实现它,先用一个比较简单的代码来看看:
from gevent import monkey
monkey.patch_all()
import gevent
from gevent.queue import Queue
list = [1,2,3,4,5,6]
work = Queue()
for i in list:
work.put_nowait(i)
def crawler():
while not work.empty():
num = work.get_nowait()
print(num,work.qsize())
tasks_list = [ ]
for x in range(2):
task = gevent.spawn(crawler)
tasks_list.append(task)
gevent.joinall(tasks_list)
基本知识点讲解:
第1行:从gevent库里导入monkey模块;
第2行:monkey.patch_all()能把程序变成协作式运行;
第3行:调用gevent库;
第4行:调用queue模块中的Queue类;
第7行:实例化Queue类,创建一个队列;
第8行:遍历列表中的元素;
第9行:Queue.put_nowait()方法是把列表中的元素依次加入队列中;
第11~14行:创建crawler函数
- Queue.empty()判断队列是否为空,空返回True;
- Queue.get_nowait()从队列中取值(即第9行添加的值);
- Queue.qsize()返回队列的长度。
第16行:创建空列表tasks_list,用于后面添加任务;
第17~19:创建2个协程,创建任务并把任务添加到任务列表中
- gevent.spawn(crawler)创建任务,这里传入的是函数名;
第20行:gevent.joinall(tasks_list)执行任务。
使用爬虫代码测试
接下来通过爬取8个网站来做一下测试:
from gevent import monkey
monkey.patch_all()
import gevent,requests
from gevent.queue import Queue
list = ['https://www.baidu.com/',
'https://www.sina.com.cn/',
'http://www.sohu.com/',
'https://www.qq.com/',
'https://www.163.com/',
'http://www.iqiyi.com/',
'https://www.tmall.com/',
'http://www.ifeng.com/']
work = Queue()
for url in list:
work.put_nowait(url)
def crawler():
while not work.empty():
url = work.get_nowait()
res = requests.get(url)
print(url,work.qsize(),res.status_code) # 打印网址,队列长度,请求返回情况
tasks_list = []
for x in range(2):
task = gevent.spawn(crawler)
tasks_list.append(task)
gevent.joinall(tasks_list)
那么,怎么看效率提高了呢?
3
2
1
0 揭晓答案:
可以调用time模块的time()方法来计算,代码如下:
from gevent import monkey
monkey.patch_all()
import gevent,requests,time
from gevent.queue import Queue
start = time.time() # 获取开始运行时间戮
list = ['https://www.baidu.com/',
'https://www.sina.com.cn/',
'http://www.sohu.com/',
'https://www.qq.com/',
'https://www.163.com/',
'http://www.iqiyi.com/',
'https://www.tmall.com/',
'http://www.ifeng.com/']
work = Queue()
for url in list:
work.put_nowait(url)
def crawler():
while not work.empty():
url = work.get_nowait()
res = requests.get(url)
print(url, work.qsize(), res.status_code)
tasks_list = []
for x in range(2):
task = gevent.spawn(crawler)
tasks_list.append(task)
gevent.joinall(tasks_list)
end = time.time() # 获取运行结束时间戮
print('运行耗时'+str(end-start)+'秒') # 相减即可获取运行时间
运行结果如下:
去掉gevent库,测试一下运行时间:
import requests,time
start = time.time()
def crawler(url):
res = requests.get(url)
print(url, res.status_code)
list = ['https://www.baidu.com/',
'https://www.sina.com.cn/',
'http://www.sohu.com/',
'https://www.qq.com/',
'https://www.163.com/',
'http://www.iqiyi.com/',
'https://www.tmall.com/',
'http://www.ifeng.com/']
for url in list:
crawler(url)
end = time.time()
print('运行耗时'+str(end-start)+'秒')
运行结果如下:
从结果查看:
有gevent库+queue模块时运行只需要1.96秒左右;
没有gevent库+queue模块时运行需要4.02秒左右。
当然,这不代表使用gevent库+queue模块速度可以减少一半,只能说明使用gevent库+queue模块能够很好的提高效率!
注意:当crawler()函数有参数的时候,gevent.spawn()这个函数传入的参数为gevent.spawn(函数名,参数)。传函数名即可,不用加括号(加括号变成了调用函数,传入的是函数的返回值),然后函数的参数,跟在后面,spawn()会把参数传进函数进行调用。
如果crawler()函数没有有参数,则直接使用gevent.spawn(函数名)即可。
-END-
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/66985.html