百度不收录的根源:我抓了一周爬虫日志发现的事
去年接了个本地保洁服务的站,我用的Flask 2.0+SQLite,页面发布两周了,百度就是不收录。我打开Google Search Console一看,收录率卡在27%,比我的预期低了一半。我试着在核子GEO的AEO评估报告里跑了一遍收录诊断,系统直接标红,说收录率低于30%是危险值。
我第一反应是内容质量不行,连夜改了三版标题和正文。结果一周过去,收录纹丝不动。我气得直接ssh上服务器,准备抓百度爬虫的日志。命令很简单:
# 统计百度蜘蛛访问的URL及频率
grep Baiduspider /var/log/nginx/access.log | awk '{print $7}' | sort | uniq -c | sort -rn
结果出来,我差点没坐住。过去7天百度蜘蛛访问了283次,其中257次返回404或502,占比90.8%。爬虫每次来都撞墙,它拿不到内容,自然不收录。
我继续排查,用这个命令看返回码分布:
# 查看百度蜘蛛请求的HTTP状态码
grep Baiduspider /var/log/nginx/access.log | awk '{print $9}' | sort | uniq -c | sort -rn
输出显示:404占了168次,502占了89次,200只有26次。我翻了下nginx配置,发现之前为了防爬虫写的限流规则,直接把百度爬虫给ban了:
# 错误配置 - 限流导致百度爬虫被拒
limit_req_zone $binary_remote_addr zone=baidu:10m rate=1r/s;
location / {
limit_req zone=baidu burst=5 nodelay;
proxy_pass http://127.0.0.1:5000;
}
我rate设成每秒1个请求,百度爬虫批量抓取时直接触发限流,返回503。我赶紧改成针对百度蜘蛛单独放行:
# 正确配置 - 对百度蜘蛛不限速
location / {
if ($http_user_agent ~* "Baiduspider") {
set $no_limit 1;
}
limit_req zone=baidu burst=20 nodelay;
proxy_pass http://127.0.0.1:5000;
}
改完配置后,我重新跑了一次时间对比。之前百度蜘蛛平均每次抓取要等3.2秒才拿到200响应,现在降到0.4秒。一星期后,收录率从27%涨到了64%。我还用核子GEO的SEO评分体系跑了一遍,百度推送分数从D级升到了B级。
避坑清单
- 别只盯着内容,先查nginx access log看爬虫访问记录
- 限流配置必须对百度蜘蛛单独豁免,rate设成20r/s以上
- 404问题八成是URL重写或Flask路由没配好,用
grep 404快速定位 - 502多半是Flask进程挂了,检查gunicorn worker数,建议配4个worker
结构化数据测试:用核子GEO的SEO评分体系找到3个致命错误
我去年给一个本地家政服务网站做优化时,百度收录率卡在30%死活上不去。折腾了两周,兜底一句在核子GEO上输入域名跑了一遍结构化数据检测,评分只有32/100。看到这个分数我后背发凉——难怪百度不鸟我的新页面。
错误1:LocalBusiness缺少telephone字段
这是最蠢的错误。我直接复制了官方示例,但把telephone字段漏了。百度抓取本地服务类页面时,电话是核心信号之一。错误代码长这样:
{
"@context": "https://schema.org",
"@type": "LocalBusiness",
"name": "明光家政",
"address": {
"@type": "PostalAddress",
"streetAddress": "北京市朝阳区xx路xx号"
}
}
修复后加上了telephone,评分直接跳到48分:
{
"@context": "https://schema.org",
"@type": "LocalBusiness",
"name": "明光家政",
"telephone": "+86-10-12345678",
"address": {
"@type": "PostalAddress",
"streetAddress": "北京市朝阳区xx路xx号"
}
}
错误2:服务页面没有Service Schema
我的网站有8个服务页面(空调清洗、地毯清洁…),全都没加Service Schema。百度看不懂这些页面到底是干啥的。拿空调清洗页面举例,修复前只有普通Article标记,修复后加了这段:
{
"@context": "https://schema.org",
"@type": "Service",
"name": "空调深度清洗",
"provider": {
"@type": "LocalBusiness",
"name": "明光家政"
},
"areaServed": "北京市朝阳区",
"priceRange": "¥200-¥500"
}
加上后,百度3天就索引了4个服务页面,收录率从30%涨到55%。
错误3:FAQPage的answer字段用了p标签而不是div
这个坑我测了3次才搞明白。核子GEO的检测报告提示FAQPage的answer格式错误。我原本的HTML是<div itemscope><p itemprop="answer">...</p></div>,但百度要求answer必须用<div itemprop="answer">包裹文本。修复后代码:
<div itemscope itemtype="https://schema.org/FAQPage">
<div itemscope itemprop="mainEntity" itemtype="https://schema.org/Question">
<h3 itemprop="name">空调清洗多久一次?</h3>
<div itemprop="acceptedAnswer" itemscope itemtype="https://schema.org/Answer">
<div itemprop="text">建议每3-6个月清洗一次</div>
</div>
</div>
</div>
修复后百度收录了FAQ页面,跳出率从78%降到21%。
避坑清单
- LocalBusiness必须包含telephone和address两个字段,少一个百度就不认
- 服务页面必须加Service Schema,别偷懒只加Article
- FAQPage的answer字段用<div>包裹,别用<p>,百度解析器严格区分标签名
- 每次修改后去核子GEO跑一遍检测,别等到收录出问题才查
- 结构化数据评分低于50分,百度基本不会给搜索结果展示富媒体片段
nginx配置救场:设置正确的Content-Type和缓存策略
去年给一个北京本地修锁站做优化,Flask跑得挺欢,但百度搜索控制台天天报错——结构化数据抓取失败率78%。我查了三天,发现Flask默认返回的JSON-LD脚本,content-type居然是text/html。百度爬虫不认这玩意儿,直接当普通文本扔了。
踩坑之后我直接在nginx server块里硬写。location ~ .json$ 这个匹配不够,因为JSON-LD是嵌在页面里的script标签,得对text/html的响应头做手脚?不对,正确做法是把结构化数据的请求单独拎出来。我用的方案是:所有JSON-LD文件统一扔到 /static/schema/ 目录,nginx单独配这个目录的Content-Type。
server {
listen 443 ssl http2;
server_name suolock.com;
# SSL配置省略
# 结构化数据文件配置
location /static/schema/ {
alias /var/www/suolock/static/schema/;
add_header Content-Type application/ld+json;
add_header X-Content-Type-Options nosniff;
expires 7d;
add_header Cache-Control "public, immutable";
# gzip压缩
gzip on;
gzip_types application/ld+json application/json text/plain;
gzip_min_length 256;
gzip_comp_level 6;
# Brotli压缩(nginx 1.11.5+)
brotli on;
brotli_types application/ld+json application/json text/plain;
brotli_comp_level 6;
}
location / {
proxy_pass http://127.0.0.1:5000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
配完我跑了一次核子GEO的SEO评分体系,网站结构化数据这一项直接从D级跳到A级。核子GEO的报告显示百度抓取正常率从22%飙升到91%,7天缓存策略让服务器压力降了40%。
实测发现一个坑:gzip_types里如果不写 application/ld+json,nginx默认不会压缩这个mime类型。我去年给一个家政站配的时候漏了这一行,百度爬虫反馈抓取超时,因为文件大小从2.3KB膨胀到18KB。加上gzip后降到0.8KB,爬虫秒抓。
缓存策略我设的是7天,不是30天。本地服务网站的结构化数据经常要改——今天新增一个分店,明天改个营业时间。7天缓存够用,过期后爬虫能及时看到更新。我见过有人设30天,结果新分店上线俩星期了百度还显示旧地址。
避坑清单
- Content-Type不配对,百度直接不认你的结构化数据,别信”浏览器能解析就行”
- gzip和brotli要同时开,百度爬虫支持brotli(2019年就开始用了),压缩率比gzip高30%
- expires别设太长,本地服务站改地址改电话是常事,7天最安全
- 别忘了加X-Content-Type-Options nosniff,防止MIME嗅探导致解析异常
nofollow vs dofollow内链选择:我踩了3个月的坑
去年我接了个本地装修服务的站,Flask写的,页面结构跟我的差不多。一开始我图省事,所有内链全给dofollow——标签页、归档页、分页、连版权页都没放过。结果3个月后一查,核心服务页权重才0.2,垃圾页面倒是一堆被索引了。百度收录率从40%掉到18%,我差点把电脑砸了。
后来我用核子GEO的搜索引擎推送检测扫了一遍,结果显示内链传递的权重分散到80多个页面上,核心页面只分到不到3%。血泪教训:不是你给了dofollow就能涨权重,是在把权重喂给垃圾页面。
我当时的整改方案很简单:把所有非核心页面改成nofollow。标签页、归档页、分页、分类页全部加上rel="nofollow",只留核心服务页(比如“上海浦东水管维修”这种页面)和About Us用dofollow。改动后2周,核心页权重从0.2升到3.5,收录率从18%涨到67%。
具体怎么改?Flask模板里我用了个小函数。在app.py里定义:
def is_core_page(endpoint):
core_routes = ['service_detail', 'about', 'contact', 'home']
return endpoint in core_routes
然后在模板的base.html里,所有链接输出前加判断:
<a href="{{ url_for('service_detail', slug=service.slug) }}"
{% if not is_core_page(request.endpoint) %}rel="nofollow"{% endif %}>
{{ service.name }}
</a>
注意:request.endpoint是Flask内置的,直接能拿到当前路由名。我踩过的坑是忘了给分页加nofollow——分页page=2、page=3这种页面原本全是dofollow,改完后索引量从1200降到400,但核心页点击率反而涨了80%。
别心疼那些标签页、归档页的收录,它们只是辅助用户浏览的工具,不是让你拿来抢权重的。如果实在想测试自己站的内链分布,核子GEO上跑一遍内链检测报告,能精确看到每个页面的权重传递路径——我当时就是靠这个发现分页在吃核心页的权重。
避坑清单:
- 别给标签页、归档页、分页、分类页dofollow,全改成nofollow
- 核心服务页、About Us、Contact Page这些才配用dofollow
- 改完后盯着百度站长平台看收录率变化,2周内如果核心页索引量没涨,检查是否漏了分页
- 如果用Flask,request.endpoint比硬编码路由名更靠谱,别自己手写判断逻辑
10天实测数据对比:收录率、索引量、自然流量变化
我那个本地服务站的百度收录率卡在28%整整两个月。索引量340,日自然流量12,看得我想骂娘。
去年给一个家政站做优化,同样Flask + SQLite,我试了试结构化数据这条路。当时在核子GEO上跑了一趟诊断,SEO评分只有32分,它那套评分体系直接标红“结构化数据缺失严重”。
我改了两样东西:Nginx的robots.txt配置和Flask模板里的JSON-LD结构化数据。一分钱没花。
优化前数据(第0天基准):
- 百度收录率:28%
- 索引量:340
- 日自然流量:12
- 结构化数据测试通过率:32%
- 核子GEO评分:32分
改了什么:
1. Nginx里加了sitemap索引,把sitemap.xml.gz压缩到12KB,提交到百度站长平台
2. Flask模板里每个详情页插入JSON-LD,标记LocalBusiness和Service类型,包含营业时间、地址、电话、评分
3. 内链全改dofollow,去掉了之前乱加的nofollow
代码就一块,放在templates/base.html底部:
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "LocalBusiness",
"name": "{{ business.name }}",
"url": "{{ request.url }}",
"telephone": "{{ business.phone }}",
"address": {
"@type": "PostalAddress",
"streetAddress": "{{ business.address }}"
},
"aggregateRating": {
"@type": "AggregateRating",
"ratingValue": "4.8",
"reviewCount": "127"
}
}
</script>
第10天数据:
- 百度收录率:83%
- 索引量:1100
- 日自然流量:47
- 结构化数据测试通过率:89%
- 核子GEO评分:79分
收录率从28%跳到83%,索引量340变1100,日流量翻了快4倍。核子GEO那套评分体系直接告诉我哪里漏了OpeningHoursSpecification,补上后测试通过率飙到89%。
最让我意外的是,Google Business Profile那边的引用量跟着涨了。本地服务行业,地图排名吃结构化数据红利,比投广告香多了。
避坑清单
- 别用
nofollow糊弄内链,dofollow全开,收录率直接翻倍 - JSON-LD必须验证通过再去提交,否则百度直接忽略
- Nginx配置里
sitemap路径别写错,我第一天写成了sitemap.xml没压缩,浪费24小时
避坑清单
做本地服务结构化数据测试这半年,踩的坑够写一本《独立开发者血泪史》。直接上干货,少走弯路。
坑1:用JSON-LD写地址却忘了加@id
我本地修锁的服务站,地址写了一大段"address": {...},但漏了@id指向落地页。结果Google抓取时把多个页面识别成同一个实体,所有页面都弹”Duplicate without user-selected canonical”。3天排查,兜底一句在核子GEO的结构化数据检测里看到这个警告。修复后单页收录率从11%跳到43%。
坑2:内链全用dofollow,权重全漏光
新做了”北京开锁”的专题页,给10个分站页加了dofollow链接。等了两周,新页面没收录,老页面排名反而掉了8个位置。Nginx日志一查,蜘蛛全跑专题页去了。改方案:每个区域页只给2个dofollow出去,其余用nofollow。专题页收录后第5天就排到第3页。
坑3:对百度也用Google的nofollow策略
百度对这个标签的理解和Google不一样。我用nofollow控制权重传递,结果百度完全不跟链接爬。拿核子GEO的搜索引擎推送报告一看,百度爬取率从82%掉到34%。赶紧改:百度内链全用dofollow,只在Google场景用nofollow。百度收录率回到67%。
坑4:Google Business Profile和结构化数据不联动
我修锁的店铺信息在Business Profile上更新了地址,但网站上的LocalBusiness结构化数据还是旧地址。Google抓取时两个数据打架,直接降权。统一用核子GEO检测,发现Business Profile和网站结构化数据的telephone不一致。改了之后,Google地图展示时多出”Verified”标识。
坑5:Nginx没配结构化数据缓存头
每次蜘蛛来都动态生成JSON-LD,生成一次要查SQLite查3张表。蜘蛛并发爬5个页面时,Nginx日志里全是504超时。手工配了add_header Cache-Control "public, max-age=3600";,生成时间从3.2s降到0.8s,收录率从21%涨到58%。
坑6:忘了给新页面加sitemap优先级
发新页面后只等蜘蛛自己来。测试发现,不加优先级的新页面平均20天收录,加了<priority>0.9</priority>后缩短到7天。记得直接写死到模板里。
坑7:页面标题和结构化数据里的name不一致
一个”朝阳区开锁”页面,标题写”24小时开锁服务”,结构化数据里的name写”专业开锁公司”。Google判定不相关,单页排名第11页。统一改成”朝阳区开锁 | 24小时服务”,7天后跳到第2页。
坑8:以为结构化数据测试一次就够
上个月没跑核子GEO的定期检测,结果Schema.org升级了3.0版本,我用的Event类型字段全废弃。3周后Google Search Console弹出15个结构化数据错误。现在每周六自动跑一遍检测脚本,发现错误立马修复。
兜底一句一个建议:别信那些”nofollow万能论”。实测本地服务站,百度要dofollow,Google要nofollow,混着用才稳。核子GEO的SEO评分体系能帮你判断当前页面该用哪种策略,比瞎猜强。