使用请求库请求web资源、网站或web服务时,请求需要很长时间才能完成.代码类似于以下内容:
import requests
requests.get("https://www.example.com/")
此请求需要2分钟(正好2分10秒)才能完成!为什么它这么慢?我该如何修复它?
使用请求库请求web资源、网站或web服务时,请求需要很长时间才能完成.代码类似于以下内容:
import requests
requests.get("https://www.example.com/")
此请求需要2分钟(正好2分10秒)才能完成!为什么它这么慢?我该如何修复它?
这个问题有多种可能的解决方案.关于StackOverflow有很多答案,所以我将try 将它们结合起来,以避免您搜索它们的麻烦.
在我的研究中,我发现了以下几层:
对于许多问题,激活日志(log)可以帮助您发现问题所在(source):
import requests
import logging
import http.client
http.client.HTTPConnection.debuglevel = 1
# You must initialize logging, otherwise you'll not see debug output.
logging.basicConfig()
logging.getLogger().setLevel(logging.DEBUG)
requests_log = logging.getLogger("requests.packages.urllib3")
requests_log.setLevel(logging.DEBUG)
requests_log.propagate = True
requests.get("https://www.example.com")
如果调试输出不能帮助您解决问题,请继续阅读.
不请求所有数据,只发送HEAD请求(source)会更快:
requests.head("https://www.example.com")
有些服务器不支持此功能,那么您可以try 流式传输响应(source):
requests.get("https://www.example.com", stream=True)
如果连续发送多个请求,可以使用requests.Session
来加快请求速度.这可以确保与服务器的连接保持打开和配置状态,并将Cookie持久化,这是一个很好的好处.试试这个(source):
import requests
session = requests.Session()
for _ in range(10):
session.get("https://www.example.com")
如果一次发送大量请求,每个请求都会阻止执行.你可以将其并行化,例如requests-futures(来自kederrac的 idea ):
from concurrent.futures import as_completed
from requests_futures.sessions import FuturesSession
with FuturesSession() as session:
futures = [session.get("https://www.example.com") for _ in range(10)]
for future in as_completed(futures):
response = future.result()
小心不要同时用太多的请求淹没服务器.
如果这也不能解决你的问题,请继续阅读...
在许多情况下,原因可能在于您请求的服务器.首先,通过以相同方式请求任何其他URL来验证这一点:
requests.get("https://www.google.com")
如果效果良好,您可以将精力集中在以下可能的问题上:
服务器可能会专门阻止requests
,或者他们可能会利用白名单,或者其他一些原因.要发送更好的用户代理字符串,请try 以下(source):
headers = {"User-Agent": "Mozilla/5.0 (X11; CrOS x86_64 12871.102.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.141 Safari/537.36"}
requests.get("https://www.example.com", headers=headers)
如果这个问题只是偶尔出现,例如在几个请求之后,服务器可能会限制您的速率.判断响应,看看它是否读到了类似的内容(即"达到速率限制"、"超过工作队列深度"或类似内容;source).
在这里,解决方案只是在请求之间等待更长时间,例如使用time.sleep()
.
您可以通过不读取从服务器收到的响应来判断这一点.如果代码仍然很慢,这不是你的问题,但如果这解决了它,问题可能在于解析响应.
要解决这些问题,请try :
r = requests.get("https://www.example.com")
r.raw.chunked = True # Fix issue 1
r.encoding = 'utf-8' # Fix issue 2
print(response.text)
这可能是最糟糕的问题.一种简单但奇怪的判断方法是添加一个timeout
参数,如下所示:
requests.get("https://www.example.com/", timeout=5)
如果返回successful response,问题应该出在IPv6上.原因是requests
先try IPv6连接.当超时时,它会try 通过IPv4连接.通过将超时设置为较低,可以强制它在较短的时间内切换到IPv4.
通过使用例如wget
或curl
进行验证:
wget --inet6-only https://www.example.com -O - > /dev/null
# or
curl --ipv6 -v https://www.example.com
在这两种情况下,我们都会强制工具通过IPv6连接,以隔离问题.如果超时,请重试强制IPv4:
wget --inet4-only https://www.example.com -O - > /dev/null
# or
curl --ipv4 -v https://www.example.com
如果这一切正常,你已经发现了你的问题!但你会问,如何解决这个问题?
socket.AF_INET
.)AddressFamily inet
添加到SSH配置中.)