head请求比get更快更安全,仅获取响应头;遇405则降级get并流式处理;禁用自动重定向,手动解析location并拼接绝对路径;控制并发、复用session、按域名分组限速;输出需含source和position等上下文字段。

用 requests 发送 HEAD 请求比 GET 更快更安全
直接发 GET 请求会下载完整页面,浪费带宽、触发统计脚本、甚至被风控;而 HEAD 只取响应头,能快速判断状态码且服务端通常不执行业务逻辑。但要注意:有些服务器对 HEAD 返回 405 Method Not Allowed,此时需降级为 GET(加 allow_redirects=False 避免自动跳转干扰判断)。
- 默认用
requests.head(url, timeout=10, allow_redirects=False) - 捕获
requests.exceptions.ConnectionError、Timeout、InvalidURL等异常,统一记为error - 若
HEAD返回405,再试一次requests.get(url, timeout=10, allow_redirects=False, stream=True),并立即.close()
识别重定向要区分 301/302 和最终状态
只看响应码不够——301 和 302 是重定向,但关键是目标地址是否有效。不能依赖 requests 自动跟随(allow_redirects=True),否则你看到的永远是最终页的状态码,丢失中间跳转信息。
- 始终设
allow_redirects=False,检查response.status_code in (301, 302, 307, 308) - 从响应头
response.headers.get('Location')提取跳转地址,再单独验证该地址 - 注意
Location可能是相对路径,需用urllib.parse.urljoin(base_url, location)拼接 - 避免无限跳转:限制最大跳转层级(如 5 层),每跳都记录原始 URL → 目标 URL 链路
批量处理时必须加请求间隔和并发控制
一次性发起几百个请求,大概率被目标站封 IP 或返回 429 Too Many Requests。别信“多线程=快”,没节制的并发反而让整体耗时飙升、错误率上升。
- 用
concurrent.futures.ThreadPoolExecutor(max_workers=5)控制并发数(5 是多数小站的安全起点) - 每个请求前加
time.sleep(0.5)(非绝对,可按域名分组设置:同一域名间隔 ≥1s) - 对同一域名做连接复用:复用
requests.Session()实例,避免重复 TCP 握手 - 把待测 URL 按域名分组,每组内串行请求,组间可并发
输出结果要包含可定位的上下文信息
只写“https://example.com/404 → 404”没用。编辑人员需要知道这个链接出现在哪篇文档、哪个 HTML 元素里,才能快速修复。
- 输入源要是带上下文的结构化数据,比如 CSV 含
source_file、line_number、anchor_text - 输出 JSON 或 CSV,字段至少包括:
url、status_code、final_url(重定向终点)、error(异常消息)、source(来源文件路径)、position(行号或 CSS 选择器) - 死链(
4xx/5xx)和循环重定向单独标记,方便过滤
真正麻烦的不是发请求,而是怎么把“链接失效”这件事,准确归因到内容源头。漏掉 source 和 position 字段,脚本跑完等于白跑。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











