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)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM