首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Python请求很慢,需要很长时间才能完成HTTP或HTTPS请求

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

Stack Overflow用户
提问于 2020-06-27 00:28:59
回答 1查看 19K关注 0票数 21

使用请求库请求web资源、网站或web服务时,请求需要很长时间才能完成。代码如下所示:

代码语言:javascript
复制
import requests
requests.get("https://www.example.com/")

这个请求需要超过2分钟(2分10秒)才能完成!为什么它这么慢,我怎么才能修复它?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-06-27 00:28:59

这个问题可以有多种可能的解决方案。在StackOverflow上有许多关于这些问题的答案,所以我将尝试将它们组合在一起,以省去您搜索它们的麻烦。

在我的搜索中,我发现了以下几层:

首先,尝试记录日志

对于许多问题,激活日志记录可以帮助您发现问题所在(source):

代码语言:javascript
复制
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),可能会更快:

代码语言:javascript
复制
requests.head("https://www.example.com")

有些服务器不支持此功能,那么您可以尝试流式传输响应(source):

代码语言:javascript
复制
requests.get("https://www.example.com", stream=True)

对于一行中的多个请求,请尝试使用会话

如果您连续发送多个请求,则可以通过使用requests.Session来加速请求。这将确保与服务器的连接保持打开和配置状态,并将cookies作为一个很好的优势保留下来。试试这个(source):

代码语言:javascript
复制
import requests
session = requests.Session()
for _ in range(10):
    session.get("https://www.example.com")

要并行化您的请求(try for > 10个请求),请使用requests futures

如果一次发送大量请求,每个请求都会阻塞执行。你可以利用requests-futures (来自kederrac的想法)将其并行化:

代码语言:javascript
复制
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来验证这一点:

代码语言:javascript
复制
requests.get("https://www.google.com")

如果运行良好,您可以将精力集中在以下可能的问题上:

服务器只允许特定的用户代理字符串

服务器可能会专门阻止requests,或者他们可能会利用白名单,或者其他一些原因。要发送更好的用户代理字符串,请尝试以下命令(source):

代码语言:javascript
复制
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()

服务器响应的格式不正确,从而导致解析问题

您可以通过不读取从服务器收到的响应来检查这一点。如果代码仍然很慢,这不是您的问题,但如果这解决了它,问题可能出在解析响应上。

chunked

  • 如果某些标头设置不正确,这可能会导致解析错误,从而阻止分块传输;在其他情况下,手动设置编码可能会解决解析问题(source).

要解决这些问题,请尝试:

代码语言:javascript
复制
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参数,如下所示:

代码语言:javascript
复制
requests.get("https://www.example.com/", timeout=5)

如果这返回一个成功的响应,那么问题应该出在IPv6。原因是requests首先尝试IPv6连接。当超时时,它会尝试通过IPv4连接。通过将超时设置为低,您可以强制它在较短的时间内切换到IPv4。

通过利用例如wgetcurl进行验证

代码语言:javascript
复制
wget --inet6-only https://www.example.com -O - > /dev/null
# or
curl --ipv6 -v https://www.example.com

在这两种情况下,我们都强制工具通过IPv6连接以隔离问题。如果此操作超时,请再次尝试强制IPv4:

代码语言:javascript
复制
wget --inet4-only https://www.example.com -O - > /dev/null
# or
curl --ipv4 -v https://www.example.com

如果运行良好,那么您已经找到了问题所在!但你会问,如何解决这个问题?

一种暴力解决方案是completely.

  • You
  1. disable IPv6 disable IPv6 for the current session .
  2. 你可能只想要force requests to use IPv4。(在链接的答案中,您必须调整代码以始终为IPv4返回socket.AF_INET。)
  3. 如果您想要为IPv4修复此问题,下面是如何使用force IPv4 for SSH。(简而言之,将AddressFamily inet添加到您的SSH配置中。)
  4. 您可能还希望检查问题是否出在您的SSH配置中
票数 60
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62599036

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档