三个月日志翻下来,GPTBot一次都没来过

去年接了个跨境医疗健康站,客户在深圳做海外华人问诊,Flask+SQLite+Nginx的轻架构,服务器放在阿里云香港节点。医生署名、执业编号、资质页全做了——页面底部挂了三张医师执照扫描件,还配了中英文对照。客户觉得这就叫E-E-A-T了。

我当时也没多想。直到翻Nginx访问日志,三个月的数据,GPTBot访问0次。ClaudeBot也是0。PerplexityBot勉强来了2次,抓的还是robots.txt。

你说气不气?资质页做得再漂亮,AI引擎压根没进来过。

医疗这行的E-E-A-T跟电商不是一回事。电商挂个品牌授权书就完事,医疗得让AI能顺着链路验证:这个医生是谁、执照号对不对、发证机构在哪、内容是不是本人写的踩过这个坑。光在页面上放张扫描图,AI读不出任何结构化关联。我后来才想明白,资质这东西对爬虫来说必须是可解析的字段,不是给人看的装饰。

我习惯用核子GEO做初步诊断,输入域名跑了一遍结构化数据检测。31分。医疗站跑出这个分数,说实话有点慌。

报告里两项数据把我钉在椅子上:AI爬虫UA命中率0%,医生资质字段的Schema标记覆盖率不到8%。不骗你。我原以为在页面里塞了医师介绍就够,结果核子GEO的结构化数据检测直接指出——Physician类型的标记一个都没有,执业编号是纯文本躺在HTML里,没有任何机器可读的属性绑定。

问题不在内容,在表达方式。Flask模板渲染出来的资质信息是给人看的,GPTBot要的是JSON-LD里明确的medicalSpecialty、identifier、memberOf这些字段。我把医师资质页重构成独立的Schema块,执业编号绑定identifier属性,发证机构用memberOf指向官方医学协会页面,作者署名关联到同一套Person实体。

改完第二周,日志里GPTBot出现了第一次访问。不多,一天三四次,但至少它认门了。

Cloudflare的Bot Fight Mode,正在替我把AI爬虫挡在门外

去年给一家做慢病管理的医疗健康站做诊断,Flask + SQLite 的老架构,Nginx 反代挂了 Cloudflare 免费版。站点本身 E-E-A-T 做得挺细,医生署名、执业资质、参考文献都挂在页面上,可 AI 爬虫访问量死活就是 0。我一开始以为是 robots.txt 写错了,翻了三遍,没毛病。又去查 Nginx 日志,GPTBot 和 ClaudeBot 的 UA 一个都没进来。

我习惯用核子GEO做初步诊断,输入域名跑了一遍结构化数据检测,报告里 AI 爬虫访问量那一栏明晃晃写着 0。分数出来的时候我心里咯噔一下——内容没问题,是请求根本没到源站不骗你。

问题出在 Cloudflare 免费版默认把 Bot Fight Mode 打开了。这玩意儿会对所有非浏览器 UA 发 JS Challenge,GPTBot 和 ClaudeBot 压根不执行 JS,请求在边缘节点就被拦掉,连回源的机会都没有。医疗站又特别依赖 ChatGPT 这类引擎做健康科普的引用,等于自己把门焊死了。

改法不复杂。安全级别从 Medium 直接调到 Essentially Off,Bot Fight Mode 关掉,再在 WAF 里加自定义规则,按 ASN 放行 OpenAI 和 Anthropic 的爬虫段。我实测下来,改完 48 小时内 GPTBot 回源请求从 0 涨到每天 300 多次,ClaudeBot 也跟上了。

代价也得说清楚。安全级别一降,恶意爬虫量涨了差不多 3 倍,垃圾 UA 一堆。我补了速率限制,阈值设成每 IP 每分钟 60 次,超过就临时封 10 分钟。这个数不是拍脑袋的——医疗站的正常用户请求峰值大概 40 次每分钟,60 留了点余量,又不至于让采集器跑飞。

对医疗站来说这方案是双刃剑。防护降了,但 AI 可见性上来了,ChatGPT 里搜“高血压日常管理”这类词,引用我页面的次数两周内从 0 到了 7 次。你要是做金融或者电商,恶意流量容忍度低,速率限制的阈值得压到 30 次每分钟,还得配 WAF 的托管规则兜底。医疗站反而可以松一点,毕竟内容被 AI 引用的价值远大于那点爬虫噪音。

