那天下午,我对着终端上跳出的“Score: 80/100,Grade: B”愣了几秒。这个名叫SEOCORE的小工具是我亲手写的,它爬了一遍 example.com,告诉我这个站点没什么大问题——标题有、报告生成、快照对比也有模有样。可就在几分钟前,我手动检查了同一个页面:元描述缺失,规范链接没设置,robots.txt 根本不存在。一个连基础标签都残缺的页面,怎么会被自己的工具评为“良好”?这一刻我才意识到,我被自己写的爬虫骗了。
SEOCORE 最初是给我自己用的一次性脚本,出发点很朴素:我需要一个端到端能跑通的 SEO 分析器,不必依赖任何云服务,每一行逻辑我都看得懂。于是我用一个周末搭出了第一版,七百来行的代码,塞进了类、接口、配置对象、站点地图解析、结构化输出、HTML 报告和快照差异对比。跑起来的样子像模像样:终端打印审计开始、爬取首页、输出评分和等级,最后把报告保存到本地目录。表面看起来,这已经是一个可用的产品了。
![]()
但正是这套“干净输出”把孱弱的内核包裹得太好,让我持续相信自己工具的判断。而实际上,它的底层有三个精准又隐蔽的错误,每一个都不致命,却足以让整个评估体系失去参考意义。
第一个问题出在重定向处理上。老版本的配置里硬编码了“followRedirects: false”,并且当服务器返回 300 到 400 之间的状态码时,脚本直接终止爬取。这意味着任何一次合规的 301 永久移动或 302 临时跳转,都会被当作失败信号,导致整个站点分析半途而废。一个真实网站如果刚刚做过域名迁移或结构调整,SEOCORE 可能连首页都跑不完就停了,而当时我丝毫没有察觉,因为脚本从不报错,只是静默退出。
第二个隐患藏在元描述的提取逻辑里。代码用了一连串降级选择器:先从标准的 meta[name="description"] 找,找不到就换 meta[property="description"],再不行就用 og:description 顶替。问题在于,后面两个根本不是元描述的正确字段。如果一个页面缺了正经的描述标签,但恰好开放图谱标签里填了内容,报告里就会显示“元描述存在”,实际上搜索引擎读取不到任何有效的 description。糟糕的是,这种误判完全发生在后台,前端报告看不出任何异常,我一度以为自己的爬虫在 SEO 检查上精准无误。
第三个 bug 最根本,也最危险。评分算法是一连串拍脑袋的扣分:满分 100,没有标题扣 15,没有元描述扣 10,没有 H1 标签再扣 15。没有严重程度模型,没有分类拆解,没有任何证据链条——输出仅仅是一个看起来很有权威的数字。比如 85 分,用户本能会觉得“还不错”,但这份“不错”的背后,可能是一个缺了标题、用错了规范链接、站内链接全部断裂的页面,仅仅因为其他无关紧要的项凑足了分数。这正是旧工具最糟糕的一点:它不是残缺,而是充满自信地给出错误结论。
一段时间里,我靠这两个“闪光点”欺骗自己:爬行图分析能看到页面之间的引用关系,快照差异对比能捕捉改版前后的变化。正因为这两块真实有用,我忽略了整个地基已经歪了。直到一次对某个内容站做季度复盘时,我对照人工审计发现了多处矛盾,才决定把诊断逻辑全部翻开检查一遍。查完之后,我删掉了那个让我信任了几个月的老版本。
重建的核心目标不是增加新功能,而是先让工具变得可信。我把 SEOCORE 从零星的 Node.js 脚本迁移到了 TypeScript 命令行接口,结构上不再模糊,每一步分析必须携带上下文和修复建议,而不是合进一个模糊的综合分。新版本可以真实地爬取在线站点,正确处理重定向和 robots.txt 规则,遇到依赖前端渲染的页面会启动无头浏览器等待执行完毕再抓取。报告不再用一个“分数+等级”打发用户,而是列出具体问题、所在页面、影响范围和推荐的修改方式。
这依旧是个个人项目,规模没有大到能跟商业套件掰手腕,但它守住了我最初那个“端到端看得懂”的底线。更重要的是,它不再假装一切安好。一个没有元描述的页面,现在会明确指出标签缺失、影响哪些搜索引擎的展示、优先级如何,而不是躲在“B 级”的面具后面。信任不是靠报告的美观度建立的,是当工具敢在你面前说“这里不行”的时刻,你依然愿意继续用它。
特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.