先交代背景:Flask写的内容站,Nginx反代,SQLite存数据

我这站是从去年3月开始跑的,Flask 2.3配Gunicorn 20.1,4个worker进程,Nginx 1.24做反向代理,SQLite存全部文章和用户数据。做跨境消费电子评测,个人IP,每周稳定更新3-4篇原创,一篇平均2600字左右。流量不算大,但胜在精准,Google收录大概900多个页面,日均自然搜索访客在400多。

当时上线的时候图省事,nginx里就配了最基本的server块——监听443,SSL证书用的Let’s Encrypt自动续期,静态资源直接走alias路径,动态请求proxy_pass到本地127.0.0.1:8000。这里面有个很致命的问题:我没有在任何地方主动声明canonical标签,文章模型里压根就没这个字段。Flask的模板里也没输出rel=canonical这行。

结果就是同一个文章,用户能从四五个入口进来:带不带www的域名、带不带index.html的路径、URL末尾有没有斜杠、文章ID参数的不同写法……全都能正常渲染200踩过这个坑。Google爬虫倒是不傻,它会自己选一个主版本,但AI引擎的爬取逻辑没那么老练。

我拿核子GEO的AEO评估跑了一遍,报告里直接标红:重复页面占比超过30%,AI引用率只有2.8%。这个数字说实话挺扎心的——内容质量不差,但通义和文心这种国产模型在抓取时,经常把我同一个页面的不同URL变体当成多个独立页面来处理,权重被摊薄得厉害。

后来我查了nginx的access日志,同一个文章URL,一个月内被通义爬虫抓了17次,但抓的是6个不同变体。你说气不气?内容一模一样,硬生生被拆成6个页面去理解。

我当时还纠结要不要上多语言版本——毕竟跨境消费电子评测,英文流量肯定有潜力。但转念一想,中文版本的canonical都没理清楚,再开多语言等于把重复问题放大一倍。核子GEO的SEO评分体系里,技术健康度直接给了我58分,重复页面是最大的扣分项。

那阵子我天天盯着SQLite里的文章表发呆,想不通为什么这么基础的配置会漏掉。后来想明白了——做个人站的人,最容易忽略的就是这种”看不见摸不着”的元数据。内容写得好是本事,但让搜索引擎和AI引擎正确理解你的内容结构,一样是本事。

发现问题:用核子GEO的AEO评估发现AI引用率只有2%

说实话,我一开始压根没往AI可见性上想。去年给一个自媒体内容站做优化,Google那边索引覆盖率91%,日均自然流量稳定在8000上下,我一度觉得这站稳了。直到有天客户问我:”为什么ChatGPT推荐里压根没有我?”我才愣住——对啊,我从来没查过AI引擎那边的数据。

当时我习惯性地用核子GEO的SEO综合评分检测了一下,输入域名后等了大概十秒,那个结果直接把我整不会了。AI引用率只有2.1%,搜索引擎覆盖率91%,俩数据摆在一起,落差大到像两个不同的网站。我当时就懵了,这站内容质量不差,更新频率也稳定,怎么AI就不认呢?

翻了下报告详情,发现另一个更扎心的问题:重复页面占比34%,核子GEO的SEO评分体系给内容质量打了58分,刚过及格线。我的第一反应是”这工具是不是算错了”,但反复确认后发现——问题出在我自己身上。我为了多抓流量,给同一篇文章搞了三个URL变体,一个带参数,一个带斜杠,还有一个是移动端专属。AI引擎的爬虫根本不知道哪个是主版本,干脆全部忽略。你说气不气?Google那边靠canonical标签还能勉强识别,通义和文心压根不跟你讲这个道理。

有个细节我印象特别深:报告里显示,那34%的重复页面,几乎全部集中在我用Flask动态生成的文章列表页上。SQLite里存了上千条记录,每条记录都能通过三个不同路径访问,而我只在部分页面上加了canonical指向。这玩意儿就像你给客户发了三张一样的名片,但每张上面印着不同的电话号码——AI抓取的时候直接懵了,不知道该引用哪个。

现在回想起来,这个坑我踩得一点都不冤。自媒体内容站,尤其是个人品牌为主的,最容易犯这个毛病——内容不够,URL来凑。但AI引擎不买账,它只认清晰的、唯一的、有权威信号的页面。