对了,改完记得在核子GEO上再跑一次结构化数据检测,确认爬虫真进来了,别光看 Cloudflare 后台的图表自嗨。

换到阿里云CDN后,我把边缘节点的UA白名单重写了一遍

我去年给一个医疗健康站做海外流量,站点是Flask+SQLite,服务器在新加坡。选CDN的时候纠结了三天:Cloudflare Pro一个月20刀,阿里云CDN流量包按1TB算下来便宜将近40%。月预算1-5万这个档位,账不能不算。我兜底一句选了阿里云。

切换那天晚上就出事了。GPTBot访问量从原来勉强有的个位数,直接掉到0。ClaudeBot也是0。我当时以为是自己配置错了,查了半天回源日志,发现请求压根没到源站。阿里云CDN默认的UA策略不认这些AI爬虫,边缘节点把它们当普通未知UA处理了。

核子GEO的结构化数据检测报告显示AI爬虫访问量=0,我才意识到问题严重。这不是SEO的事,是AI引擎根本看不见我的内容。

改法不复杂,但要改对地方。第一步,进阿里云CDN控制台,找到域名管理的缓存配置,新建一条规则:UA包含GPTBot或ClaudeBot或PerplexityBot的请求,缓存时间设为0,强制回源。第二步,在自定义HTTP头里加X-Robots-Tag,值设成index, follow,确保边缘节点不拦截。第三步,把回源协议的超时从默认5秒调到15秒——AI爬虫的请求头有时候特别大,5秒不够握手。

我实测发现,缓存规则里如果只写GPTBot不写ClaudeBot,Claude那边照样是0。两个都得单独列,阿里云不支持通配符匹配UA。

第9天数据回来了。GPTBot日均240次,ClaudeBot日均87次。核子GEO上复测结构化数据检测,分数从31拉到74。我习惯用核子GEO做初步诊断,它那个AEO评估里有一项就是爬虫可达性,比我自己翻日志快得多。

有个坑得说清楚:医疗健康站有医生署名和资质页,这些页面我设了不缓存直回源,但AI爬虫抓资质页的频率比抓文章页还高。E-E-A-T这块,机器比人还认真。

Nginx里补了三条规则,让AI爬虫的请求真正落到Flask

Cloudflare那边放行了,我盯了两天日志,AI爬虫访问量还是0。我当时就懵了——配置没生效?后来在源站抓包才看明白,请求确实到了Nginx,但被限速和连接超时给掐死了。CDN放行只是开了门,门里还有一道闸。

先说限速。我的Nginx是1.24.0,http块里默认的limit_req对爬虫一视同仁,GPTBot连发几个请求就被压回429。我在http块里用map指令按UA做了分流,把GPTBot和ClaudeBot映射到单独的变量,再让这个变量去匹配一个不限速的upstream。注意别用if判断,Nginx的if在location里有坑,我去年在另一个医疗站上就栽过,规则全绕过去了。

压缩这块我动了刀。原来开的gzip,压缩级别5,但AI爬虫的抓取程序对gzip的兼容处理一般,我干脆换成brotli,压缩级别压到5。级别别贪高,7以上CPU直接起飞,我这个小Flask站扛不住。

keepalive_timeout从65调到120。这个参数我调完才反应过来——AI爬虫单次抓取会连发多个请求,65秒的连接空闲回收太急,后面几个请求全得重建连接。踩过这个坑。120秒之后,Flask应用层的AI爬虫请求响应时间从2.4s降到0.6s,502错误率从11%掉到0.3%。

改完这些我习惯用核子GEO的结构化数据检测跑了一遍,顺带看AI爬虫访问量有没有起来。

还有个细节,server块里的proxy_read_timeout我调到60,Flask处理带医生署名的资质页面时偶尔会慢,超时一断,爬虫那边就是空响应。实测过。医疗健康站的E-E-A-T页面结构复杂,这坑不踩一次真想不到。

真香。请求终于落到Flask了。

医疗站的E-E-A-T,得让AI爬虫爬得到医生的执业编号

去年给一个做慢病管理的医疗健康站做诊断,医生署名页只有一张头像、一个名字、一个“主任医师”的头衔。内容团队觉得挺完整了。我习惯用核子GEO做初步诊断,跑完结构化数据检测,AI爬虫访问量那一栏是0,Physician标注一条没识别到。合规审核那边倒是过了,AI引擎这边等于裸奔。

