死链需通过工具+路径逻辑交叉验证,muffet 扫描本地 HTML 目录前须启动 HTTP 服务(如 python -m http.server),并用 --exclude 过滤非 HTML 资源;Python 脚本可离线检查相对路径文件是否存在;浏览器 Network 面板查看真实请求 URL 是最终判定依据。

死链不是靠肉眼找出来的,而是靠工具+路径逻辑交叉验证——不跑一次 muffet 或本地脚本,你永远不知道哪些 href 和 src 在 HTTP 服务下实际会 404。
用 muffet 扫描静态 HTML 模板目录
直接对本地 HTML 文件夹做死链检测,比等部署后再查快得多。前提是模板里链接是相对路径(如 ./assets/js/main.js),且你已起本地 HTTP 服务(python -m http.server 或 VS Code Live Server)。
-
muffet默认只处理http://和https://协议,所以必须先起服务,让模板可通过http://localhost:8000/index.html访问 - 扫描命令要加
--timeout 5和--max-connections 20,避免本地文件响应慢被误判为超时 - 排除非 HTML 资源干扰:
muffet --exclude ".*\.(png|jpg|gif|svg|pdf)$" http://localhost:8000/ - 若报错
connection refused,说明服务没起来;若大量404但路径看起来没错,大概率是/开头的绝对路径在本地服务下解析错了基准目录
用 Python 脚本检查未起服务的纯 HTML 文件
适合 CI 流程或离线审核:不依赖服务器,直接解析 HTML 中所有 href、src,拼出完整路径后检查文件是否存在。
- 关键逻辑是:把 HTML 文件所在目录作为根,对每个相对路径调用
os.path.join(os.path.dirname(html_path), relative_url) - 跳过以
http://、https://、//开头的 URL(这些留给线上扫描) - 注意
../回退层级不能超出项目根目录,否则判定为无效路径(比如src="../../../bad.png") - 示例片段:
from pathlib import Path<br>html = Path("templates/page.html")<br>for link in soup.find_all(["a", "link", "img", "script"], href=True) + soup.find_all(["img", "script"], src=True):<br> url = link.get("href") or link.get("src")<br> if url and not url.startswith(("http://", "https://", "//")):<br> target = html.parent / url<br> if not target.exists():<br> print(f"MISSING: {url} (from {html.name})")
浏览器 Network 面板里看真实请求 URL
这是最准的“最终判决”——无论你怎么写 src 或 href,浏览器发出的请求地址才是它真正想找的地方。
立即学习“前端免费学习笔记(深入)”;
- 打开开发者工具 → Network → 刷新页面 → 筛选
Doc(检查跳转)、Img(检查图片)、JS(检查脚本) - 重点看状态码是
404还是302:前者是文件真没了,后者说明有重定向,得追到终点再判断 - 右键点击某条 404 请求 → “Copy” → “Copy request URL”,粘贴出来就是浏览器算出来的绝对路径,和你写的原始值对比,立刻看出是路径写错、漏了
./,还是服务器路由配置问题 - 常见陷阱:
src="images/logo.png"在/blog/post.html里会被解析成http://site.com/blog/images/logo.png,而不是你认为的网站根目录下的/images/
真正卡住人的从来不是工具不会用,而是把 ./ 当可选项、把双击打开 HTML 当调试方式、把模板变量未渲染当成路径错误——这些细节不盯死,扫十遍 muffet 也修不完。



