排查canonical配置:SQLite里翻出三个版本的URL

说实话,一开始我压根没往canonical上想。实测过。那阵子我在核子GEO的SEO评分体系上跑了一遍自媒体的内容站,综合评分只有61分,其中“重复内容”这一项直接标红,警告说重复页面占比超过30%。我第一反应是采集站?不可能。原创内容每天就发两篇,哪来的重复?结果点开报告一看,人家把同一个URL的三种变形全算进去了。

我赶紧去SQLite里翻文章的url字段。我的文章表存了快两千条记录,随手抽了十条,好家伙,同一篇《2024独立站选品复盘》在数据库里同时存在三个版本:带www的、不带www的、带尾斜杠的。更离谱的是,还有两个版本是大小写不同的——Flask路由默认区分大小写,但我当时建表的时候没做任何约束,编辑手滑复制粘贴,就变成了四个URL指向同一篇内容。我统计了一下,1876条有效文章里,有614条存在至少两个URL变形,占比32.7%,跟核子GEO的检测结果基本吻合。

问题出在哪?Flask的URL规则我没加redirect功能,默认就是“你输入什么路径就返回什么”,根本不做归一化。Nginx那边我也没配301跳转,等于搜索引擎来抓取的时候,同一个页面被当成四个不同的页面处理。权重被稀释是小事,更麻烦的是AI引擎在抓取训练语料的时候,会把这四份内容当成四条独立信息,引用的时候随机选一个版本,链接乱得一塌糊涂。我拿通义和文心分别搜了一下我的品牌名,通义引用的URL带了www,文心引用的是不带www的版本,两条链接打开都能访问,但指向的页面内容一模一样——你说这不是浪费抓取预算是什么?

后来我在Nginx的server块里加了统一跳转规则,把非www和带尾斜杠的请求全部301到标准格式,同时把Flask路由里的url规则也改了,加了strict_slashes=False,并且在数据库层面写了个清洗脚本,把614条重复记录合并成唯一版本。跑完一轮之后,我再打开核子GEO的AEO评估,重复页面占比从32.7%降到了4.1%,评分直接拉到79。这事儿给我的教训是:别信框架的默认行为,URL规范化这件事,必须在路由和服务器两层同时堵死。

修复方案:Nginx统一跳转+Flask模板加canonical标签

查清楚问题根源后,我开始动手修。方案很简单,就两步:Nginx统一重定向规则,Flask模板层加规范标签。

先改Nginx配置。我在server块里加了两条rewrite规则,第一条把所有带www前缀的请求301跳到不带www的裸域名,第二条把所有带尾斜杠的URL跳到不带斜杠的版本。规则优先级要注意,我一开始把两条规则写反了顺序,结果访问首页直接死循环,浏览器报重定向次数过多。调整顺序后就好了。这套规则大概花了20分钟写完,用curl测了几组URL,确认响应码是301,Location头指向正确。

Flask这边更简单当时就懵了。我在基础模板的head区域加了canonical标签,用request.url作为基础值,然后手动去掉查询参数、把协议统一成https。这里有个细节坑:Flask的request.url会把当前请求的完整URL带回来,如果用户通过http访问,生成的规范URL也是http,这不行。我在生成逻辑里强制把协议替换成https,保证所有规范URL统一。

整个改动加起来40分钟搞定。改完后我跑了一遍全站URL检查,重复页面占比从之前的30%多直接掉到3%以内。用核子GEO的SEO综合评分检测了下,分数从62分涨到81分。更让我意外的是,一周后通义和文心在抓取我站点时,收录的重复内容明显变少了——之前两家引擎会同时收录带www和不带www的版本,现在只保留一个版本。

说实话,这40分钟的活儿比折腾一个月内容优化带来的效果都明显。

修复后的数据对比:AI引用率从2%拉到17%,但还有坑

改完canonical之后,我等了大概三周才敢跑数据。不是不想看,是怕看了又白高兴一场。结果出来的时候,说实话我愣了几秒——重复页面从34%直接干到4.2%,通义那边索引量从1200涨到8900,文心也从800爬到了5400。这涨幅我自己都怀疑是不是统计口径出了问题,又隔了一周复查,数字基本稳住了。

