27g3(如提示需要,请输入)
这个工具解决什么问题
站点做到两百个页面之后,问题就不再是「写什么」,而是「哪个页面被漏掉了」。新上的活动页、改版时保留下来的旧栏目页、运营顺手建的落地页,往往只存在于某个人的收藏夹里——站内没有任何一个页面链接到它,搜索引擎顺着链接爬不到,用户也点不到,只有拿着地址直接访问才打得开。这类页面在后台看着「已发布、正常」,实际上等于不存在。另一头是层数:从首页开始一层层点下去,有的详情页要经过「栏目 → 列表 → 专题 → 子专题」四五个跳转才到得了,权重被一层层稀释,抓取频率也低。这两个毛病在浏览器里都看不出来:你得手工点开每一个页面、抄下它链到哪里、再反推谁链到它,两百个页面就是两百次重复劳动,抄完还不一定对。真正做一遍的人都知道,这件事靠人工是做不完的,只能靠工具把整张图画出来。
- 原来的做法:在浏览器里一页页点开,用眼睛看导航和正文里有没有指向目标页的链接;或者把页面源码复制到表格里,手工搜索地址片段。两百个页面做一遍要大半天,站点一改版又得重来。
- 用这个工具:填上站点首页,点一次「开始体检」,程序按宽度优先顺序把同域页面走一遍,记录每一条站内链接,算出每个页面的入链数、出链数和点击深度;再读站点地图,把「登记了但没人链」的页面单独标成孤岛。结果表可排序可筛选,右边一张按深度分列的关系图,一眼看出结构哪里塌了。
- 省下来的:内置的演示站有 20 个页面、60 条站内链接,一轮体检不到三秒;同样的事人工做一遍是半天起步,而且改版之后要重做。真正省下来的不是这半天,是「改版后敢不敢确认内链没断」这件事——以前只能靠感觉,现在跑一次就有结论。
技术实现
这个工具的技术难点不在界面,而在「怎么把一张站点图算对」。三件事必须做对:第一,同一个页面会有多种地址写法(带不带 www、末尾带不带斜杠、index.html),不去重就会把站内链接数算成两倍;第二,入链数不能边抓边累加,因为先抓到的页面永远拿不到后来者给它的投票,必须等整轮抓完再统一反向索引;第三,点击深度要用广度优先才有意义,深度优先第一次走到某个页面的路径往往不是最短路径。零第三方依赖是刻意选择:整个工具只用标准库,编译出的 exe 不需要用户装任何运行库,也不会因为某个包的版本变化突然坏掉。爬取是串行带间隔的,宁可慢,也不给别人的站点造成压力。
- 地址归一:先有「同一个页面」的定义,才谈得上入链数:页面身份键做了四件事:主机名去 www、路径末尾去斜杠、把 /index.html、/index.php、/default.asp 这类默认文档归并到目录、保留查询串(?id=1 与 ?id=2 是两个页面,不能合并)。不这么做的后果很具体:站点里 /about 与 /about/ 会被算成两个页面,各自只有一半入链,看着像两个孤岛。锚点(#后面的部分)在归一阶段就丢掉——它不构成另一个页面,但会被大量「回到顶部」链接带进来,不丢掉的话首页入链数能虚高几十倍。
- 只认 <a href>,不认正文里出现的网址:用 html.parser 写了一个只关心 a / area / base / title 的解析器。为什么不用正则扫全文:文章正文里出现的网址(示例、引用、代码块里的链接)不是页面结构的一部分,算进内链图会让「入链数」彻底失真,而这种错误在结果里完全看不出来。base 标签必须尊重——有些站点用它把相对路径整体改到另一个目录,忽略它会让整站的链接全部解析到错误位置。rel 里带 nofollow 的链接会记下来但不计入入链:它确实是一个链接(用户点得到),但它不传递权重,而本工具判断孤岛用的正是「有没有人给它投票」。
- 广度优先,深度才是「最少点几下」:用队列做 BFS:首页入队深度 0,出队时把它指向的页面以「当前深度+1」入队,已经访问过的页面不再入队。这样每个页面第一次被访问时的深度,就是从首页出发的最短跳数。换成深度优先(递归往下钻)也能遍历整站,但第一次到达某个页面的路径可能是绕远的,算出来的深度会偏大,用户按这个去改内链会改错地方。深度 ≥3 层的页面会被标成「深埋」,这个阈值对应「首页 → 栏目 → 列表 → 详情」的通行结构。
- 入链统一反向索引,边抓边算会算错:爬取过程中只记录「谁链到谁」,等整轮抓完再做一次反向索引,把每条 dofollow 边的目标页面加上一个来源。原因是顺序问题:第 3 个被抓的页面可能被第 15 个页面链接,边抓边累加时它拿不到这一票,结果就少一条。这个 bug 的症状特别隐蔽——入链数普遍偏小,看着像是「站点内链本来就少」,不对比就发现不了。自测里专门有断言:同一站点抓两次,两次的统计结果必须完全一致。
- 孤岛页只能靠站点地图发现:一个页面如果没有任何内链指向它,顺着链接是永远走不到的——这正是孤岛的定义,也是它的悖论。所以本工具先读 robots.txt 里的 Sitemap: 行(没有就试 /sitemap.xml,支持一层 sitemapindex 索引),把登记的地址取出来,等 BFS 走完再把「登记了但没走到」的页面单独抓一次。这一步同时给出两个结论:这个页面还在不在(状态码),以及它有没有入链(孤岛判定)。站点地图缺失时本工具不会假装能发现孤岛,结论行会直接写「未找到站点地图」。
- robots.txt 按 RFC 9309 判,不做「删掉星号」的偷懒实现:读 robots.txt 是爬虫的底线。实现上处理了四件容易出错的事:Allow 与 Disallow 同时命中时取最长匹配(同长度时 Allow 优先,这是 RFC 9309 的明确规定,判反了会把公开目录整片误拦);* 通配要编成正则而不是删掉;结尾的 $ 才表示锚定,出现在中间是普通字符;具名 User-agent 分组优先于 *。被规则拦住的页面不会去请求,结果表里标成「robots 禁止」——用户看到这条会知道是自己站点规则挡的,不是工具坏了。
技术栈:Python 3.8+、tkinter 窗体、标准库零依赖、BFS 广度优先爬取、robots.txt 遵循
已知局限:只分析静态 HTML:链接如果是 JavaScript 渲染出来的(点一下才加载、或整站由前端框架生成),本工具看不到,这类站点请改用带浏览器内核的采集方式。不判断链接指向的页面内容质量,只统计结构与状态码。不做并发,串行 + 间隔是刻意选择,页数多时耗时按「页数 × 间隔」估算,60 页、0.3 秒间隔大约 20 秒。点击深度以起始地址为第 0 层,若从栏目页而非首页开始体检,深度含义随之改变。站内判定按主机名去 www 比较,子域名(如 blog.example.com 与 www.example.com)视为两个站点,不做合并。
同类软件对照
下面几款都是公开可查的同类软件,定位各不相同。这里只说明各自的定位,以及本工具在其中的位置,方便你判断哪一类更契合自己的用法。
| 软件 | 它的定位 | 本工具的定位 |
|---|---|---|
| Screaming Frog SEO Spider | 桌面端站点爬虫,输出结构化的抓取清单(状态码、标题、内链、深度等),可导出多种格式 | 本工具只做一件事:把站内链接关系画成图并标出孤岛与深埋页,界面是「表格 + 关系图」两页,不需要配置抓取规则 |
| Xenu's Link Sleuth | 老牌桌面链接检查工具,主要报告死链与断链 | 本工具的重点不是死链数量,而是「谁链到谁」:入链数为零的页面、点击深度过大的页面会被单独标出并画进关系图 |
| Google Search Console(链接报告) | 官方提供的站点内链与外部链接报告,需要先验证站点所有权,数据有延迟 | 本工具在本机即时运行、不需要任何账号或验证,能看到当前这一刻的站内结构;代价是它只反映静态 HTML 里的链接 |
| W3C Link Checker | 在线链接检查服务,提交一个地址后检查页面里的链接是否可访问 | 本工具在本机跑完整站点、并统计入链与深度;对需要体检内网或未公开站点的场景更合适 |
以上仅作定位对照,各软件的可用性、授权方式与功能范围请以其官方页面为准。
操作教程
- 填上站点首页
在顶部输入框里填站点地址,比如 https://www.example.com/。不写 http:// 也能识别,程序会自动补。如果你的站点首页在子目录(比如 /blog/),填那个地址即可,深度会以它为第 0 层。
预期结果:输入框里出现完整的网址。 - 设页数上限与请求间隔
「最多抓」默认 60 页,按站点规模调。第一次体检建议先抓 60 页看结构,确认没问题再放宽。「间隔」是每抓一页之后停多久,默认 0.3 秒;站点在国外或比较慢时调到 0.5~1 秒更稳妥。
预期结果:两个数字被记住,下一次体检沿用。 - 点「开始体检」
程序先读 robots.txt 与站点地图,再从首页按宽度优先顺序往下走。底部状态栏实时显示正在抓哪个地址、已抓几页。中途可以点「停止」,已经抓到的数据仍然会出一份结果(结论行会注明是部分数据)。
预期结果:进度条走到头,结论行出现「共 N 页 · 内链 M 条 · 最深层级 K · 孤岛 X · 深埋 Y · 死胡同 Z」。 - 在「页面清单」里找问题
点表头可以按任一列排序:点「入链」升序,入链最少的排最前,排在前面的就是最该处理的页面;点「层级」倒序,最深的页面排最前。右上角的下拉框可以直接筛「只看孤岛页」「只看深埋页」「只看死胡同」「只看打不开的」。
预期结果:红字是孤岛页,蓝字是深埋页,橙字是打不开的页,灰色是从首页走不到的页。 - 切到「内链关系图」看结构
图按点击深度分列:最左是首页,往右一层层变深;「走不到」的页面单独放在最左边一列。点图上的方块会把表格定位到对应那一行,点表格行也会在图上高亮对应节点。一列特别厚说明这一层页面太多、需要加中间页;大量节点堆在最左边说明它们没有入口。
预期结果:看到一张能对着站点结构读的图,节点颜色与表格里的结论一致。 - 导出 CSV 留档
点「导出 CSV…」选保存位置,得到一份带 BOM 的表格(Excel 双击不乱码)。建议改版前后各导一次,用两份表对比「入链数有没有掉」「孤岛有没有变多」。
预期结果:得到 8 列的 CSV:地址、状态码、点击深度、入链数、出链数、标签、在站点地图、标题/错误。 - 先看演示站点再上手
第一次用不确定填什么,就点「载入演示站点」:程序会在本机起一个 20 页的小网站并自动体检一轮,里面有孤岛页、只有 nofollow 内链的页、五层深的报告页、死胡同、404 出链和被 robots 禁止的目录,正好把各条结论都演一遍。
预期结果:本机演示站跑完,表格 20 行、结论行显示孤岛 2 个,关系图分 6 列。
常见问题
技术实现与后续维护
程序分三层:抓取层(robots 判定、HTTP 请求、HTML 解析)、模型层(页面节点、边、反向索引、指标)、界面层(表格、关系图、导出)。三层之间没有反向依赖,模型层可以完全脱离窗口测试——工程里的自测有 125 项断言,全部不碰窗口,且只访问本机演示站点。后续维护最需要盯两处:一是地址归一函数,任何改动都要跑「带 www / 不带 www / 末尾斜杠 / index.html」这组用例,归一错了会连带把入链数、孤岛判定、深度全部带偏;二是反向索引那一步,千万不要为了「实时显示」改成边抓边累加,那会让入链数系统性偏小。关系图的布局是确定性的(按深度分列),改动布局时保持这个性质,否则每次截图都不一样,说明配图就对不上了。
运行环境:
运行环境:Windows 10/11(64 位),无需安装 Python、无需任何运行库。程序已打包成单个可执行文件,解压后双击即可运行,不写注册表、不装服务。体检时会访问你填写的站点,除此之外不向任何地方发请求。
可扩展方向:
- 加「只看某个栏目」的过滤:按路径前缀筛选,把大型站点拆成几块分别体检
- 加「两次体检对比」:导入上一次导出的 CSV,直接列出「新增孤岛」「入链数下降」的页面
- 加「推荐内链」:对孤岛页按标题关键词与站内其它页面的相似度,给出「在哪几页加链接」的建议
- 加「锚文本统计」:记录每条内链用的锚文本,看是否存在大量「点击这里」这类无意义锚文本
- 加「导出关系图」:把当前画布导出成 PNG 或 SVG,便于贴进周报与改版文档
本工具免费提供使用,但不对外分发源码。如果你需要在本工具基础上做功能调整、对接内部系统或长期维护,可以联系我们做二次开发,源码与工程文档可在定制合作中一并交付。
需要其它功能?可以定制
这个工具只做一件事:站点上了两百多个页面,哪些页面一条内链都没有、哪些要点四五层才点到,肉眼翻页面根本看不出来。如果你的场景还需要别的处理,可以联系我们做二次开发,按你的实际数据格式和流程定制。
常见的定制需求:
- 多站点批量体检:把公司几个子站的地址排进队列,早上跑一轮,出一张「哪些站点有孤岛页」的汇总表
- 接入已有运维脚本:体检完自动把孤岛页清单写成工单,派给对应栏目的负责人
- 按公司口径定制判定规则:比如「深度 ≥2 就算深埋」「入链 <2 就算薄弱」,做成内部统一口径的版本
- 与站点地图生成流程结合:体检发现孤岛页后,反过来提示该把它从站点地图里移除或补内链
- 联系方式:邮箱/微信见站内「联系我们」页面,或在本文下方留言
- 定制说明:请附上你的数据样例(脱敏即可)和期望结果,方便快速评估工作量
- 交付形式:定制项目可交付可执行程序,按需一并交付源码与工程文档,支持长期维护
使用说明与免责声明
- 本工具仅用于采集公开可见或你自身拥有权限的数据。
- 请遵守目标网站的服务条款、robots 协议及《网络安全法》等相关法律法规。
- 请合理控制请求频率,不要对目标站点造成访问压力。
- 不得用于采集个人隐私、付费墙内容或任何受法律保护的非公开数据。
- 因使用不当造成的后果由使用者自行承担;本工具不做数据二次分发。
27g3(如提示需要,请输入)
