了解请求与问候

时间:2017-09-13 19:30:37

标签: python python-3.x python-requests httprequest grequests

我正在使用一个基本如下的过程:

  1. 拿一些网址列表。
  2. 从每个对象中获取Response个对象。
  3. 从每个Response的text创建一个BeautifulSoup对象。
  4. 从BeautifulSoup对象中提取某个标签的文本。
  5. 根据我的理解,这似乎是grequests的理想选择:

      

    GRequests允许您使用带有Gevent的请求来进行异步   HTTP请求很容易。

    但是,这两个进程(一个有请求,一个有grequests)似乎给我带来了不同的结果,grequest中的一些请求返回None而不是响应。

    使用请求

    import requests
    
    tickers = [
        'A', 'AAL', 'AAP', 'AAPL', 'ABBV', 'ABC', 'ABT', 'ACN', 'ADBE', 'ADI', 
        'ADM',  'ADP', 'ADS', 'ADSK', 'AEE', 'AEP', 'AES', 'AET', 'AFL', 'AGN', 
        'AIG', 'AIV', 'AIZ', 'AJG', 'AKAM', 'ALB', 'ALGN', 'ALK', 'ALL', 'ALLE',
        ]
    
    BASE = 'https://finance.google.com/finance?q={}'
    
    rs = (requests.get(u) for u in [BASE.format(t) for t in tickers])
    rs = list(rs)
    
    rs
    # [<Response [200]>,
     # <Response [200]>,
     # <Response [200]>,
     # <Response [200]>,
     # <Response [200]>,
     # <Response [200]>,
     # ...
     # <Response [200]>]
    
    # All are okay (status_code == 200)
    

    使用grequests

    # Restarted my interpreter and redefined `tickers` and `BASE`
    import grequests
    
    rs = (grequests.get(u) for u in [BASE.format(t) for t in tickers])
    rs = grequests.map(rs)
    
    rs
    # [None,
     # <Response [200]>,
     # None,
     # None,
     # None,
     # None,
     # None,
     # None,
     # None,
     # None,
     # None,
     # None,
     # None,
     # None,
     # None,
     # None,
     # None,
     # None,
     # <Response [200]>,
     # <Response [200]>,
     # <Response [200]>,
     # <Response [200]>,
     # <Response [200]>,
     # <Response [200]>,
     # <Response [200]>,
     # <Response [200]>,
     # <Response [200]>,
     # <Response [200]>,
     # <Response [200]>,
     # <Response [200]>]
    

    为什么结果有差异?

    更新:我可以按如下方式打印例外类型。相关讨论here但我不知道发生了什么。

    def exception_handler(request, exception):
        print(exception)
    
    rs = grequests.map(rs, exception_handler=exception_handler)
    
    # ("bad handshake: SysCallError(-1, 'Unexpected EOF')",)
    # ("bad handshake: SysCallError(-1, 'Unexpected EOF')",)
    # ("bad handshake: SysCallError(-1, 'Unexpected EOF')",)
    # ("bad handshake: SysCallError(-1, 'Unexpected EOF')",)
    # ("bad handshake: SysCallError(-1, 'Unexpected EOF')",)
    # ("bad handshake: SysCallError(-1, 'Unexpected EOF')",)
    # ("bad handshake: SysCallError(-1, 'Unexpected EOF')",)
    # ("bad handshake: SysCallError(-1, 'Unexpected EOF')",)
    # ("bad handshake: SysCallError(-1, 'Unexpected EOF')",)
    # ("bad handshake: SysCallError(-1, 'Unexpected EOF')",)
    # ("bad handshake: SysCallError(-1, 'Unexpected EOF')",)
    # ("bad handshake: SysCallError(-1, 'Unexpected EOF')",)
    # ("bad handshake: SysCallError(-1, 'Unexpected EOF')",)
    # ("bad handshake: SysCallError(-1, 'Unexpected EOF')",)
    # ("bad handshake: SysCallError(-1, 'Unexpected EOF')",)
    

    系统/版本信息

    • 要求:2.18.4
    • grequests:0.3.0
    • Python:3.6.3
    • urllib3:1.22
    • pyopenssl:17.2.0
    • All via Anaconda
    • 系统:Mac OSX HS&amp; Windows 10,build 10.0.16299

2 个答案:

答案 0 :(得分:5)

您只是发送请求太快。由于grequests是异步库,所有这些请求几乎都是同时发送的。它们太多了。

您只需要grequests.map(rs, size=your_choice)限制并发任务,我已经测试了grequests.map(rs, size=10)并且效果很好。

答案 1 :(得分:4)

我不知道.map()观察到行为的确切原因。但是,使用.imap()函数和size=1总是会在几分钟的测试中返回“响应200”。这是代码snipet:

rs = (grequests.get(u) for u in [BASE.format(t) for t in tickers])
rsm_iterator = grequests.imap(rs, exception_handler=exception_handler, size=1)
rsm_list = [r for r in rsm_iterator]
print(rsm_list)

如果您不想在完成答案之前等待所有请求完成,您可以这样做:

rs = (grequests.get(u) for u in [BASE.format(t) for t in tickers])
rsm_iterator = grequests.imap(rs, exception_handler=exception_handler, size=1)
for r in rsm_iterator:
    print(r)