Python 更快地从API中抓取JSON:异步还是?
我需要尽快从网站API中获取大约30GB的JSON数据。我不需要解析它——我只需要保存每个API URL上显示的所有内容Python 更快地从API中抓取JSON:异步还是?,python,asynchronous,web-scraping,python-requests,Python,Asynchronous,Web Scraping,Python Requests,我需要尽快从网站API中获取大约30GB的JSON数据。我不需要解析它——我只需要保存每个API URL上显示的所有内容 我一次可以请求相当多的数据——比如1MB甚至50MB的“块”(API参数编码在URL中,允许我选择每个请求需要多少数据) API限制每秒1个请求 我想在笔记本电脑和100MB/秒的互联网连接上实现这一点 目前,我正在通过以下方式实现这一点(同步且速度太慢): -预先计算所有我想要抓取的(编码的)URL -使用Python3的请求库请求每个URL,并将生成的JSON逐个保存
- 我一次可以请求相当多的数据——比如1MB甚至50MB的“块”(API参数编码在URL中,允许我选择每个请求需要多少数据)
- API限制每秒1个请求
- 我想在笔记本电脑和100MB/秒的互联网连接上实现这一点
您正在解析内容,然后再次序列化它。您可以直接将内容写入文件
curr_url_request = requests.get(encoded_URL_i, timeout=timeout_secs)
if curr_url_request.ok:
with open('json_output.txt', 'w') as outfile:
outfile.write(curr_url_request.content)
这可能会消除大部分处理开销。您正在解析内容,然后再次序列化它。您可以直接将内容写入文件
curr_url_request = requests.get(encoded_URL_i, timeout=timeout_secs)
if curr_url_request.ok:
with open('json_output.txt', 'w') as outfile:
outfile.write(curr_url_request.content)
这可能会消除大部分处理开销。tornado有一个非常强大的异步客户端。下面是一个基本代码,可以实现这一点:
from tornado.httpclient import AsyncHTTPClient
import tornado
URLS = []
http_client = AsyncHTTPClient()
loop = tornado.ioloop.IOLoop.current()
def handle_request(response):
if response.code == 200:
with open('json_output.txt', 'a') as outfile:
outfile.write(response.body)
@tornado.gen.coroutine
def queue_requests():
results = []
for url in URLS:
nxt = tornado.gen.sleep(1) # 1 request per second
res = http_client.fetch(url, handle_request)
results.append(res)
yield nxt
yield results # wait for all requests to finish
loop.add_callback(loop.stop)
loop.add_callback(queue_requests)
loop.start()
这是一种直接的方法,可能会导致与远程服务器的连接过多。在对请求排队时,您可能必须使用滑动窗口来解决此问题
如果请求超时或需要特定的标题,请随意阅读
tornado
有一个非常强大的异步客户端。下面是一个基本代码,可以实现这一点:
from tornado.httpclient import AsyncHTTPClient
import tornado
URLS = []
http_client = AsyncHTTPClient()
loop = tornado.ioloop.IOLoop.current()
def handle_request(response):
if response.code == 200:
with open('json_output.txt', 'a') as outfile:
outfile.write(response.body)
@tornado.gen.coroutine
def queue_requests():
results = []
for url in URLS:
nxt = tornado.gen.sleep(1) # 1 request per second
res = http_client.fetch(url, handle_request)
results.append(res)
yield nxt
yield results # wait for all requests to finish
loop.add_callback(loop.stop)
loop.add_callback(queue_requests)
loop.start()
这是一种直接的方法,可能会导致与远程服务器的连接过多。在对请求排队时,您可能必须使用滑动窗口来解决此问题
如果请求超时或需要特定标题,请随意阅读您是否考虑过简单地尝试一下并找出答案?我使用过并且发现它很有用,它几乎是一个异步的
请求
。一个非常容易实现的结果是使用一个-现在,您正在为每个请求建立一个新的TCP连接。会话将使您保持单个TCP连接的活动状态并重新使用它(请参阅)。^^感谢您的请求。会话提示--这肯定是最容易做到的。我将根据我最终得到的任何异步解决方案对其进行基准测试。您是否考虑过简单地尝试一下并找出答案?我使用过并且发现它很有用,它几乎是一个异步的请求
。一个非常容易实现的结果是使用一个-现在,您正在为每个请求建立一个新的TCP连接。会话将使您保持单个TCP连接的活动状态并重新使用它(请参阅)。^^感谢您的请求。会话提示--这肯定是最容易做到的。我将根据我最终得到的任何异步解决方案对其进行基准测试。谢谢!为了让它运行,我必须将loop.add\u callback(queue\u requests)
更改为loop.add\u callback(lambda:queue\u requests)
,这样它就不会调用未来。另外,睡眠也是有帮助的,但实际上我发现所有的工作人员都在同一时间抓取一页,然后在同一时间睡觉,等等……所以他们不遵守每秒1次的限制。我在python-2.7
上测试了这一点,因为它工作正常,在他们的网站上,他们说tornado
受python-3
的支持,但也许有一些细微的差别。谢谢!为了让它运行,我必须将loop.add\u callback(queue\u requests)
更改为loop.add\u callback(lambda:queue\u requests)
,这样它就不会调用未来。另外,睡眠也是有帮助的,但实际上我发现所有的工作人员都在同一时间抓取一页,然后在同一时间睡觉,等等……所以他们不遵守每秒1次的限制。我在python-2.7
上测试了这一点,因为它工作正常,在他们的网站上,他们说tornado
受python-3
的支持,但也许有一些细微的差别。