【发布时间】:2018-02-22 15:13:32
【问题描述】:
我正在使用一个基本上如下的流程:
- 获取一些网址列表。
- 从每个对象中获取一个
Response对象。 - 从每个响应的
text创建一个 BeautifulSoup 对象。 - 从 BeautifulSoup 对象中提取某个标签的文本。
据我了解,这似乎是grequests 的理想选择:
GRequests 允许您将 Requests 与 Gevent 一起使用以进行异步 HTTP 请求很容易。
但是,这两个进程(一个带有请求,一个带有 grequests)似乎给我带来了不同的结果,grequests 中的一些请求返回 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
- 请求:0.3.0
- Python:3.6.3
- urllib3: 1.22
- pyopenssl: 17.2.0
- 全部来自 Anaconda
- 系统:Mac OSX HS 和 Windows 10 上的相同问题,内部版本 10.0.16299
【问题讨论】:
-
如果您查看README,它表明失败的请求会导致
None。我猜当你一次发出太多未经身份验证的请求时,谷歌会生气。阅读自述文件中的更多内容描述了如何编写一个异常处理程序来告诉你发生了什么。 -
打印异常,而不是固定字符串
-
如果是系统问题,您可能需要包含更多信息,例如您的操作系统及其版本、Python 版本/构建,以及请求版本、grequests、urllib3、PyOpenSSL(如果已安装)。听起来更像是一个错误报告......
-
你可以尝试使用
grequests.map(rs, size=2)限制gevent并发 -
我在github site 上看到了这条评论:“注意:您可能应该改用 requests-threads 或 requests-futures。”此外,最后一次代码更新似乎是在 2 年前。
标签: python python-3.x python-requests httprequest grequests