Python请求很慢,并且需要很长时间才能完成HTTP或HTTPS请求

标签 python python-3.x python-requests urllib3

当使用请求库请求Web资源或网站或Web服务时,请求需要很长时间才能完成。该代码类似于以下内容:

import requests
requests.get("https://www.example.com/")
此请求需要2分钟(恰好是2分钟10秒)才能完成!为什么这么慢,我该如何解决?

最佳答案

对于这个问题可以有多种可能的解决方案。关于StackOverflow,有很多答案,因此,我将尝试将所有答案组合在一起,以节省您寻找它们的麻烦。
在搜索中,我发现了以下几层:
首先,尝试记录
对于许多问题,激活日志记录可以帮助您发现问题所在(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或流式请求
不请求所有数据,而是仅发送HEAD请求(source),可能会更快:
requests.head("https://www.example.com")
某些服务器不支持此功能,那么您可以尝试流式传输响应(source):
requests.get("https://www.example.com", stream=True)
对于连续多个请求,请尝试利用 session
如果您连续发送多个请求,则可以使用requests.Session加快请求的速度。这样可以确保与服务器的连接保持打开和配置状态,并且还保留cookie,这是一个不错的好处。试试这个(source):
import requests
session = requests.Session()
for _ in range(10):
    session.get("https://www.example.com")
要并行处理您的请求(尝试10个以上的请求),请使用requests-futures
如果您一次发送大量请求,则每个请求都会阻止执行。您可以使用requests-futures(kederrac的思想)并行化它:
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,或者他们可能利用了白名单或其他原因。要发送更好的用户代理字符串,请尝试以下(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()
服务器响应的格式错误,导致解析问题
您可以通过不阅读从服务器收到的响应来进行检查。如果代码仍然很慢,这不是您的问题,但是如果此问题得以解决,则问题可能出在解析响应上。
  • 如果某些 header 设置不正确,则会导致解析错误,从而阻止分块传输(source)。
  • 在其他情况下,手动设置编码可能会解决解析问题(source)。

  • 要解决这些问题,请尝试:
    r = requests.get("https://www.example.com")
    r.raw.chunked = True # Fix issue 1
    r.encoding = 'utf-8' # Fix issue 2
    print(response.text)
    
    IPv6不起作用,但IPv4起作用
    这可能是所有所有人中最糟糕的问题。一种简单但奇怪的检查方法是添加timeout参数,如下所示:
    requests.get("https://www.example.com/", timeout=5)
    
    如果返回成功响应,则问题应该出在IPv6上。原因是requests首先尝试进行IPv6连接。超时后,它将尝试通过IPv4连接。通过将超时设置为较低,可以强制其在较短的时间内切换到IPv4。
    通过使用wgetcurl进行验证:
    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
    
    如果这样可以正常工作,则说明您已找到问题!但是,您问如何解决呢?
  • 蛮力解决方案是完全使用disable IPv6
  • 您也可以只使用disable IPv6 for the current session
  • 您可能只想force requests to use IPv4。 (在链接的答案中,您必须调整代码以始终返回IPv4的socket.AF_INET。)
  • 如果要解决SSH的此问题,请参见force IPv4 for SSH的方法。 (简而言之,将AddressFamily inet添加到您的SSH配置中。)
  • 您可能还想检查问题是否出在DNS or TCP上。
  • 关于Python请求很慢,并且需要很长时间才能完成HTTP或HTTPS请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62599036/

    相关文章:

    python - Pandas DataFrame 中的滚动半方差

    javascript - 通过 requests-html 给定 OpenSSL.SSL.Error 'SSL routines', 'tls_process_server_certificate' , 'certificate verify failed 获取 JavaScript Web

    python - 如何分配数组元素

    python - 使用 requests.get() 时缺少 Cookie 的某些部分?

    python - 使用 beautifulsoup 解析站点

    python - Matplotlib:来自 3 列 pandas 数据帧的 pcolormesh 或 pcolor

    python - 遍历 Pandas 数据框

    python - 迭代 Pandas 数据框中的多个列并创建新列

    python-3.x - 无法在 Jupyter Notebook 中导入 Scipy

    python - 生成一个 View 来识别 python 列中特定值的第一个条目和最后一个条目