python grequest模块使用备忘录

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

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

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

基于此,就找到了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模块在遇到请求超时、异常时返回的Response是None的。
这个就有点坑了,因为我有几千个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
...
用起来就很简单了
```python
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)
posted @ 2019-11-19 13:53  seozed  阅读(1649)  评论(0编辑  收藏  举报