ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

构建Agent友好网站:从爬虫对抗到AI共生的完整指南

构建Agent友好网站:从爬虫对抗到AI共生的完整指南 先说说我为什么会碰这个问题。上个月我在调一个基于LangChain的资讯搜集Agent目标是让它自动抓取几个行业网站的更新并生成摘要。结果跑了不到一天Agent要么拿到一堆空壳HTML要么被WAF拦在门外要么面对满屏的登录弹窗直接“思考失败”。那几天我改提示词、调超时参数、换浏览器模拟越调越觉得问题根本不在Agent这边而在网站本身——很多网站压根没打算让程序好好读它。后来我索性换了个思路抛开“爬虫对抗”的旧观念直接站在网站所有者的角度去研究“怎样构建一个Agent-friendly的网站”。这个方向反而想通了很多事。今天这篇就把我这段时间的实践整理出来从Agent怎么“看”网站讲起到具体改造手段再到验证方法全程都是可复用的实操内容。1. Agent到底怎么“看”你的网站很多站长对“Agent访问网站”的理解还停留在“爬虫抓网页”的层面。实际上大模型驱动的Agent访问网站的方式和你我打开浏览器的方式有着本质区别。搞清楚这个区别才谈得上做Agent-friendly改造。1.1 从一次真实抓取看Agent的浏览路径去年年底我帮朋友调试一个房产信息Agent目标是从某个楼盘列表页提取在售房源。Agent的调用链大概是这样的先请求首页解析出各个楼盘的详情链接再逐个请求详情页把正文内容交给大模型做结构化提取。听起来很常规对吧但实际跑起来几乎每一步都在翻车。首页拿下来之后Agent拿到的是一个只有几行JS脚本的骨架页面真正的房源列表是前端通过接口异步渲染的。Agent去找a标签什么也没找到。这就是最典型的问题Agent不会像人一样自动执行JavaScript并等待页面渲染完。市面上虽然有Playwright这类浏览器自动化工具但让Agent每次都驱动一个完整浏览器成本高、速度慢而且稳定性很差。第二次尝试我改用了带渲染的抓取方案用Playwright无头浏览器去打开页面。列表倒是出来了但页面上有大量的“委托代理”“降价通知”等悬浮组件加上几十个图片懒加载占位符整个DOM文本被截断到十几万字符。Agent光解析这个页面就消耗了大量token而且有效信息被淹没在噪声里。那次任务最后的结果是一个小时的调用花了大概3美元的API费用提取出来的房源信息还有三处明显错误。1.2 Agent的“阅读”习惯线性、片段化、无视觉人类浏览网页时是视觉驱动的我们扫一眼就能忽略广告、跳过导航栏、直接定位正文区域。但Agent不是这样它拿到的是经过处理的文本流——要么是curl抓到的原始HTML要么是经过程序抽取后的正文片段。它的处理方式是线性的更像是在读一本没有目录、没有排版、插图全变成alt文本的书。这就带来了几个Agent认知网站时的显著特征极其依赖文本结构标题层级、段落关系、链接锚文本这些在人类眼里只是排版在Agent眼里是理解页面语义的路标。对噪声极不敏感但会被噪声干扰网页里的广告、推荐模块、页脚友情链接人类会自动忽略Agent却会把这些内容当正文处理。token预算是个硬约束一个页面5000字还是50000字对Agent来说不只是速度快慢的问题直接关系到任务能不能跑通。Token超过上下文窗口Agent会丢前面的内容最后给你一个莫名其妙的总结。这里要强调一个很容易被忽略的点Agent的上下文窗口不是无限的。即便最新的模型支持超长上下文长度增加会显著影响推理质量和响应速度而且费用是线性上升的。所以Agent-friendly的核心目标之一就是用尽可能少的token传递尽可能多的有效信息。1.3 为什么“对爬虫友好”不等于“对Agent友好”传统的爬虫友好通常指robots.txt写得清楚、静态页面可抓取、链接可追踪。这套规则对搜索引擎爬虫够用对AI Agent却远远不够。搜索引擎爬虫拿回页面之后是由算法做关键词匹配和链接分析而Agent拿回页面之后是要让大模型“读懂”页面里的业务逻辑和实体关系。举个例子传统SEO要求每个页面有唯一的title和meta description这对搜索引擎很重要但对Agent来说更重要的是页面里有没有清晰的实体标注比如商品价格、库存状态、发货时间这些关键字段能不能直接被识别出来。如果这些信息只存在于图片里或者只靠CSS样式暗示比如红色表示售罄搜索引擎可能还勉强过得去Agent就彻底无能为力了。另外还有一层差异搜索引擎爬虫对内容重复的容忍度较高大不了给你降权Agent面对重复内容、空转链接、死循环跳转会直接判定这个网站“不值得信任”从而放弃整个站点。这意味着Agent-friendly不仅要求“能被抓”还要求“逻辑清晰、无歧义、可验证”。2. 网站对Agent不友好的典型症状在动手改造之前先学会诊断。这一节列出的症状我不止一次在实际项目里遇到过。如果你发现自己的站可以被人正常访问但Agent任务总是失败大概率是下面这些原因之一。2.1 “空壳HTML”陷阱症状curl拿到的HTML和浏览器里看到的页面完全两回事。页面内容全部由JavaScript动态渲染源码里只有一个root节点和一堆script标签。这种站对Agent来说等于不存在。我之前测过一个建站工具生成的营销页面HTML源码只有12KB但浏览器渲染出来却有完整的图文排版。Agent去访问的时候除了一个加载动画的div什么都提取不到。要诊断这个问题很简单用curl -L访问一下页面把保存下来的HTML打开看看有多少实际内容。如果文本量很小大概率就是壳。2.2 登录墙与半登录状态症状页面本身不需要登录就能看正文但一旦被识别为自动化访问就跳转到登录页或要求输入验证码。这里的“自动化识别”往往不是看UA而是看请求频率和指纹特征。更隐蔽的一种是“半登录状态”——部分内容可见部分内容要求登录比如列表页可访问但详情页被拦截或者首页可打开但点击搜索后需要验证。Agent的任务链路一走深就会断在半路。我在做数据采集类Agent时经常需要为这种情况专门写“登录预处理”逻辑但如果网站本身能提供免登录的只读接口这个问题根本不存在。2.3 验证码与人机识别症状弹出滑块验证、图片点选、或者要求开启JavaScript再访问。Cloudflare的“检查你的浏览器”页面是重灾区。对Agent来说滑块验证基本无解这已经属于对抗范畴了。哪怕有一些打码平台能过那也不是构建Agent-friendly网站该考虑的方向。反过来如果网站能对低风险请求直接放行只在真正可疑的高频请求时才发起验证Agent就能顺畅访问。2.4 链接不可预测与内容碎片化症状列表页到详情页的链接是通过onclick事件动态生成的或者页面使用无限滚动加载没有静态的分页链接。Agent无法从HTML里找到可追踪的URL自然无法深入爬取。更麻烦的是内容碎片化一篇完整的文章被拆成5页分页加载每一页只有开头部分要看完整内容必须点击“下一页”。人类不觉得这有什么问题Agent却会因此无法理解全文进而产生错误判断。2.5 语义信息缺失症状页面文本里有“库存紧张”“已售罄”“限时优惠”这些状态但没有对应的结构化标记价格直接写成“起价999”没有货币单位和有效期产品参数用图标和图片展示完全没有文本描述。这类页面人类看一眼就懂了Agent却无法可靠地提取。AI Agent对文本的依赖远超你对视觉的依赖所有只靠视觉传达的信息在Agent眼里都是缺失的。3. 一次完整的Agent友好化改造实操理论讲完上实践。这一节我以东哥笔记这个内容站点为例完整记录了一次Agent友好化改造的过程。改造前这个站的Agent抓取成功率不到30%改造后稳定在90%以上单次抓取的token消耗还降了60%。3.1 第一步用robo.txt和元数据亮明身份很多站长觉得robots.txt只是用来防搜索引擎的随便写两句就行。实际上对Agent来说robots.txt是它的第一道导航它需要在这里明确知道“你能去哪、不能去哪、多久来一次合适”。我的建议是至少包含这三块内容User-agent: * Allow: / Disallow: /admin/ Disallow: /cart/ Disallow: /search?* User-agent: GPTBot Allow: / Disallow: /draft/ User-agent: CCBot Allow: /public/第一块给普通爬虫和未识别Agent明确排除管理后台、购物车、搜索结果页这些无意义的动态页面。第二、三块是给特定厂商的AI爬虫单独开“白名单”比如OpenAI的GPTBot和Common Crawl的CCBot这些爬虫遵守robot规范比较自觉。如果哪天你不想被某个AI厂商抓取可以单独在它的规则下写Disallow: /。注意一个细节Disallow: /search?*这一行很多人不会写。搜索结果页是典型的无限URL空间对Agent是巨大的资源黑洞一个?page1和?page2给Agent返回的内容几乎一样却在浪费它的预算。把它们屏蔽掉对你没有任何损失。3.2 第二步用sitemap和结构化数据搭建内容骨架接下来是sitemap。这里不是指传统XML格式的sitemap.xml——那个也重要但Agent更需要注意的是sitemap里的URL到底稳不稳定。我的经验是URL必须永久有效不要频繁变动路径每个URL对应的内容要有明确主体不要一个URL在PC端显示A内容、在移动端显示B内容如果内容有版本更新最好保留固定的“最新版”URL而不是把版本号写进路径里。接着是结构化数据我强烈建议从JSON-LD格式入手。原因很简单JSON-LD可以放在head里不干扰正文文本Agent解析起来也比Microdata格式更直接。这是一个标准的Article结构化数据示例{ context: https://schema.org, type: Article, headline: Agent-friendly网站改造指南, description: 面向AI Agent的网站架构设计与改造实操, datePublished: 2025-03-10, dateModified: 2025-03-18, author: { type: Person, name: 东哥 }, mainEntityOfPage: { type: WebPage, id: https://example.com/guides/agent-friendly-website } }这里有个容易被忽视的地方dateModified不要漏。Agent有时候需要判断信息的新旧如果你的文章实际上更新过但没有更新这个字段Agent拿到的就是过时数据。我见过不少站的归档文章全是创建日期没有任何修改标记这类信息对做时效性判断的Agent来说等于缺失。3.3 第三步正文标记与语义化HTML真正决定Agent体验的是正文区域的HTML结构。很多站为了排版好看把整个页面都用div套div正文藏在一层层容器里。对Agent来说它需要靠标签语义来确定什么才是正文。我的建议顺序是用article包裹正文用main包裹当前页面的独有内容标题层级严格按h1→h2→h3一级级用不要跳级不要用h3当正文内的大标题列表项用ul或ol不要用一串div加行内符号模拟列表图片必须写alt文本这个文本是Agent理解图片内容的唯一通道表格用table加thead、th标签不要把表格结构拆成浮动块。一个硬性要求关键信息必须同时以文本形式存在。价格、日期、数量、状态这些绝对不要只出现在图片里。3.4 第四步合并碎片缩短正文路径然后是我这次改造收益最大的一步把分页文章合并为单页。我原来有几篇长文章分了三页改造后合成一页。表面上看单页变大了但对Agent来说这反而是缩短路径。为什么Agent不用再走“点击下一页→解析链接→发起新请求→等待响应→提取下一页正文”这条长链路。链路越长失败概率越高。合并完之后我还做了一件事给每篇文章的正文添加了一个idmain-content的锚点并在sitemap里用#main-content作为正文地址。当然标准爬虫不会管锚点但这个锚点给了我一个自己写Agent解析器的借口——直接定位、直接提取不用再猜哪部分是正文。3.5 第五步提供Agent专用的API入口如果条件允许这是最推荐的方案给网站加一个只读的、返回纯文本或JSON的API端点。你不用做完整的RESTful接口只需要一个返回规范数据的“阅读端点”就够了。比如GET /api/article/slug返回体可以设计成这样{ title: Agent-friendly网站改造指南, updatedAt: 2025-03-18, content: ……全文纯文本……, tags: [AI Agent, 网站架构], relatedLinks: [/guides/ai-agent-intro] }一次请求所有信息都齐了。Agent不用解析HTML不用跟CSS和广告模块斗争整个流程又稳又快。这个API可以不对外宣传只要在robots.txt里Allow这个路径就行。我改造东哥笔记的时候就加了这样一个端点从那以后我的Agent任务的成功率直接从72%跳到了95%。3.6 改造前后的数据对比贴一组改造前后的实测数据方便你做参考。测试场景是让同一个Agent收集20篇文章的信息每篇包括标题、发布时间、正文前200字和标签。指标改造前改造后请求总次数8641单篇平均token消耗89003400任务完成率28%94%平均耗时12分钟5分钟信息准确率82%99%token消耗一下子降了60%以上这就是结构化数据和API入口的威力。对做AI应用的人来说这个差距直接换算成API成本是实实在在的钱。4. 如何科学验证你的网站是否Agent-friendly改造完了不能拍脑袋说“应该可以了”要用一套标准化流程去验证。下面是我现在每次改完一个站都会跑的测试清单。4.1 用cURL模拟Agent的首次访问最简单的验证方式是先模拟Agent视角的“第一眼”。打开终端curl -s -L -A Mozilla/5.0 (compatible; GPTBot/1.0; https://openai.com/gptbot) \ -o /tmp/dongge.html \ https://example.com/guides/agent-friendly-website然后统计这个文件里的正文文本量python3 -c from bs4 import BeautifulSoup html open(/tmp/dongge.html).read() soup BeautifulSoup(html, html.parser) for tag in soup([script, style, nav, footer]): tag.decompose() print(len(soup.get_text(stripTrue))) 如果这个数字小于1000而页面本身应该有3000字以上说明页面还有内容被JS遮着或者正文被隐藏了。继续查。注意-A参数里带了GPTBot的UA。很多网站对不同的UA返回不同的页面版本有的甚至会因为识别到GPTBot而返回404。所以如果你想验证“真实用户视角下的可抓取性”可以不带UA参数再试一次。两个结果差异太大说明站内做了UA区分这本身就是一个需要注意的信号。4.2 验证结构化数据的完整性JSON-LD写没写、写对了没有有一个快速校验办法——用Google的结构化数据测试工具跑一遍页面URL。它会告诉你哪些字段缺失、哪些类型定义错误。这个工具的校验逻辑比较严格比你自己肉眼检查靠谱得多。另外可以写个简单的脚本抓下页面head区域里的JSON-LD块检查type和核心字段python3 -c import json, re, urllib.request html urllib.request.urlopen(https://example.com).read().decode() for match in re.finditer(rscript[^]*application/ld\json[^]*(.*?)/script, html, re.S): data json.loads(match.group(1)) print(data.get(type), data.get(headline), data.get(dateModified)) 跑一遍能很直观地看到页面到底暴露了多少结构信息。如果输出为空说明你的结构化数据代码放错位置或者格式有问题。4.3 用一个真实Agent任务做端到端测试cURL验证的是“能被抓”端到端测试验证的是“能被读懂”。我的做法很简单写一个小Agent让它访问网站首页找出最新的一篇文章提取标题和正文第一段然后让大模型判断“这个页面是否正常加载了内容”。走一遍完整链路。from openai import OpenAI import requests from bs4 import BeautifulSoup client OpenAI() # 1. 抓首页 resp requests.get(https://example.com) soup BeautifulSoup(resp.text, html.parser) # 2. 找出第一条文章链接 first_link soup.select_one(article a) or soup.select_one(h2 a) if not first_link: print(FAIL: 首页没有定位到文章链接) else: article_url first_link[href] print(OK: 找到文章链接 -, article_url) # 3. 提取文章内容 article_resp requests.get(article_url) article_soup BeautifulSoup(article_resp.text, html.parser) article_body article_soup.select_one(article) text article_body.get_text(separator\n, stripTrue)[:500] # 4. 交给大模型做语义完整性判断 response client.chat.completions.create( modelgpt-4o-mini, messages[ {role: system, content: 你是一个网页质量审查员。判断给定的文本是否是一篇完整文章的起始部分回复OK或FAIL以及原因。}, {role: user, content: f文章标题: {article_soup.title.string}\n正文开头:\n{text}} ], ) print(response.choices[0].message.content)这个测试脚本有一个很明显的优势它不是检查“代码有没有”而是检查“Agent实际跑任务能不能成”。最怕的情况就是页面在cURL验证的时候看起来没问题一上真实Agent就被反爬策略拦住。端到端测试可以把这个情况暴露出来。4.4 量化token消耗与成功率曲线最后我强烈建议你把Agent每次访问页面的token消耗记录下来做一个成本看板。数据不用多精细统计下面四个值就够了单次访问平均token数过高说明页面内容太杂任务成功率低于80%说明站内链路有问题平均任务耗时过长说明页面响应慢或者需要多次跳转失败任务的重试次数次数多大概率是被拦截我自己留了一套脚本每周跑一次把数据记进一个SQLite库自动生成趋势曲线。改造完之后观察两周Token曲线明显下降、成功率稳定在90%以上基本可以宣告Agent-friendly改造达标。5. 让Agent“愿意来”的运维细节架构层面的改造做完之后还有几个运维细节。这些细节不会直接决定“能不能抓”但会显著影响Agent对你的网站的信赖程度和使用频率。5.1 响应速度与稳定性Agent的调用链里有一个隐形指标叫“超时预算”。我这个Agent项目设置的超时是10秒超过这个时间直接放弃并切换下一个源站。很多站不是被识别为机器人封的而是响应太慢被Agent主动放弃的。对Agent来说稳定比什么都重要。偶尔502可以容忍频繁的5xx状态码会让Agent调用方直接把你拉进黑名单。最好保证至少99%的请求在3秒内返回。如果你用了类似Nginx的服务可以看下access log里的响应时间分布一目了然。5.2 清晰的限流策略有些站长为了保护服务器遇到密集请求直接封IP。这个策略对搜索引擎还好对Agent非常不友好因为Agent的出口IP往往是一整段动态IP封完一个它换一个继续打最后你损失的是所有Agent的访问能力。更好的策略是返回HTTP状态码限流而不是封禁。比如对一个来源IP在一分钟内超过20次请求时返回429状态码并附上Retry-After头。Agent调用方看到429会主动退避重试这个逻辑是标准行为。一次性封IP反而会引发更多无意义的重试两边都受罪。5.3 提供人类可读的联系方式最后这个小细节可能你觉得无厘头但我认为非常重要在网站底部放一个真实可用的联系邮箱。你开发或者运营一个Agent应用时如果它的目标源站出了问题——比如页面结构变了、数据不更新了你作为开发者第一反应是什么是找联系方式去沟通。如果网站没有联系方式只能靠猜和试效率极低。有一个清晰的联系入口意味着你给了Agent开发者一个和你协商的空间这对维持长期合作关系极其重要。5.4 关注主流AI爬虫的更新动态OpenAI、Google、Common Crawl这些机构会不定期更新他们爬虫的UA和访问策略。比如GPTBot的UA字符串可能会调整或者新增了新的爬虫类型。我在项目的requests模块里专门维护了一个“知名AI爬虫UA”的字符串列表定期更新。如果你在服务端做了UA识别也建议你持续关注这些更新别把Agent的UA认成普通爬虫给误伤了。6. 从“防爬”思维转向“共生”思维回头看我自己的经历这个项目真正让我想明白的不是“怎么让Agent抓我的网站”而是整个思维方式的转变。过去做网站防爬核心思路是“怎么区分人和机器然后把机器挡在外面”。但AI Agent时代机器本身就是你的用户。一个Agent在你的网站上顺畅地获取信息意味着你的内容正在被整合进某个AI产品的答案里这对内容方来说其实是曝光和流量。与其花力气去“防”不如把一部分资源花在“友好化”上。这中间有一个平衡要拿捏不想被恶意爬虫抓走的数据还是该做权限控制但面向公开内容的区域让Agent少走弯路、低消耗地获取信息是一种双赢。我现在的做法是管理后台、个人中心这类需要身份认证的区域保持现有的防护逻辑不动对公开的正文内容建一条只读的、稳定的、纯文本的通道专门给Agent使用。这条通道既减少了对服务器资源的消耗也提升了Agent侧的体验。如果你也正在被Agent抓取问题折腾我的建议是别急着上更高级的反爬技术先回头看看自己的网站对Agent是不是足够友好。就从一个cURL测试开始看看你的正文能不能在没有浏览器的情况下被完整读取。能读是一切合作的基础不能读那你再牛的提示词工程也救不了。改造完之后我的Agent任务成功率从28%涨到了94%token成本下降了六成。这个收益让我确信了一件事在AI Agent正在成为重要流量入口的当下给你的网站做Agent-friendly改造是性价比最高的一笔基础设施投资。
返回列表