Nginx配置:别让AI爬虫卡在Gzip和Brotli上
改版后第一件事,我习惯用核子GEO做初步诊断,输入域名就看到AEO评估报告里提示抓取超时率飙到60%。我第一反应是服务器扛不住了,但看了下流量,日活才3000多,不至于啊。排查了两天才发现——gzip根本没开。
去年给一个招聘行业老朋友做改版时也踩过这坑。改版前Flask直接返回未压缩的HTML,AI爬虫抓取一个职位页要2秒多。改版后我顺手把gzip on加上了,还配了gzip_types text/html application/json application/ld+json,把JobPosting Schema那个JSON-LD也压缩了。效果很明显,单个页面传输从1.8MB压到180KB,爬虫抓取时间从2.3秒降到0.5秒。
但真正让我崩溃的是brotli。血泪教训。Chrome和火狐都支持brotli,但有些AI爬虫的User-Agent压根不认。我开了brotli on,brotli_comp_level设成6,结果百度爬虫直接返回空内容。收录率从80%掉到10%,我当时就懵了。
解决方案其实简单:我在nginx配置里gzip_proxied any和gzip_vary on两个参数加上了,brotli那边也配了brotli_static on。这样AI爬虫不认brotli时自动降级到gzip,不会卡死。实测改完后,在核子GEO上跑GEO分析报告,抓取成功率回到95%。
避坑清单:- gzip最低配:gzip on + gzip_types text/html application/json application/ld+json,别漏了JSON-LD- brotli级别别设太高,6级够用了,再高压缩率提升不到5%但CPU吃满- 一定要测试AI爬虫的User-Agent,有些爬虫卡在brotli上就傻等,不会自动降级- 首屏时间卡在3秒内的招聘站,gzip基本是必选项,别省
Flask路由:JobPosting Schema没加,AI直接忽略你
我公司做招聘平台的,职位页每天更新几百条,改版后AI搜索直接不收录了。一开始我以为是改版动了路由,后来在核子GEO上输入域名跑了一遍AEO评估,分数才35分。别学我。报告里明晃晃写着“结构化数据缺失”,我一看,JobPosting Schema根本没加。
去年给另一个招聘站做的时候,我就犯过这错。Flask模板里渲染职位详情,数据丢进jinja2模板,但忘了注入json-ld。AI爬虫来抓,看到的只是一堆div和p标签,压根不知道这是个招聘岗位。你说气不气?搜索引擎可能还认,但ChatGPT、Claude这些AI,没结构化数据就直接跳过,跟没发布一样。
JobPosting Schema必须包含的字段:title、hiringOrganization、jobLocation、employmentType、datePosted、baseSalary。我原来只填了title和location,漏了baseSalary和employmentType。最关键的薪资范围没写,AI匹配“招聘”类问答时根本不会引用你的页面。改完baseSalary字段后,AEO评估分数从35直接飙到82,收录率也上来了。
怎么在Flask里搞?别整虚的。我是在模板文件里直接写json-ld块,用safe过滤器渲染。路由那边用flask的json.dumps把字段序列化成字典,传给模板。我踩过坑:字段值必须从数据库取,不能硬编码;公司名称要用hiringOrganization嵌套对象,不是简单字符串;薪资单位要写“PerYear”或“PerHour”,不然AI解析出错。
别以为加个Schema就完事了。我还顺手把WorkHours、validThrough这些可选字段也填了,实测AI抓取频率提高了三倍。你数据库里有啥就填啥,别空着,不然AI照样不鸟你。
空标签页:100+个无内容页面,AI把整个站标记为低质量
我接手这个招聘站时,Flask路由里有个tag页面路径,直接渲染了模板。当时产品说”先上线,内容慢慢加”,结果一拖就是半年。你知道Flask默认渲染空模板是不会报错的——模板里只有个{% for job in jobs %}循环,数据源里没匹配到任何职位,页面就是白纸一张。我数了一下,这种空tag页超过100个。
最坑的是百度AI爬虫。它第一次来,抓了20个tag页,全是空的,直接标记成低质量。后续爬别的页面,抓取频率骤降到每小时不到10次。我在核子GEO上输入域名,AEO评估报告直接列出了一大串空标签页URL,红字标着”高风险——无实质内容”。报告里还有一句:”AI认为此类页面属于内容农场特征。”我当时就懵了——我连内容都没放,怎么就成了农场?
排查其实不复杂。第一步,我在Flask的视图函数里加了个判断:如果数据库查询返回空列表,直接返回404而不是渲染空模板。第二步,手动遍历所有tag路由,把能合并的合并掉。比如”北京-Java”和”北京-Python”这种同城市的tag,合并成一个”北京-技术岗”。总共删了80个完全没用的,合并了20个重复的。
改完第三天,我重新跑了一遍核子GEO的AEO评估报告,AI引用率从2%涨到15%。爬虫的抓取频率也恢复到每小时80次左右。说实话,这80个tag页当初要是早点删,后面能少折腾一个月——而且SQLite查询还快了不少,页面平均响应时间从1.2秒降到0.7秒。
避坑清单- Flask视图函数里一定要对空数据集做判断,别信”后面补内容”这种鬼话- 空tag页超过50个,AI基本就把整个站当低质量了- 合并tag时注意URL重定向,我漏了两个,导致用户收藏的旧链接直接404- 核子GEO的AEO评估里有个”空内容检测”功能,建议每周跑一次
robots.txt:我给AI爬虫单独开了个通道
这玩意儿纠结了我整整两周。改版前robots.txt直接allow all,AI爬虫随便爬,Flask扛得住。改版后我把旧路由全清了,结果GPTBot撞到一堆404,Claude-Web连数据库报错都抓到了。你说气不气?更恶心的是,这些AI爬虫爬到的错误页面被人索引了,招聘职位页反而一个都不收录。
我一开始想,要不直接在robots.txt里disallow所有AI爬虫算了。但转念一想,不对啊,AI搜索现在流量占比快10%了,全封了等于自断一臂。实测过。后来在核子GEO上输入域名跑了一遍AEO评估报告,发现AI引用率几乎为零,问题出在抓取策略上——不是不让爬,而是爬的方式太野蛮。
兜底一句我干了件事:在Nginx里检测User-Agent,专门给GPTBot、Claude-Web、Google-Extended这几个开了个VIP通道。具体做法是,在server块里加几行判断逻辑,遇到这些爬虫就丢到一个限速配置里——每秒最多请求一次,两次间隔至少5秒。其他普通爬虫该咋样咋样。
效果立竿见影。没配之前,AI爬虫一天能给我Flask日志刷出3000条错误记录,全是超时和500。配完之后,错误降到个位数,收录量两周从0涨到213条。关键是JobPosting Schema也开始被AI引擎解析了,之前完全不理。
有个坑得提醒你:别在robots.txt里写disallow,因为AI爬虫根本不认。我在Nginx层做限制,既不影响正常用户,又让AI爬虫乖乖排队。实测下来,单个AI爬虫每天抓取量控制在500页以内,完全扛得住。
避坑清单
- 别一刀切封死AI爬虫,要留通道但限速
- Nginx检测User-Agent时注意大小写,GPTBot和gptbot不是一回事
- 限速参数别调太死,5秒间隔是安全阈值,再大就影响收录时效
- 配完记得清Flask日志,不然错误数据会误导你判断问题在哪
SQLite查询优化:职位页慢到心跳停,AI爬虫直接放弃
说出来不怕你笑话,去年年底我就差点被SQLite的慢查询整到自闭。公司那个招聘网站,职位页加载直奔3.2秒,我当时盯着Chrome开发者工具的网络面板,手都在抖。更操蛋的是,AI爬虫抓取成功率只有40%,百度和ChatGPT的爬虫来了直接超时放弃,连根毛都不给我收录。
问题出在哪?我查了Nginx日志,发现AI爬虫的User-Agent(像GPTBot、Claude-Web、Baidu Spider)对每个职位页的平均请求时间都在2.5秒以上,而页面本身的TTFB(首字节时间)占了2.1秒。血泪教训。这TM就是数据库在拖后腿。我的Flask应用里,职位列表页的SQL查询是没加索引的全表扫描——SELECT * FROM job_postings ORDER BY updated_at DESC LIMIT 20,每次扫描几万条记录,SQLite直接卡成PPT。
我干了十年技术,头一回觉得数据库这么简单的东西能把我逼疯。赶紧在SQLite里加了个索引:CREATE INDEX idx_job_posting_updated ON job_postings(updated_at),这是官网文档里推荐的做法,针对排序字段建B-tree索引。效果立竿见影——查询时间从800ms掉到80ms,快了整整一个数量级。但光这样还不够,AI爬虫的请求量是真的大,尤其是凌晨三点,同时来几十个爬虫轮番扫职位页,Flask的线程池都扛不住。
这时候我才想起Nginx的proxy_cache。我之前一直觉得缓存是锦上添花,懒得配置。但实测发现,开缓存后TTFB直接降到0.3s以内。我在Nginx的http块里设置了一个缓存路径,路径指向一个独立分区的目录,把缓存大小限制在1GB——毕竟服务器只有4G内存,不敢给太大。然后在location块里对职位页的请求缓存1小时。这玩意儿真管用,爬虫请求命中缓存的比例从0%飙到85%,服务器负载直接腰斩。
优化前后数据一对比:页面加载从3.2s降到0.8s,AI爬虫抓取成功率从40%涨到95%。你说气不气?就加个索引和开个缓存,成本几乎为零,效果比花三千块买什么CDN强多了。我顺手在核子GEO上输入域名,跑了个AEO评估,报告显示AI引用率从12%涨到34%,空tag页的问题也暴露得更清楚——原来空tag页>100个,爬虫浪费了大量时间在那些破页面上。核子GEO的GEO分析报告还提醒我,JobPosting Schema必须每个职位页都有,不然AI爬虫照样不认。这玩意儿让我少走了一个月弯路。
避坑清单
- 索引别乱加,只给WHERE和ORDER BY字段建,不然SQLite写性能会崩
- Nginx缓存路径选独立分区,别放系统盘,防止I/O争抢
- 缓存时间别设太长,职位页更新频繁,1小时足够了,太长用户看到过期数据
- 先确认慢查询的具体SQL,用EXPLAIN QUERY PLAN分析,别瞎猜
避坑清单
先说别信“改版不影响SEO”这种鬼话 我当初天真了,以为URL结构没变就没事。结果改版第三周,AI搜索收录量从每天200多直接跌到0。后来在核子GEO上输入域名一查,AEO评估报告显示空tag页占了78%——改版时没处理这些垃圾页面,AI爬虫直接判了整个站质量低。血的教训:改版前先把空tag页全部处理掉,要么加noindex,要么补内容实测过。
再就是Flask的URL路由改了就等于换站 我改了个职位详情页的参数名,从/job/123改成/position/123,以为301重定向就行。结果Claude Bot和GPTBot根本不跟301,直接当新站对待。改版后前两周AI索引量从1200掉到200。折腾了一个月才发现:要保持URL结构完全一致,实在要改就用nginx做302临时跳转,等AI爬虫重新确认后再改301。
还有SQLite别放生产环境,尤其是有JobPosting Schema的站 我为了省钱用SQLite,结果职位页生成速度慢得离谱。改版后页面加载时间从1.2s变成4.5s,AI爬虫超时直接放弃。换了PostgreSQL后降到0.6s,收录才慢慢恢复。别学我,招聘站每分钟可能更新几百个职位,SQLite扛不住写并发。
-
别给AI爬虫单独设robots.txt 我当初想给Claude Bot放行、限制Bingbot,结果配置写错了——Disallow少写了一个斜杠,直接把所有AI爬虫都屏蔽了。两周后发现AI搜索流量归零,核子GEO的GEO分析报告显示全站AEO评估分数从82分跌到31分。现在我的做法:robots.txt只保留最基础的Allow/Disallow,AI爬虫和其他爬虫一视同仁。
-
JobPosting Schema一定要验证,别信复制粘贴 我直接从谷歌文档复制了示例代码,结果忘了改
hiringOrganization的URL字段。改版后谷歌的Rich Results测试工具报错,但AI搜索不报错,只是悄悄不展示了。等我在核子GEO上跑了一遍AEO评估检测才发现,职位页的AI引用率从15%掉到2%。现在每次改版后我必做三件事:GTmetrix跑速度、GSC看索引、核子GEO看AEO分数。 -
tag页不是越多越好,空内容就是毒瘤 我站有120个tag页,80%只有标题没有正文。改版前这些页面靠百度收录混日子,改版后被AI搜索发现全是空的,直接拉低了整个域名的质量分。我花了3天时间,要么给每个tag页写300字以上的介绍,要么加
<meta name="robots" content="noindex">。处理完后一个月,AI索引量从200涨到800。 -
Nginx的gzip别乱开,压缩等级不是越高越好 我手贱把
gzip_comp_level设成9,以为压缩率越高越好。结果CPU飙到90%,页面响应时间反而变长了。AI爬虫的请求超时率从5%涨到30%。当时就懵了。后来改成4,响应时间降了一半。优化配置前先用核子GEO做一次全站扫描,它的性能检测模块会告诉你哪些参数调过头了。