【爬虫 | Python】解决‘Requests Max Retries Exceeded With Url‘报错的问题

这篇具有很好参考价值的文章主要介绍了【爬虫 | Python】解决‘Requests Max Retries Exceeded With Url‘报错的问题。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

背景

我们在写爬虫的时候,经常会遇到这样的报错信息:

HTTPConnectionPool(host=‘xxx.xxx.com’, port=443): Max retries exceeded with url: /api/v2/oauth (Caused by NewConnectionError(’<urllib3.connection.HTTPConnection object at 0x7fac5953ab70>: Failed to establish a new connection: [Errno 110] Connection timed out’))

这里有3个重要的信息点,分别是:

HTTPConnectionPool(host='xxx.xxx.com', port=443)
Max retries exceeded with url:
Connection timed out

解决方案


一、普遍方案

针对上述的问题,目前网上给出3种解决方案

1.在Headers里添加Connection参数,使其为close,因为默认为keep-alive

因为requests使用的http连接池在发出request后会继续保持connection处于活跃状态,而http线程池里的的线程数是有限的。当多次request后,随机使用完了线程池里的session,因此为避免此问题需要设置connection为close来断连。

headers = {
	'Connection': 'close' # 设置为关闭长连接
}

2.使用requests.close()来关闭连接。

使用self.close()主动断开宇服务器的连接。

