了解请求与 grequests
Understanding requests versus grequests
我正在处理一个基本如下的流程:
- 获取一些 url 列表。
- 从每个对象中获取一个
Response
对象。
- 从每个响应的
text
创建一个 BeautifulSoup 对象。
- 从那个 BeautifulSoup 对象中提取某个标签的文本。
据我了解,这似乎很适合 grequests:
GRequests allows you to use Requests with Gevent to make asynchronous
HTTP Requests easily.
但是,这两个进程(一个有请求,一个有 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')",)
System/version 信息
- 请求:2.18.4
- grequests: 0.3.0
- Python: 3.6.3
- urllib3: 1.22
- pyopenssl: 17.2.0
- 全部通过 Anaconda
- 系统:Mac OSX HS 和 Windows 10,build 10.0.16299
都存在同样的问题
我不知道 .map()
观察到的行为的确切原因。但是,在我的几分钟测试中,使用带有 size=1
的 .imap()
函数总是返回 'Response 200'。这是代码片段:
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)
您发送请求的速度太快了。由于 grequests
是一个异步库,所有这些请求几乎都是同时发送的。他们太多了。
你只需要限制并发任务grequests.map(rs, size=your_choice)
,我测试过grequests.map(rs, size=10)
,效果很好。
我正在处理一个基本如下的流程:
- 获取一些 url 列表。
- 从每个对象中获取一个
Response
对象。 - 从每个响应的
text
创建一个 BeautifulSoup 对象。 - 从那个 BeautifulSoup 对象中提取某个标签的文本。
据我了解,这似乎很适合 grequests:
GRequests allows you to use Requests with Gevent to make asynchronous HTTP Requests easily.
但是,这两个进程(一个有请求,一个有 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')",)
System/version 信息
- 请求:2.18.4
- grequests: 0.3.0
- Python: 3.6.3
- urllib3: 1.22
- pyopenssl: 17.2.0
- 全部通过 Anaconda
- 系统:Mac OSX HS 和 Windows 10,build 10.0.16299 都存在同样的问题
我不知道 .map()
观察到的行为的确切原因。但是,在我的几分钟测试中,使用带有 size=1
的 .imap()
函数总是返回 'Response 200'。这是代码片段:
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)
您发送请求的速度太快了。由于 grequests
是一个异步库,所有这些请求几乎都是同时发送的。他们太多了。
你只需要限制并发任务grequests.map(rs, size=your_choice)
,我测试过grequests.map(rs, size=10)
,效果很好。