python grequest模块使用备忘录

文章讲述了作者在处理大量链接检查时,选择使用grequests进行异步IO,避免了多线程的复杂性和性能问题。然而,grequests的map模块在请求失败时返回None,作者为此自定义了ggrequests模块,增加了对超时和异常的处理功能。
摘要由CSDN通过智能技术生成

手里上有一批链接,需要检查他们是否已经被删除。本来是想用多线程的,但是考虑了下一个是实现起来稍繁琐。而且性能不理想,单机基本超过10线程基本上就没有太多增益了。

所以考虑了下,还是决定用异步IO。

在使用grequest之前用的是aiohttp来处理的,但是这个库蛋疼的时,每个延时请求前都要添加await,导致代码里一堆awaitasync

基于此,就找到了grequest。

写代码的方式还是以同步的思路来写的,只不过grequest会在底层帮你把代码转换成异步IO。

代码如下

import grequests

urls = [
    'http://www.baidu.com',
    'http://www.qq.com',
    'http://www.163.com',
    'http://www.zhihu.com',
    'http://www.toutiao.com',
    'http://www.douban.com'
]

>>> rs = (grequests.get(u) for u in urls)
>>> grequests.map(rs)
[<Response [200]>, <Response [200]>, <Response [200]>, <Response [200]>, None, <Response [200]>]

>>> def exception_handler(request, exception):
...    print("Request failed")

>>> reqs = [
...    grequests.get('http://httpbin.org/delay/1', timeout=0.001),
...    grequests.get('http://fakedomain/'),
...    grequests.get('http://httpbin.org/status/500')]
>>> grequests.map(reqs, exception_handler=exception_handler)
Request failed
Request failed
[None, None, <Response [500]>]

但是,这里有个问题。就是grequest的map模块在遇到请求超时、异常时返回的ResponseNone的。
这个就有点坑了,因为我有几千个URL,而且还涉及不同的网站。其中有些网站可能已经关站,或者由于网速问题,超时了。

所以,这里把map模块做了一下调整。

直接把grequests模块的源码复制一份,然后增加以下模块。

ggrequests.py

...
def extract_item(request):
    """
    提取request的内容
    """
    item = dict()
    item['url'] = request.url
    item['text'] = request.response.text or ''
    item['status_code'] = request.response.status_code or 0
    return item

def map(requests, stream=False, size=None, exception_handler=None, gtimeout=None):
    """将Request列表转换为Response。

     :param 请求:Request对象的集合。
     :param stream:如果为True,则内容不会立即下载。
     :param size:指定单次请求的数量。 如果为空,则没有限制。
     :param exception_handler:回调函数,当发生异常时调用。 参数:请求,例外
     :param gtimeout:几秒钟内Gevent连接超时。 (注意:与请求超时无关)
    """

    requests = list(requests)

    pool = Pool(size) if size else None
    jobs = [send(r, pool, stream=stream) for r in requests]
    gevent.joinall(jobs, timeout=gtimeout)

    ret = []
    # 这里就是请求成功后处理Response的地方
    for request in requests:
        if request.response is not None:
            ret.append(extract_item(request))
        elif exception_handler and hasattr(request, 'exception'):
            ret.append(exception_handler(request, request.exception))
        else:
            ret.append(extract_item(request))

    return ret
...

用起来就很简单了

import ggrequests as grequests

urls = [
    'http://www.baidu.com',
    'http://www.qq.com',
    'http://www.163.com',
    'http://www.zhihu.com',
    'http://www.toutiao.com',
    'http://www.douban.com'
]
rs = (grequests.get(u) for u in urls)
response_list = grequests.map(rs, gtimeout=10)
for response in response_list:
    print(response)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值