req = requests.get(url='xxx', headers='xxx', data='xxx)
req.close()	# 关闭连接

3.使用request.session()的请求方式。

创建session,然后主动断开。

s = requests.session()
s.keep_alive = False  # 关闭多余连接
s.get(url='xxx', headers='xxx', data='xxx)

上面的3种方案也许能解决问题,但是经过尝试,并非所有情况都能有效解决问题。下面给出更加全面和细致的解决方案。


细致方案

俗话说,具体问题具体分析。“因地制宜”才能真正解决所遇到的问题。

当请求库无法成功将请求发送到发出的站点时,就会发生错误。发生这种情况是因为不同的原因。这是常见的。其中可能存在如下的问题所致:

1.错误的 URL (解决方案 1)
2.未能验证 SSL 证书(解决方案 2)
3.使用没有或不稳定的互联网连接的请求(解决方案 3)
4.发送太多请求或服务器太忙(解决方案 4)


一、问题重述

1.错误的 URL

发生这种错误的其中一种可能的原因是你输入了错误的URL,导致request请求不到或超时。例如:

1.你把com写成了con,因此需要认真检查URL是否正确。

import requests
 
# 错误的URL,应为https://www.github.com
host = 'https://www.github.con' 
res = requests.get(url=host)
print(res) # 报错

2.你所调用的URL已失效或不存在,例如某个API已经失效或不存在,因此会发生此问题,可以使用浏览器检验一下该URL的有效性。

import requests
 
# 不存在的URL或已失效的URL
host = 'https://www.github.com/api/baidu' 
res = requests.get(url=host)
print(res) # 报错

上述问题输出:

requests.exceptions.ConnectionError: HTTPSConnectionPool(host='www.github.coxxx', port=443): Max retries exceeded with url: / (Caused by NewConnectionError('<urllib3.connection.VerifiedHTTPSConnection object at 0x7fd5b5d33100>: Failed to establish a new connection: [Errno 111] Connection refused'))

可以观察到报错信息的最后部分是Connection refused

2.未能验证 SSL 证书

默认情况下,请求库实施 SSL 证书验证以确保您建立安全连接。如果无法验证证书,您最终会遇到如下错误:

requests.exceptions.ConnectionError: HTTPSConnectionPool(host='www.github.coxxx', port=443): Max retries exceeded with url: / (Caused by NewConnectionError('<urllib3.connection.VerifiedHTTPSConnection object at 0x7fd5b5d33100>: requests.exceptions.SSLError: [Errno 1] _ssl.c:503: error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed'))

可以观察到报错信息的最后部分是certificate verify failed

3.网络不稳定

你所发送请求的主机与目标服务器之间的通信路线不稳定(如跨国)或两者之间其中之一的带宽受限导致的网络不稳定现象所致:

Error: requests.exceptions.ConnectionError: HTTPSConnectionPool(host=’www.github.com’, port=443): Max retries exceeded with url: / (Caused by NewConnectionError(‘<urllib3.connection.VerifiedHTTPSConnection object at 0x7f7f5fadb100>: Failed to establish a new connection: [Errno -3] Temporary failure in name resolution’))

可以观察到报错信息的最后部分是Temporary failure in name resolution

4.发送太多请求/服务器过载

当如此快地发出如此多的请求时,某些网站会阻止连接。与此相关的另一个问题是当服务器过载时——同时管理大量连接。或者你的IP已经被目标服务器加入了黑名单(被封锁IP)。在这种情况下,requests.get() 会抛出如下错误:

requests.exceptions.ConnectionError: HTTPConnectionPool(host='www.github.com', port=80): Max retries exceeded with url: / (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x0000008EC69AAA90>: Failed to establish a new connection: [Errno 11001] getaddrinfo failed'))
HTTPConnectionPool(host='www.github.com', port=80): Max retries exceeded with url: /api/v2/oauth (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7fac5953ab70>: Failed to establish a new connection: [Errno 110] Connection timed out'))

二、应对方案


1.方案一:仔细检查 URL

确保您拥有正确且有效的 URL。考虑前面提到的有效 URL:“ https://www.github.com ”。“Max retries exceeded with url”错误主要发生在对www 和顶级域名(例如 .com)进行错误编辑时。

当方案/协议 (https) 被错误编辑时会出现另一个错误:requests.exceptions.InvalidSchema。如果二级域(在我们的例子中是“github”)被错误编辑,我们将被引导到一个完全不同的网站,如果该网站不存在,我们会收到 404 响应。

导致“超过 url 的最大重试次数”的其他错误 URL 是“wwt.github.com”和“https://www.github.com”(.com 之后的空格)。


2.方案二:解决SSLError

如前所述,该错误是由不受信任的 SSL 证书引起的。最快的解决方法是requests.get()上设置属性 verify=False。这告诉 requests 在不验证 SSL 证书的情况下发送请求。

requests.get('https://www.github.com', verify=False)

请注意,证书不会被验证;因此,您的应用程序将面临中间人攻击等安全威胁。对于在生产级别使用的脚本,最好避免使用此方法。


3.方案三:解决网络不稳定的问题

此解决方案适用于间歇性连接中断的情况。在这些情况下,我们希望请求能够在抛出错误之前对请求进行多次尝试。对于这种情况,我们可以使用两种解决方案:

  • requests.get() 中发出超时参数。
  • 在出现与连接相关的错误时重试连接。

方案A

requests.get() 中发出超时参数。

1.如果服务器过载,我们可以使用超时来等待更长时间的响应。这将增加请求成功完成的机会。

import requests
 
url = 'https://www.github.com'
res = requests.get(url,  timeout=7)
print(res)

上面的代码将等待 7 秒,以便请求包连接到站点并读取源代码。

2.你可以将超时作为双元素元组传递,其中第一个元素是连接超时(与服务器建立连接的时间),第二个值是读取超时(允许客户端从服务器读取数据的时间)

requests.get('https://api.github.com', timeout=(3, 7))

使用以上线路时,必须在3秒内建立连接,7秒内读取数据;否则,请求会引发超时错误。


方案B

在出现连接相关错误时重试连接.

这些请求使用urllib3 中的重试实用程序 ( urllib3.util.Retry ) 来重试连接。我们将使用以下代码发送请求:

import requests
from requests.adapters import HTTPAdapter, Retry
import time
 
def send_request(url,
    n_retries=4,
    backoff_factor=0.9,
    status_codes=[504, 503, 502, 500, 429]):
    
    sess = requests.Session()
    retries = Retry(connect=n_retries, backoff_factor=backoff_factor, status_forcelist=status_codes)
    sess.mount("https://", HTTPAdapter(max_retries=retries))
    sess.mount("http://", HTTPAdapter(max_retries=retries))
    res = sess.get(url)
    return res

我们在urllib3.util.Retry类中使​​用了以下参数:

  • connect – 与连接相关的尝试次数。默认情况下, send_request()将进行 4 次尝试加 1 次(立即发生的原始请求)。
  • backoff_factor – 确定重试之间的延迟。休眠时间使用公式{backoff_factor} * (2 ^ ({retry_number} – 1))计算。我们将在调用该函数时处理此参数的示例。
  • status_forcelist – 仅重试导致 504503502500429 状态代码的所有连接。

现在让我们调用我们的函数并计时执行。

# 开始一个计时器
start_time = time.time()
 
# 请求Github API
url = "https://api.github.com/users"
res = send_request(url)
 
# 打印返回状态码
print(res.status_code)
 
# 结束计时器
end_time = time.time()
 
# 计算运行时长
print("Run time: ", end_time-start_time)

输出:

200
Run time:  0.8597214221954346

连接已成功完成(状态 200),耗时 0.86 秒。要查看退避的实现,让我们尝试向不存在的服务器发送请求,在异常发生时捕获异常并计算执行时间。

try:
    # 启动执行定时器
    start_time = time.time()
    url = "http://localhost/6000"
	# 调用send_request()方法向url发送请求
    # 这永远不会成功,因为没有服务器在运行
    # 在端口 6000 上。
    response = send_request(url)
    print(response.status_code)
except Exception as e:
    # 捕获任何异常 - 执行将在这里结束,因为
    # 请求无法连接到 http://localhost/6000
    print("Error Name: ", e.__class__.__name__)
    print("Error Message: ", e)
finally:
    # 选择结束时间
    end_time = time.time()
    # 计算执行所花费的时间
    print("Run time: ", end_time-start_time)

输出:

Error Name:  ConnectionError
Error Message:  HTTPConnectionPool(host='localhost', port=80): Max retries exceeded with url: /6000 (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7f06a5862a00>: Failed to establish a new connection: [Errno 111] Connection refused'))
Run time:  12.61784315109253

backoff_factor=0.9 的 4 次重试(加上 1 个原始请求)之后,执行时间为 12.6 秒。让我们使用之前看到的公式来计算睡眠时间。

sleeping_time = {backoff_factor} * (2 ^ ({retry_number}1))

总共有5个请求

  • 第一个请求(立即发出)——睡眠0秒,
  • 第一次重试(也是在第一次请求失败后立即发送)——0秒休眠,
  • 第二次重试-> 0.9*(2^(2-1)) = 0.9*2 = 1.8 秒睡眠,
  • 第三次重试 -> 0.9*(2^(3-1)) = 0.9*4 = 3.6 秒的休眠时间,以及,
  • 第四次重试 -> 0.9*(2^(4-1)) = 0.9*8 = 7.2秒。

这是urllib3.util.Retry实现的总共 12.6 秒的休眠时间。实际执行时间为12.61784315109253秒。未说明的 0.01784315109253 差异归因于 DNC 和一般计算机电源延迟。


4.方案四:超时处理服务器请求

一些网站会阻止网络爬虫。他们注意到机器人正在根据传递的标头发送请求。例如,让我们运行此代码并打开详细信息以查看幕后发生的情况。


import http.client
 
# turn verbose on
http.client.HTTPConnection.debuglevel = 1
import requests
url = 'https://www.github.com'
res = requests.get(url=url)
print(res)

输出(Curl):

send: b'GET / HTTP/1.1\r\nHost: www.github.com\r\nUser-Agent: python-requests/2.28.1\r\nAccept-Encoding: gzip, deflate\r\nAccept: */*\r\nConnection: keep-alive\r\n\r\n'
reply: 'HTTP/1.1 200 OK\r\n'

在该日志中,您可以看到 User-Agentpython-requests v2.28.1 而不是真正的浏览器。使用此类标识,您可能会被阻止并收到“超过 url 的最大重试次数”错误。为避免这种情况,我们需要将我们的实际浏览器作为用户代理传递。您可以转到以下链接获取一些标头: http://myhttpheader.com/。在该链接中,我的用户代理是“Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Firefox/91.0”。现在让我们改用该用户代理。

import http.client
 
# 打开详细信息
http.client.HTTPConnection.debuglevel = 1
 
import requests
 
headers = {'User-Agent':'Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Firefox/91.0'}
url = 'https://www.github.com'
res = requests.get(url=url,  timeout=5, headers=headers)
print(res)

输出(Curl):

send: b'GET / HTTP/1.1\r\nHost: www.github.com\r\nUser-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Firefox/91.0\r\nAccept-Encoding: gzip, deflate\r\nAccept: */*\r\nConnection: keep-alive\r\n\r\n'
reply: 'HTTP/1.1 200 OK\r\n'

重要:

针对被高级反爬及被封禁IP的解决方法策略有所不同。

1.被高级反爬后的处理:
例如像国内rs这样的中高级动态反爬技术,其原理是检测用户浏览器环境是否为真实的用户环境。

针对此类问题需要采用更加高级的手段进行沙盒实验及补环境。

2.所使用的设备被目标主机封禁IP。

针对此类问题,可以使用IP代理池,每次请求都随机更换IP来避免被封禁;其次,需要降低请求的速率。

注意:请遵守所在国家或地区的法律法规。


本文首发于我的个人博客: Colyn’s Blog,欢迎访问和留言!

本文属于作者自主知识产权的原创文章,如须引用、转载,请注明来源:

版权声明:本文为CSDN博主「InetGeek」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_34532102/article/details/129480220文章来源地址https://www.toymoban.com/news/detail-411384.html

到了这里,关于【爬虫 | Python】解决‘Requests Max Retries Exceeded With Url‘报错的问题的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • http请求报错SSLError: HTTPSConnectionPool:Max retries exceeded with url

    1、问题描述: 迭代请求http web服务,中途遇到异常报错: requests.exceptions.SSLError: HTTPSConnectionPool(host=\\\'xxx.com\\\', port=443): Max retries exceeded with url:xxx 2、问题排查 3、问题原因: http的连接数超过最大限制。默认的情况下连接是keep-alive的,所以导致服务器保持了太多连接而不能再新

    2024年02月12日
    浏览(49)
  • 解决requests.exceptions.ProxyError: HTTPSConnectionPool(host=‘api.github.com‘, port=443): Max retries

    一般来说,出现这种错误的原因可能是以下之一: 代理设置错误 : 你的计算机或网络环境可能配置了代理服务器,但代理服务器设置可能不正确。你需要检查你的代理设置是否正确,并确保它们与你的网络环境相匹配。 代理服务器不可用 : 如果代理服务器无法访问或不可用

    2024年02月05日
    浏览(53)
  • python3 爬虫相关学习3:response= requests.get(url)的各种属性

    目录 1  requests.get(url) 的各种属性,也就是response的各种属性 2 下面进行测试 2.1 response.text 1.2  response.content.decode() 1.2.1 response.content.decode() 或者  response.content.decode(\\\"utf-8\\\") 1.2.2   response.content.decode(\\\"GBK\\\") 报错 1.2.3 关于编码知识 1.3 response.url  1.4 response.status_code 插入知识:

    2024年02月03日
    浏览(41)
  • python中——requests爬虫【中文乱码】的3种解决方法

    requests是一个较为简单易用的HTTP请求库,是python中编写爬虫程序最基础常用的一个库。 而【中文乱码】问题,是最常遇到的问题,对于初学者来说,是很困恼的。 本文将详细说明,python中使用requests库编写爬虫程序时,出现【中文乱码】的原因,及常见3种解决办法。 首先,

    2024年02月12日
    浏览(49)
  • 解决GateWay报错:Exceeded limit on max bytes to buffer : 262144

    场景: 前端传来了一个大的字符串 发现请求不通 一番调试发现SpringGateway 默认内存缓冲区262144字节 网上查了很多种常见的解决方案无效之后 直接重写底层 网友的解决方案 方案1(无效) 直接修改缓冲区大小 方案2(无效) 方案3 无效 gateway-2.2.3以上版本修复了该bug,在Gat

    2024年02月04日
    浏览(45)
  • Python爬虫-requests.exceptions.SSLError: HTTPSConnectionPool疑难杂症解决(1)

    前言 本文是该专栏的第7篇,后面会持续分享python爬虫案例干货,记得关注。 在爬虫项目开发中,偶尔可能会遇到SSL验证问题“ requests.exceptions.SSLError: HTTPSConnectionPool (host=\\\'www.xxxxxx.com\\\', port=443): Max retries exceeded with url ... ”。亦或是验证之后的提示警告“ InsecureRequestWarning: Un

    2024年02月05日
    浏览(47)
  • python requests爬虫返回403错误?加了所有特征的请求头+代理也解决不了的问题处理

    【疑惑】:使用python的requests库发起get或post请求返回403代码错误,使用postman发起请求发现状态码200竟然成功了。这是什么原因?首先排除ip问题,ip有问题的话postman也访问不了。难道是headers出现了问题吗,通过对比发现也不是headers的问题。那就奇了怪了? 【解疑】:其实遇

    2024年02月15日
    浏览(40)
  • Spring Cloud Gateway 彻底解决Exceeded limit on max bytes to buffer : 262144报错问题

    使用Spring Cloud Gateway开发内部API网关时,当业务的Http请求体大小超过256K时,会出现如下报错:Exceeded limit on max bytes to buffer : 262144。 Spring Boot框架给了两种方式来修改这个大小的方式: 方式一:使用修改配置参数值,spring.max-in-memory-size: 1024 * 1024 的方式 方式二:使用WebFluxC

    2024年02月10日
    浏览(47)
  • 已解决requests.exceptions.MissingSchema: Invalid URL

    已解决Python爬虫报错requests.exceptions.MissingSchema: Invalid URL 解决方法,亲测有效!!! 粉丝群里面的一个小伙伴遇到问题跑来私信我,想用python爬虫爬取数据,已经拿到URL再次往下访问,但是发生了报错(当时他心里瞬间凉了一大截,跑来找我求助,然后顺利帮助他解决了,顺

    2024年02月04日
    浏览(51)
  • Python学习笔记:Requests库安装、通过url下载文件

    在pipy或者github下载,通常是个zip,解压缩后在路径输入cmd,并运行以下代码  安装完成后,输入python再输入import requests得到可以判断时候完成安装  2.通过url下载文件 使用的是urllib模块

    2024年02月10日
    浏览(49)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包