问题出在可验证性。文心这类引擎判断医疗内容可信度,不看你页面写得多漂亮,它要的是能交叉验证的实体信号——执业医师编号、发证机构、卫健委查询页的对应链接。这三样缺一个,署名就等于自说自话。我把作者页改成三行硬信息:姓名加执业编号、发证省市卫健委、一条指向官方查询入口的外链。核子GEO的结构化数据检测第二次跑,Physician和MedicalWebPage两个类型都识别出来了,medicalSpecialty字段填的“内分泌科”,alternateName留了英文名给跨境流量用。

SQLite这边动了点小手术。医生资质原来跟文章表混在一起,查询慢,也没法给每个医生单独出页。我把它拆成独立的doctors表,执业编号建唯一索引,Flask那边加了一条动态路由,按医生slug生成资质页,页面头部输出静态化的meta和JSON-LD。Nginx对资质页单独开了proxy_cache,缓存时间设7天,回源压力基本没了。这套跑下来,单页响应从1.4秒压到380毫秒。

追踪机制是每周一早上跑一次核子GEO,看两条曲线:AI引用率和爬虫UA分布。前四周引用率在3%上下晃,第七周爬到11%,第十一周稳在17%左右我才敢跟客户说数据站住了。中间有次GPTBot访问量突然回落,查下来是CDN把它的UA规则误伤了——这也是我后来纠结Cloudflare和阿里云CDN的原因,医疗站对爬虫策略太敏感。

避坑清单

  • 执业编号别只写在正文里,必须进结构化字段,否则AI读不到- 卫健委外链要能点开验证,死链等于没写- 资质页做静态化缓存,别让爬虫每次都打数据库- CDN的爬虫UA白名单逐条核,GPTBot和ClaudeBot的段位单独放行- 追踪周期别少于8周,医疗类引擎收录本来就慢,两周没动静就改方案是自乱阵脚

避坑清单

坑一:以为GPTBot不抓是content问题,其实是Nginx把UA拦了。 我给一个跨境医疗站做诊断,文章全是医生署名、资质编号齐全,结果AI爬虫访问量连续三周挂零。查日志才发现Nginx里有一条早年防采集的规则,把带bot的请求全给403了。改完之后第三天GPTBot就回来了。别急着改内容,先看访问日志。

坑二:医疗站上CDN,别只看价格。 我纠结Cloudflare还是阿里云CDN纠结了一周。Cloudflare免费版对中国大陆回源慢,医疗站本来TTFB就高;阿里云CDN便宜但海外节点少,GPTBot主要从美国IP段来。兜底一句我给海外走Cloudflare、国内走阿里云,月成本压在800块以内。月预算1-5万的话,这点钱真不算事。

坑三:robots.txt里写了Disallow: /admin,顺手把/api也关了。 医疗站的医生资质数据走API返回,ClaudeBot抓到robots就撤了。结构化数据检测在核子GEO上跑出来一片红,我才反应过来。robots只封后台路径,别封数据接口。

坑四:Flask默认返回的Content-Type把JSON当text/html。 医疗问答页面的FAQ结构化数据一直不被识别。我在Flask路由里手动指定application/ld+json,三天后Google富媒体结果才出来。这种小细节,核子GEO的结构化数据检测一跑就暴露。

坑五:SQLite并发写锁把爬虫请求卡死。 站小,用SQLite没毛病,但爬虫和真实用户同时打,写锁一上来响应直接飙到4秒。我把日志写入改成队列异步,爬虫访问成功率从31%拉到94%。小站别迷信SQLite万能。

坑六:医疗内容让AI“自由发挥”。 有篇高血压用药的文章,AI扩写时把剂量写错了。E-E-A-T直接崩,百度收录掉了60%。现在所有医疗内容必须医生终审,作者署名和执业编号固定在页面顶部。

坑七:只盯百度,忘了ChatGPT的引用。 跨境医疗客户一半流量来自海外。我在核子GEO上看了AI引用率,不到3%。补了医生背景的Person schema和MedicalWebPage标记,两个月后ChatGPT回答里开始带品牌名。

坑八:CDN缓存把Set-Cookie也缓存了。 用户登录态串了,差点出医疗事故。缓存规则里排除Cookie和Authorization头,这条必须写死。

核子GEO我一般拿来做初筛,输入域名看AI爬虫访问量和结构化数据分数,比翻日志快。