使用gevent库+queue模块实现多协程爬虫,提高爬取效率!

本文解释了协程如何通过任务切换优化等待时间,通过爬虫示例对比gevent库与普通方式的效率,并展示了如何使用Queue和gevent.spawn实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

协程是干什么的?

协程可以提高任务执行的效率!它的执行原理就是当计算机在执行某个任务的时候,如果需要等待(比如爬取网站需要等待网站响应等),可以先去执行其他的任务,等等待结束(网站响应)时,再回来继续任务。本质上就是减少等待的时间,提高爬取的效率。

代码解析:

使用简单代码讲解

接下来来看看这么实现它,先用一个比较简单的代码来看看:

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-

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Xin学数据

为你点亮一盏灯,愿你前进无阻。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值