我刚刚开始学习如何使用requests
Python 中的模块从 API 获取数据。我将使用一个非常简单的 GET 请求调用此 API,但我需要执行 500,000 多次,只为每个请求传递不同的值。响应是一个 JSON 对象,我可以很容易地解析出我需要的东西。
问题是我目前这样做的方式(在for-loop
usingrequests
中)太慢了。据我了解,这种方法是发送请求,等待响应完成,然后移动到可迭代对象中的下一个请求。
为了解决这个问题,我遇到了grequest
支持异步请求的模块。使用这种方法,我希望能够同时启动许多查询,可能以 100 个左右的批次进行。理想情况下,这将使我能够更快地通过我的大型迭代。
通过阅读文档和几个示例,我在下面创建了一个假设示例。显然,这是一个小得多的数据集,所以我没有包含我将用来将所有 URL 分成更小的块以便一次提交的部分。我希望在转移到我的真实数据集之前使用这个示例数据集来证明我的方法。
目前,使用下面的代码并使用timeit
,每种方法的结果运行时如下:
- for 循环和请求 = 16.9 秒
- grequests async with mapping = 13.9 s
我的问题是,如果 grequests 方法同时启动所有请求,那为什么不是更快呢?此外,是否有人对如何更好地同时提交多个请求有任何建议?
# coding: utf-8
# In[1]:
import grequests
import requests
# In[2]:
# set up session
s = requests.session()
# In[3]:
# get a list of airports
airports = ['ATL', 'ORD', 'LAX', 'DFW', 'DEN', 'JFK', 'IAH', 'SFO', 'LAS', 'PHX',
'CLT', 'MIA', 'MCO', 'EWR', 'DTW', 'MSP', 'SEA', 'PHL', 'BOS', 'LGA',
'IAD', 'BWI', 'FLL', 'SLC', 'HNL', 'DCA', 'MDW', 'SAN', 'TPA', 'PDX',
'STL', 'MCI', 'MEM', 'MKE', 'OAK', 'CLE', 'RDU', 'BNA', 'SMF', 'HOU',
'SNA', 'AUS', 'MSY', 'SJC', 'PIT', 'SAT', 'CVG', 'DAL', 'IND']
# In[4]:
# build query string
def build_request(airport):
base_url = 'https://services.faa.gov/airport/status/'
request_string = base_url + airport + '/?format=application/json'
return request_string
# In[5]:
# create the request strings for all airports
urls = [build_request(a) for a in airports]
# In[7]:
def try_grequests(urls):
# create a set of unsent requests
rs = (grequests.get(u) for u in urls)
# send them all at the same time
data = grequests.map(rs)
return data
# In[10]:
def try_requests(urls):
# send requests one by one
data = [s.get(u).json() for u in urls]
return data
# In[11]:
# time how long it takes using grequests
get_ipython().magic(u'timeit try_grequests(urls)')
# In[12]:
# time how long it takes using requests
get_ipython().magic(u'timeit try_requests(urls)')