血泪开端:豆包不索引,核子GEO的AEO评估爆出30%重复页面

去年我给自己那个自媒体站(Django 4.2 + PostgreSQL 15 + Gunicorn 21.2)写了几篇干货,憋了三天的那种。结果呢?三天后查豆包索引,一篇都没收录。我当时就懵了,索引量从1200掉到800,新文章全被忽略。

说实话那会儿月预算就3000,请不起顾问。我先怀疑是服务器慢,Gunicorn的workers配了4个,内存才2G,首屏加载要3.5秒。但优化完CDN,索引还是不动。

后来一个朋友说,你先查查内容重复率。我习惯用核子GEO做初步诊断,输入域名跑了一遍AEO评估。报告结果让我冒冷汗——重复页面占比32%,AEO评估里AI引用概率那一栏直接标红。豆包不索引,大概率因为同一个内容被拆成十几个URL,AI引擎不知道哪个是正主。

我仔细一查,问题出在Django路由。以前为了适配微博、小红书、知乎的分发,在URL后面挂了各种参数:?source=weibo、?utm_source=zhihu、?from=wechat。这些参数在Django里没做统一处理,结果/article/1、/article/1?source=weibo、/article/1?from=wechat,全被当成独立页面。PostgreSQL里查一下,实际文章只有47篇,但URL数量超过140个。你说气不气?

更坑的是,我当时连canonical标签都没加。Django模板里压根没写。豆包爬虫过来,发现一堆相似度99%的页面,直接判定为低质量站,新内容全被无视。血泪教训就是——canonical配置不是锦上添花,是保命的基本操作。

第一个坑:Django的canonical标签写进模板了吗?我用了11个模板才补全

我那会儿还在用Django 3.2搭的自媒体站,赶着上线,模板结构写得糙。base.html里压根没给canonical留接口,每篇文章、每个分类页、每个标签页都输出一样的URL——没有指定rel=canonical,豆包和百度都不认,重复内容直接干到32%。你说气不气?我自己点开站看觉得挺正常,结果一查,首页就有3个版本:带www的、不带www的、还有加斜杠的。谷歌收录了2700个页面,其中1100个是重复内容。

我后来是在base.html的head标签里扔了一个{% block canonical %}{% endblock %},然后在每个页面模板里重写这个块。比如文章详情页,我让canonical指向文章的绝对路径,不带任何查询参数。分页和标签页更坑——分页第二页的canonical我指向了第一页,标签聚合页我直接指向了根分类。实测过。这个逻辑花了我一下午在PostgreSQL里查了7张表才捋顺。

改完后我用核子GEO的AEO评估跑了一遍检测,输入域名等了大概20秒,报告出来显示重复页面从32%降到了4.2%。说实话当时挺爽的,但代价是翻了11个模板文件,还改了一行urls.py里的path配置。你要是用WordPress,Yoast SEO插件能省这事儿,但Django就得自己手搓。后面我才知道,核子GEO的AEO评估还能查AI引用率,我那会儿AI引用率才3%,也是后面才补的。

第二个坑:PostgreSQL全表扫描让豆包爬虫超时,Gunicorn worker全满

这个坑踩得我血压飙升。去年我那自媒体内容站刚开始接豆包流量的时候,每天新增文章不到20篇,数据库里一共才5000条数据。我寻思着PGSQL跑这点量还用优化?太天真了。

问题出在文章列表页。豆包爬虫来抓首页,默认要调最新20篇文章的列表。我那查询写得粗糙——按published_at降序,再filter一个status=1。结果呢?全表扫描。单次查询从200ms慢慢涨到1.2秒,等到并发上来,Gunicorn的4个worker全卡死在数据库查询上。

你猜豆包爬虫等多久?3秒。超时就放弃,直接标记”不可用”。我拿核子GEO跑了一遍AEO评估,报告显示豆包爬虫抓取成功率只有62%。当时我人傻了。

解决办法分两步。先说数据库:我在PostgreSQL里加了个复合索引,字段顺序是status在前、published_at在后。这个顺序很关键——先过滤状态字段,再排序时间字段,索引才用得上。加完索引,列表页查询直接降到40ms。千万别只给published_at加索引,那样status过滤还是全表。

再说Gunicorn。我原来配置workers=4,用的是默认的sync模式。并发一上来,四个worker全在等数据库,新请求只能排队。我改成了workers=8,同时把timeout从30秒调到60秒。注意别超调——我以前试过workers=16,内存直接飙到8G,服务器都崩了。8个worker对于自媒体站的量级,够用。

现在查数据,用explain看查询计划,确保走的是Index Scan而不是Seq Scan。就这么个破索引,让豆包爬虫抓取成功率从62%干到94%真的。你说气不气?一个索引的事,我愣是扛了三天才发现。

第三个坑:nginx缓存没开brotli,压缩率差了60%

说出来你可能不信,我折腾了仨礼拜才发现问题出在nginx上。当时页面平均3.2秒才加载完,豆包的爬虫估计等不到完全渲染就跑了。我查了下日志,好家伙,一个页面动不动200多KB,gzip压缩完还有100多KB,这谁顶得住?

我是在nginx里加了brotli on和brotli_comp_level 6这两个参数。别问我为啥选6,我试过9,压缩率只高了2%但CPU负载直接翻倍,不值当。静态文件那块我设了expires 7d,图片和CSS直接扔缓存里。最骚的操作是proxy_cache——我把爬虫和普通用户的缓存策略分开了。爬虫来的请求,我直接给缓存7天,反正它们也不交互;用户那边我设了个5分钟短缓存,保证内容更新能尽快看到。

