[{"data":1,"prerenderedAt":274},["ShallowReactive",2],{"blog-custom-crawler-dead-links":3,"blog-prev-custom-crawler-dead-links":91,"blog-next-custom-crawler-dead-links":187},{"id":4,"title":5,"author":6,"body":7,"canonical":75,"category":76,"cover":75,"date":77,"description":78,"draft":79,"extension":80,"keywords":75,"meta":81,"navigation":82,"noindex":79,"ogImage":75,"path":83,"seo":84,"seoDescription":75,"seoTitle":75,"stem":85,"tags":86,"updated":75,"__hash__":90},"blog\u002Fblog\u002Fcustom-crawler-dead-links.md","几千个页面的死链，我们为什么自己写脚本查","元析智能",{"type":8,"value":9,"toc":66},"minimark",[10,14,18,21,24,27,30,33,36,39,42,45,48,51,54,57,60,63],[11,12,13],"p",{},"2025 年 12 月我们查一个一万两千页的文档站，历史死链积了两千多条，运维照着工具列表改了一周也没改完。站一旦上万页，查死链这件事工具就不够用了。免费版爬虫有 500 个 URL 的上限，付费版能爬完，但只告诉你哪些链接返回 404，不告诉你先修哪个。我们后来写了个八十行的脚本，解决的是排序问题。",[15,16,17],"h2",{"id":17},"现成工具卡在哪",[11,19,20],{},"爬取能力不是问题，判断规则是。工具把死链列成一张表，几千行，按发现顺序排。运维看一眼就头大，最后挑前十条改，剩下的放着。",[11,22,23],{},"另一件事是死链的价值不一样。从导航链过去的 404 和内页深处一个没人点的 404，处理优先级差很远。工具不做这个区分，因为它不知道你的业务。",[15,25,26],{"id":26},"脚本做什么",[11,28,29],{},"先读站点地图拿到全量 URL，再爬每个页面的出链，拼成一张内链图。然后并发发 HEAD 请求，记录状态码、跳转链、响应时间。",[11,31,32],{},"拿到结果后排序：来源页是不是首页或导航可达、这个 404 被蜘蛛抓过多少次、来源页本身有多少条内链。这几个数据日志里都有，拼起来就是优先级。",[11,34,35],{},"输出一张 CSV，前二十行直接进工单。我们处理完一批，脚本再跑一次，看哪些新冒出来。",[15,37,38],{"id":38},"三个坑",[11,40,41],{},"第一，HEAD 请求会被部分防火墙拦，返回 403，看着像坏链其实没错。改用 GET，只读前几 KB 就断开。",[11,43,44],{},"第二，不带 UA 的请求会被当成攻击。把 UA 改成带标识的，并且把并发压到 10 以下。",[11,46,47],{},"第三，301 可能是一串。从 A 跳到 B 再到 C，脚本要跟到底，只报最终状态。我们见过三跳的跳转链，第一跳修了，第二跳还在。",[15,49,50],{"id":50},"脚本的价值在排序",[11,52,53],{},"发现死链这件事，工具一秒能给你一万条。修哪一千条、按什么顺序修，才需要判断。",[15,55,56],{"id":56},"和现成监控服务的区别",[11,58,59],{},"市面上的死链监控服务是持续跑的，发现新 404 就告警。它解决的是别断，不解决先修哪个。我们两边都用：监控盯线上，脚本每月跑一次做排序。",[11,61,62],{},"监控服务还有个副作用，老站本来就有几百条历史死链，一接上就天天告警，最后没人看。先清一轮历史再接监控，告警才有人理。",[11,64,65],{},"我们现在的流程是每个月跑一次，按优先级修前 100 条，剩下的记录在案，等下次重建导航时一起处理。用了半年，站内 404 从 2400 多条降到 300 条以内，被抓取浪费掉的频次也明显少了。",{"title":67,"searchDepth":68,"depth":68,"links":69},"",2,[70,71,72,73,74],{"id":17,"depth":68,"text":17},{"id":26,"depth":68,"text":26},{"id":38,"depth":68,"text":38},{"id":50,"depth":68,"text":50},{"id":56,"depth":68,"text":56},null,"工具评测","2025-12-30","免费版爬虫有 500 URL 上限，付费版能爬但只报状态码。站上一万页、要按流量和权重排优先级时，八十行脚本更管用，这篇写脚本做什么和三个坑。",false,"md",{},true,"\u002Fblog\u002Fcustom-crawler-dead-links",{"title":5,"description":78},"blog\u002Fcustom-crawler-dead-links",[87,88,89],"死链检测","自动化脚本","内链","-FaJsdcVmaQFc6e6A0s_n6Lw1yx6rkhcN6zYlA4rjE4",{"id":92,"title":93,"author":6,"body":94,"canonical":75,"category":175,"cover":75,"date":176,"description":177,"draft":79,"extension":80,"keywords":75,"meta":178,"navigation":82,"noindex":79,"ogImage":75,"path":179,"seo":180,"seoDescription":75,"seoTitle":75,"stem":181,"tags":182,"updated":75,"__hash__":186},"blog\u002Fblog\u002Fbaidu-api-index-submission.md","百度普通收录 API：从手动提交到脚本自动跑",{"type":8,"value":95,"toc":167},[96,99,102,105,115,118,121,124,127,131,134,137,140,143,146,149,152,155,158,161,164],[11,97,98],{},"手动提交 URL 费时还容易漏。我们把百度普通收录 API 接进发布流程，每天自动推 30 条，半年省下约 40 小时。接口本身很简单，难在提交策略。",[15,100,101],{"id":101},"接口长什么样",[11,103,104],{},"百度普通收录 API 是一个 HTTP 请求，site 和 token 在搜索资源平台后台拿：",[106,107,112],"pre",{"className":108,"code":110,"language":111},[109],"language-text","curl -H 'Content-Type:text\u002Fplain' \\\n  --data-binary @urls.txt \\\n  'http:\u002F\u002Fdata.zz.baidu.com\u002Furls?site=https:\u002F\u002Fwww.example.com&token=xxx'\n","text",[113,114,110],"code",{"__ignoreMap":67},[11,116,117],{},"urls.txt 一行一条 URL，返回 JSON，里面有本次成功条数和剩余配额。就这么点东西，20 行脚本能跑通。",[15,119,120],{"id":120},"我们的脚本怎么跑",[11,122,123],{},"发布流程里加一步：新内容上线后，脚本从数据库取当天新增的 URL，过滤掉重复提交过的，拼成 urls.txt，调接口，把返回结果记日志。",[11,125,126],{},"两个细节。一是去重表，同一个 URL 只推一次，重复推不增加收录，还浪费配额。二是失败重试，接口偶尔超时，脚本第二天自动补推，不人工介入。",[15,128,130],{"id":129},"提交策略只推这四类-url","提交策略：只推这四类 URL",[11,132,133],{},"配额有限，什么 URL 都推等于没推。我们只推四类：新发布的文章、新上线的产品页、有搜索需求但还没收录的页面、更新过核心内容的老页面。",[11,135,136],{},"不推的：分类页、标签页、分页、搜索结果页、参数页。这些页面推了也大概率不收，收了也是低质页面。",[15,138,139],{"id":139},"快速收录和普通收录别搞混",[11,141,142],{},"搜索资源平台里有两个接口：普通收录和快速收录。快速收录不是所有站都有，需要站点有相应权益，别照着旧教程硬调，调不通先看后台有没有这个入口。",[11,144,145],{},"普通收录是保底的。我们所有站都接普通收录，快速收录只给有权益的站配，两者不冲突。",[15,147,148],{"id":148},"常见错误码",[11,150,151],{},"返回 401 是 token 不对；403 是配额用完或者站点没验证；400 常见于 URL 格式错误，比如带空格、没写协议头。",[11,153,154],{},"还有一个坑：同一批里有一条 URL 格式不对，整批可能失败。我们的脚本会先做格式校验，再提交。",[15,156,157],{"id":157},"效果和一个提醒",[11,159,160],{},"2025 年 8 月接入，到今年 1 月正好半年。一个 800 页的站，接 API 之前手动提交，一周推 60 条左右，收录周期 5 到 9 天。接完之后每天推 30 条，收录周期缩到 3 到 6 天，人工投入几乎为零。",[11,162,163],{},"提醒一句：提交只是告知，不是保证收录。我们见过客户每天推满配额，收录率还是不到 30%，问题在页面质量，不在接口。先把页面做好，再用 API 提效，顺序别反。",[11,165,166],{},"半年复盘：这个站的人工提交时间从每周 70 分钟降到 5 分钟，收录周期稳定在 3 到 6 天。今天这篇就是脚本自动推的，推完 4 天收录。对一个日更的站，这个时间差会放大，人工根本盯不过来。",{"title":67,"searchDepth":68,"depth":68,"links":168},[169,170,171,172,173,174],{"id":101,"depth":68,"text":101},{"id":120,"depth":68,"text":120},{"id":129,"depth":68,"text":130},{"id":139,"depth":68,"text":139},{"id":148,"depth":68,"text":148},{"id":157,"depth":68,"text":157},"技术SEO","2025-12-29","手动提交 URL 费时还容易漏。我们把百度普通收录 API 接进发布流程，每天自动推 30 条，半年省下约 40 小时。接口用法、提交策略、常见错误码和踩过的坑，这篇一次讲完，最后一节是我们半年后的复盘，照着做能省出每周一小时。",{},"\u002Fblog\u002Fbaidu-api-index-submission",{"title":93,"description":177},"blog\u002Fbaidu-api-index-submission",[183,184,185],"百度收录","API","自动化","ryB5loOd061VIlJKAxV1Q26u0OTCmcRbqDzd7DNpNLk",{"id":188,"title":189,"author":6,"body":190,"canonical":75,"category":175,"cover":75,"date":263,"description":264,"draft":79,"extension":80,"keywords":75,"meta":265,"navigation":82,"noindex":79,"ogImage":75,"path":266,"seo":267,"seoDescription":75,"seoTitle":75,"stem":268,"tags":269,"updated":75,"__hash__":273},"blog\u002Fblog\u002Fjson-ld-article-faq-fields.md","文章和问答的结构化数据，五个字段最容易写错",{"type":8,"value":191,"toc":254},[192,195,198,201,205,212,215,218,222,225,229,236,239,242,245,248,251],[11,193,194],{},"结构化数据报错，九成不是 JSON 语法错，是标记的内容和页面可见内容对不上。校验器能过，不等于搜索引擎认。下面五个字段是我们改客户站时最常返工的。",[15,196,197],{"id":197},"headline",[11,199,200],{},"必须和页面 H1 一致，长度控制在 110 个字符以内。常见错法是把 title 标签整串塞进去，带上\" | 品牌名\"后缀，或者为了关键词硬改 H1。headline 和 H1 不一致，Google 会以页面为准，标记被判无效。",[15,202,204],{"id":203},"datepublished-和-datemodified","datePublished 和 dateModified",[11,206,207,208,211],{},"格式必须是带时区的 ISO 8601，比如 ",[113,209,210],{},"2026-01-15T09:00:00+08:00","。只写日期也能过校验，但改造过的旧文章如果 dateModified 早于 datePublished，整条标记作废。这两项要和页面上显示的发布时间对得上，别为了\"显得新\"改日期。",[15,213,214],{"id":214},"author",[11,216,217],{},"文章署名是公司就用 Organization，个人就用 Person，name 必须和页面上署的名字一字不差。我们见过 320 篇文章的 author 全写着 \"Admin\"，GSC 报告里全报作者无效。",[15,219,221],{"id":220},"faq-主体","FAQ 主体",[11,223,224],{},"Question 的 name 是问题原文，acceptedAnswer 的 text 是答案正文，必须和页面可见的问答内容一致。答案里如果要保留加粗，用受支持的标签，别塞自定义组件。还有一条容易忽略：页面上要有真实的问答区块，不能只在 JSON-LD 里写问答，页面正文根本没有——这属于作弊，会被判垃圾结构化数据。",[15,226,228],{"id":227},"inlanguage","inLanguage",[11,230,231,232,235],{},"和页面语言一致。多语言站很容易漏，中文页写了 ",[113,233,234],{},"en","，整条标记作废。",[15,237,238],{"id":238},"怎么查才快",[11,240,241],{},"三件事就够了。第一，Rich Results Test 跑单页，直接告诉你哪条字段无效，但它不覆盖全部类型。第二，GSC 的\"增强功能\"报告按类型汇总全站错误，一次能看几百条，适合批量修。第三，把页面源码里的 JSON-LD 抠出来过一遍 JSON 校验，语法错通常死在这里，比如尾逗号、双引号没转义、时间字段写成中文日期。",[11,243,244],{},"我们的做法是把 JSON-LD 做成模板函数，入参是标题、作者、发布时间、封面图，前端统一调用，模板一改全站生效。手写 JSON-LD 的站，改完 300 篇能漏 80 篇。",[15,246,247],{"id":247},"一个判断",[11,249,250],{},"FAQ 的富媒体展示从 2023 年 8 月起就大幅收缩了，普通商业站基本看不到问答展开样式。所以别为了标记硬造问答，页面上本来没有 FAQ 就别加。Article 标记相反，成本低、一直有效，每篇文章都该有。",[11,252,253],{},"还有 Organization 和 BreadcrumbList，前者放在全站模板，后者跟着导航走。四类标记，一套模板解决，不用一篇篇手写。",{"title":67,"searchDepth":68,"depth":68,"links":255},[256,257,258,259,260,261,262],{"id":197,"depth":68,"text":197},{"id":203,"depth":68,"text":204},{"id":214,"depth":68,"text":214},{"id":220,"depth":68,"text":221},{"id":227,"depth":68,"text":228},{"id":238,"depth":68,"text":238},{"id":247,"depth":68,"text":247},"2025-12-31","FAQ 富媒体展示早就收紧了，Article 标记却一直值得做。我们按真实报错整理出五个最常写错的字段：headline、日期、author、FAQ 主体、语言，每个给正确和错误写法。",{},"\u002Fblog\u002Fjson-ld-article-faq-fields",{"title":189,"description":264},"blog\u002Fjson-ld-article-faq-fields",[270,271,272],"结构化数据","JSON-LD","Article","MaikUshocMuPFKqdfdiF3sOundW55OcmZuYC0xfWxZE",1794088109627]