Python requests批量检测站点时捕获gaierror异常避免程序中断
批量站点HTTP状态码检测的连接异常修复方案
原有实现逻辑
- 依赖导入:引入
BeautifulSoup、requests、urllib3库,执行urllib3.disable_warnings()禁用InsecureRequestWarning类型的SSL证书警告 - 初始化配置:拉取指定源URL的文本内容写入
Url.txt,初始化requests.Session对象,配置User-Agent、Accept等标准浏览器请求头 - 待检测列表构建:读取
Url.txt中的所有站点URL,逐行去除空白符后存入待检测列表 - 初始检测流程:遍历待检测站点列表,在
try块外部调用se.get()发起GET请求,传入verify=False、allow_redirects=False参数;try块内仅执行response.raise_for_status(),仅捕获requests.exceptions.HTTPError异常,将正常响应的状态结果追加写入UrlOutput.txt并打印输出
故障现象
检测过程中遇到DNS故障、域名无法解析的站点时,异常按以下层级抛出:
- 底层触发
gaierror: [Errno -2] Name or service not known - 依次向上引发
NewConnectionError、MaxRetryError - 最终抛出
requests.exceptions.ConnectionError
即使补充urllib3、requests官方文档列出的所有可捕获异常类型,这类异常仍会直接中断程序运行,无法继续检测剩余站点。
根因说明
你把se.get()请求调用写在了try块外部,请求发起阶段抛出的连接类异常根本不会进入你写的异常捕获逻辑,自然会直接中断程序,和补充多少种异常捕获类型没有关系。
修复方案
- 将
se.get()请求调用整体移入try块内部,所有请求相关的异常才会被捕获 - 按从细到粗的顺序配置异常捕获分支:先捕获
requests.exceptions.HTTPError处理4xx/5xx类HTTP状态错误,再捕获requests.exceptions.ConnectionError覆盖DNS解析失败、TCP建连失败、站点不可达类连接故障,再补充超时异常捕获,最后用requests.exceptions.RequestException做兜底,覆盖所有requests库抛出的请求类异常 - 给请求增加
timeout参数,避免异常站点导致请求无限挂起 - 所有检测结果(含异常结果)统一写入输出文件,保证单站点故障不中断整体遍历流程
修复后核心代码
import requests import urllib3 from bs4 import BeautifulSoup # 关闭SSL证书告警 urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) # 初始化会话,配置标准请求头 se = requests.Session() se.headers.update({ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8" }) # 读取待检测URL列表 with open("Url.txt", "r", encoding="utf-8") as f: url_list = [line.strip() for line in f if line.strip()] # 逐站检测,结果写入输出文件 with open("UrlOutput.txt", "a", encoding="utf-8") as out_f: for url in url_list: try: # get请求必须放在try块内,新增超时配置避免挂起 resp = se.get(url, verify=False, allow_redirects=False, timeout=10) resp.raise_for_status() log_line = f"[正常] {url} 状态码:{resp.status_code}\n" except requests.exceptions.HTTPError as e: log_line = f"[HTTP错误] {url} 状态码:{e.response.status_code}\n" except requests.exceptions.ConnectionError: log_line = f"[连接故障] {url} 原因:DNS解析失败/站点不可达\n" except requests.exceptions.Timeout: log_line = f"[请求超时] {url}\n" except requests.exceptions.RequestException as e: log_line = f"[其他异常] {url} 错误信息:{str(e)}\n" print(log_line.strip()) out_f.write(log_line)
注意事项
- 不需要额外捕获urllib3层的
NewConnectionError、MaxRetryError或socket层的gaierror,这些异常都会被requests统一封装为requests.exceptions.ConnectionError抛出,捕获该类型即可覆盖所有连接类故障 - 不要使用裸
except:捕获所有异常,否则会拦截键盘中断、系统退出等信号,导致程序无法正常终止 - 可根据实际网络环境调整
timeout参数数值,建议设置为5-15秒区间
内容的提问来源于stack exchange,提问作者Hunter Michael
相关产品推荐
相关产品推荐