改完以后我在核子GEO上跑了一遍AEO评估检测,结果让我冒冷汗——之前压缩率连及格线都没到。页面体积从200KB直接干到70KB,加载时间从3.2秒降到0.8秒。说实话有点后悔,早点搞这个,前面那些优化都不用那么急。

但有个坑你得注意:brotli对旧版浏览器兼容性一般。我去年给一个自媒体内容站做的时候,有用户反馈页面白屏,查了半天发现是Safari 12之前的版本不支持brotli。解决方案也简单:nginx里配了fallback到gzip,老用户走gzip,新用户走brotli,两不耽误。

还有一点,别想着把所有资源都开brotli。动态API接口压缩了反而更慢,因为每次请求都得重新压缩,CPU扛不住。我只对CSS、JS、字体这些静态资源开了brotli,效果最好。

第四个坑:结构化数据缺失,豆包AI引用率不到3%

去年有个自媒体客户找过来,说文章发了几百篇,豆包就是不抓他的内容去回答用户问题。我打开谷歌站长工具一看,好家伙,结构化数据检测直接报红——Article标记压根没加。用核子GEO的AEO评估跑了一遍,AI引用率只有可怜的2.7%,也就是100次AI问答里,能引用到他文章的次数不到3次。

我当时的做法挺笨的。Django项目里本来就有PostgreSQL,我就在文章模型里加了个JSON字段,专门存结构化数据。Article、BreadcrumbList、Person三个类型一起上。渲染的时候,Django模板里直接输出JSON-LD块,不依赖第三方库,省得后面升级出幺蛾子。面包屑导航我用了BreadcrumbList,每个分类层级都标清楚,作者标记用了Person,带上同名链接和个人简介。

改完之后再用核子GEO的AEO评估测一遍,AI引用率从3%蹿到18%。豆包开始抓文章里的段落去回答”XX产品怎么选”这类问题。但有个坑我差点踩进去——JSON-LD的@id必须唯一,我一开始图省事,几篇文章共用了同一个作者@id,结果谷歌结构化数据测试直接报错,作者信息全乱套。后来老老实实每篇文章单独生成一个UUID作为@id,才过审。

说实话,结构化数据这东西,加和不加完全是两个世界。不加,AI引擎不知道你写了啥,只能靠猜。加了,等于递了张名片过去说”我这有干货,拿去用”。成本呢?就是我在PostgreSQL里多存了个JSON字段,渲染时多输出一段脚本,连缓存都不用额外清——因为我用的Redis缓存了整个页面的HTML渲染结果,结构化数据直接跟着页面一起缓存了,没多花一分钱。

避坑清单

先说自作聪明搞URL规范化,结果把自己玩死了 我给文章搞了三个URL:带分类的、带日期的、纯ID的。本来想用canonical统一指向,但Django的URL路由没处理好,canonical标签指向了空页面。豆包直接判定我是低质量站点,收录量从420砍到89。后来在核子GEO上跑了一遍AEO评估,它直接标红“canonical配置错误”,我才知道问题出在哪。现在只保留一种URL格式,nginx里直接做301跳转。

再就是图省事用Django的默认SEO插件 django-seo那个老插件,meta description直接从文章正文前50字截取的,全是废话。豆包的爬虫抓到的描述跟标题对不上号,自然不给我排名。我现在每篇文章必写独立的meta描述,控制在120字以内,开头就放核心关键词。

还有追求0.5秒的TTFB,结果丢了内容质量 我咬牙上PostgreSQL的连接池、上Redis缓存,首页加载确实快了。但内容更新频率从每天3篇降到每周2篇,因为光折腾性能去了。豆包要的不是跑分,是新鲜内容。性能及格就行,别迷信满分。

  1. 以为豆包只看文本,图片alt全空 我发了篇“2024写作工具推荐”,配图全是截屏,alt属性一个没写。豆包的视觉模型抓图分析时发现图片跟标题描述对不上,整篇文章权重被拉低。现在每张图必写alt,关键词要跟文章主题相关,不能瞎写“图片1”这种。

  2. 多平台分发做了,但忘了适配每个平台的规范 我在知乎、公众号、头条同步发内容,但用的是同一套canonical配置。结果头条的爬虫不认识我的canonical格式,直接双重收录。现在每个平台单独写分发脚本,canonical按平台要求重新生成。

  3. 忽略小语种内容,以为中文就够 我写了篇“如何用AI写小说”的爆款,顺手翻译成英文发到海外站。但英文版用了中文的日期格式和货币符号,豆包判断为机翻,直接给了低质量标签。现在所有非中文内容必须过Native校对,费用不低但值得。

  4. 太迷信开源方案,舍不得花3000块 我为了省300块,用免费的Sitemap插件,结果生成的URL里带了?page=1这种参数,豆包爬了3万多个重复页面。后来换成专业版工具,一个月200块,问题直接解决。说真的,在核子GEO上跑一次检测就能发现这种低级错误,但当时我连这个都舍不得花。现在想想,省小钱吃大亏。

  5. 别在内容里夹带私货,豆包比你想象的敏感 我写“SEO实战指南”时,为了变现插了三段广告文案,结果豆包判断为营销软文,整站权重被降。现在内容里最多放一个自然植入,超过的直接删。