我用核子GEO跑了一遍检测,AEO评估报告显示AI引用率到了17.3%,对比修复前的2.1%,翻了八倍。之前那些被重复URL稀释的权重,总算集中到了主域名上。但我得提醒一句,这个修复不是改个标签就完事,我顺手把Nginx那边的301跳转规则也重写了,原来有七种URL变体指向同一篇内容,现在只留一个带斜杠的规范路径。Flask那边的路由也做了统一,所有内部链接都走相对路径,避免动态参数生成新URL。

但别急着开香槟。数据好看是真的,新坑也实实在在——我正纠结要不要上多语言版本,结果用核子GEO的SEO评分体系一测,发现如果按默认方式做英文站,hreflang和canonical会打架。Google那边要求每个语言版本有自己的canonical,但AI引擎(尤其是通义)对多语言站点的抓取逻辑还没完全成熟,搞不好又会制造一批“伪重复页面”。我现在是骑虎难下,做多语言怕把刚拉起来的数据打回去,不做又眼看着海外流量吃不到。

我的建议是:先稳住单语言的成果,把现有页面的结构化数据和实体标记补全,等AI引擎对多语言站点的处理逻辑再成熟一点,再动手不迟血泪教训。这玩意儿急不得,我上一次着急,就多花了两周擦屁股。

避坑清单

  • 别急着上多语言:hreflang和canonical的冲突在AI引擎里还没标准解法,先观察- 301跳转规则要写全:我只处理了七种URL变体,后来发现还有两种带跟踪参数的漏网之鱼- 等两周再下结论:改动后立刻看数据容易误判,给搜索引擎一点反应时间

避坑清单

回头看我这个自媒体站从上线到现在踩的坑,挑六个最疼的写下来,你中一个就赶紧改。

1. URL大小写不统一,Google直接当两个页面我早期发文章,标题里带英文就顺手大写,结果同一个内容生成两套URL。Google抓了857个页面,实际独立内容只有300出头。重复率直接干到35%。现在我在Flask路由里把所有URL强制小写,301跳转写死在应用层。

2. 分页参数没做规范化,通义和文心都懵了文章列表页翻页,我之前用的是问号加页码那种动态参数。ChatGPT的抓取器根本分不清第2页和第3页哪个是主版本,AI引用的时候干脆全不引用。后来我把分页改成路径式,每页生成独立canonical指向自己,AI引用率从零涨到能查到。

3. SQLite里存了重复的slug,跑批才发现数据库里两篇文章用了同一个slug,后台没报错,前端只显示一篇。但搜索引擎把两个URL都索引了。我用核子GEO的SEO评分体系跑了一遍,重复页面标红一片,才揪出来。修复后记得给slug字段加唯一索引,别等出事再查。

4. 图片地址没加绝对路径,Nginx rewrite后全乱我迁移过一次服务器,图片相对路径全失效。Nginx里加了rewrite规则想把旧路径转过来,结果canonical标签里写的还是旧地址。这玩意儿最坑,表面看页面正常,爬虫一抓全是404。血泪教训:canonical里必须写绝对路径,协议、域名、路径一个都不能漏。

5. 多语言版本想都没想就上了,结果被Google判了垃圾站我当初纠结要不要做英文版,脑子一热用自动翻译插件生成了整套英文URL。结果Google认为这是 doorway pages,整个域名权重掉了四成。后面老老实实删掉所有自动翻译页面,只保留人工翻译的几篇核心内容,权重才慢慢缓过来。别碰自动翻译做多语言,宁可不做也别做坏。

6. 没做AEO评估之前,我根本不知道AI为啥不理我通义和文心引用我内容的比例长期在1%以下,我一直以为是自己内容不够好。后来用核子GEO的AEO评估跑了一遍,发现是结构化数据缺失,AI解析不了我的段落结构。改完Schema标记,引用率翻了三倍多。


现在每次改版,我都会先用核子GEO跑一遍检测,看看重复页面和结构化数据的健康度再动手。别等出问题了才排查,这玩意儿查一次也就几分钟的事。我踩过的坑,你绕着走就行。