搜索引擎爬虫到底有没有来
个人站长做 SEO,最常见的困惑不是「怎么优化」,而是「我改了这么多,搜索引擎到底有没有看到」。很多人靠猜:盯着百度站长平台或者 Google Search Console 的图表看,但那些数据往往滞后几天,而且不会告诉你爬虫具体卡在哪一步。
其实答案就藏在你自己的 Nginx 访问日志里。搜索引擎爬虫每一次来访,都会在日志里留下一条带 User-Agent 的记录,包括它请求了哪个 URL、返回了什么状态码、消耗了多少时间。把这些记录分析清楚,收录问题基本就能定位到具体原因。本文用 GoAccess 这个工具,搭一套属于自己的爬虫诊断面板。
为什么不用现成的统计工具
百度统计、Google Analytics 这类前端统计工具依赖 JavaScript 执行,而搜索引擎爬虫绝大多数不执行 JS。这意味着你在统计后台看到的流量,几乎全是真人访问,爬虫流量是完全缺失的。更麻烦的是,你无法从这些工具里得知爬虫被 403 挡了多少次、被 404 挡了多少次。
服务端日志则记录了全部请求,不管是人是爬虫,不管是 200 还是 500。这是唯一完整的真相来源。
先确认日志格式够用
默认的 Nginx combined 格式包含 IP、时间、请求行、状态码、Referer 和 User-Agent,对爬虫分析来说已经足够。但如果你想要响应时间,就需要自定义格式。推荐在 nginx.conf 的 http 块中定义:
log_format seo_analysis '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'rt=$request_time uct=$upstream_connect_time '
'urt=$upstream_response_time';然后在站点的 server 块里引用:
access_log /www/wwwlogs/zz1984.log seo_analysis;
access_log /www/wwwlogs/zz1984-crawler.log seo_analysis;改完执行 nginx -t && nginx -s reload。这里需要注意,日志格式一旦变更,新老日志的字段数会不一致,GoAccess 解析时会报 malformed 记录。所以建议变更时把旧日志归档改名,让新日志从零开始。
用 grep 做最直接的爬虫体检
在装工具之前,先用最朴素的命令确认爬虫是否真的在访问。下面这几条命令能立刻给出答案:
# 统计各搜索引擎爬虫的访问次数
grep -iE 'Baiduspider|Googlebot|bingbot|Sogou web spider|360Spider|YisouSpider' \
/www/wwwlogs/zz1984.log | wc -l
# 分别统计
for ua in Baiduspider Googlebot bingbot YisouSpider; do
echo -n "$ua: "
grep -c -i "$ua" /www/wwwlogs/zz1984.log
done如果某个爬虫的数字是 0,那问题很简单:它压根没来,不用再往下查收录了,应该去检查 robots.txt 是否全站 Disallow、是否有 IP 层防火墙拦截、以及服务器是否长时间不可达。
确认爬虫来过之后,接着看它拿到的是什么状态码,这往往就是收录失败的直接原因:
# 查看百度爬虫遇到的所有非 200 响应
grep -i 'Baiduspider' /www/wwwlogs/zz1984.log \
| awk '{print $9}' | sort | uniq -c | sort -rn
# 列出被 403 挡掉的 URL
grep -i 'Baiduspider' /www/wwwlogs/zz1984.log \
| awk '$9 == 403 {print $7}' | sort -u | head -50这里的 $9 是状态码字段,$7 是请求路径。如果发现大量 403,通常意味着站点装了 WAF 或者 Nginx 里用了 deny 规则误伤爬虫;如果大量 429,是限流规则太激进;如果大量 503,则是服务器过载或者 PHP-FPM 队列打满,爬虫来了也抓不到内容。
爬虫 IP 反查:识别真假爬虫
日志里写着 Baiduspider 的请求,未必真的来自百度。伪装 UA 的采集器非常多,它们消耗你大量带宽。识别方法是对 IP 做反向 DNS 解析,真百度爬虫的 IP 反解一定落在 baidu.com 域名下:
# 提取访问最频繁的爬虫 IP
grep -i 'Baiduspider' /www/wwwlogs/zz1984.log \
| awk '{print $1}' | sort | uniq -c | sort -rn | head -20
# 对某个 IP 做反向解析
dig -x 220.181.108.15 +short
# 正常结果类似:baiduspider-220-181-108-15.crawl.baidu.com.
# 如果返回的是某个 IDC 的域名,那就是伪造的批量验证可以写个小脚本:
grep -i 'Baiduspider' /www/wwwlogs/zz1984.log \
| awk '{print $1}' | sort -u | while read ip; do
host=$(dig -x "$ip" +short)
case "$host" in
*.baidu.com.) echo "REAL $ip $host" ;;
*) echo "FAKE $ip $host" ;;
esac
done | tee /tmp/spider_check.txt对确认为伪造的 IP 段,可以在 Nginx 里直接封掉,既省带宽也让日志更干净:
# 在 server 块或 http 块中
deny 1.2.3.0/24;
deny 45.67.89.10;安装并配置 GoAccess
GoAccess 是一个实时日志分析工具,能把 Nginx 日志渲染成可交互的 HTML 报告,非常适合放在服务器上做常驻诊断面板。安装方式按系统不同略有差异:
# Debian / Ubuntu
apt-get install -y goaccess
# 或者用官方源拿最新版
wget -O - https://deb.goaccess.io/gnugpg.key | apt-key add -
echo "deb https://deb.goaccess.io/ $(lsb_release -cs) main" \
> /etc/apt/sources.list.d/goaccess.list
apt-get update && apt-get install -y goaccess用配置文件的方式运行,避免每次敲一长串参数。新建 /etc/goaccess/zz1984.conf:
time-format %H:%M:%S
date-format %d/%b/%Y
log-format %h - %^ [%d:%t %^] "%r" %s %b "%R" "%u" "rt=%T"
output /www/wwwroot/stat/index.html
real-time-html true
port 7890
ws-url wss://stat.zz1984.com/ws
html-prefs {"theme":"bright","perPage":50}
html-report-title SEO 爬虫诊断
ignore-crawlers false
anonymize-ip true这里 ignore-crawlers false 是关键:GoAccess 默认会把已知爬虫单独归类,我们要的就是看清爬虫的行为,所以不要忽略它们。anonymize-ip true 则是在报告里把 IP 最后一段打码,避免面板万一暴露导致访客隐私泄露。
启动实时模式:
goaccess /www/wwwlogs/zz1984.log \
--config-file=/etc/goaccess/zz1984.conf \
--real-time-html \
--daemonize需要注意的坑有三个。第一,log-format 必须和 Nginx 里定义的格式严格逐字符对应,包括空格和引号,任何差异都会导致解析失败,日志里会出现大量 Token 'x' doesn't match specifier。第二,实时模式的前端通过 WebSocket 接收数据,如果站点走 HTTPS,ws-url 必须用 wss://,否则浏览器会因混合内容拦截而白屏。第三,GoAccess 读取日志需要权限,如果 nginx 日志是 600 且属主是 www,用 root 跑没问题,但用其他用户跑就要加入 adm 组或者放宽权限。
从报告里读收录问题的信号
GoAccess 报告里对 SEO 诊断最有价值的几个板块是:
Requests by Status Code。 如果 404 比例异常高(超过 5%),说明站内有大量死链,爬虫在浪费抓取配额。可以拿日志导出 404 URL 清单,做 301 定向到相关页面:
grep ' 404 ' /www/wwwlogs/zz1984.log \
| awk '{print $7}' | sort | uniq -c | sort -rn | head -50 \
> /tmp/404_list.txtTop Requested Files。 如果爬虫反复抓取的 URL 高度集中,而新发布的内容几乎没被请求过,说明内链结构有问题——新文章没有被站内链接指向,爬虫发现不了。解决办法是在首页、分类页、相关文章模块里给新内容足够的曝光入口。
Time Distribution。 观察爬虫的抓取时段分布。如果集中在深夜且每小时只有几条,说明抓取频次被限制在很低的水位,站点的整体权重或响应速度还有提升空间。
Bandwidth。 如果爬虫占用了大量带宽但页面收录没有增加,说明它在抓取无价值页面,比如分页、标签云、搜索结果的 URL 参数页。这时应该在 robots.txt 里屏蔽这些页面,把抓取配额留给真正的内容页。
robots.txt 与日志的配合
一个常见的错误是:robots.txt 里屏蔽了某个目录,但日志显示爬虫仍在大量请求它。原因是对 robots.txt 的 Disallow 只是「请求不要再抓」,并不能阻止之前的旧链接被抓到,也不能阻止恶意爬虫。正确的做法是 Disallow + 页面加 noindex 双管齐下,但要注意两者不能同时用——被 Disallow 的页面爬虫看不到页面内容,也就看不到 noindex 标签,标签会失效。所以对需要保留但不想收录的页面,应该用 noindex 而不是 Disallow。
验证 robots.txt 是否正确生效:
curl -s https://www.zz1984.com/robots.txt?_=$(date +%s)
# 检查自己的写法是否合法(会指出语法错误和冲突规则)
curl -s -A "Googlebot" https://www.zz1984.com/robots.txt收录慢与新页面堆积的典型信号
除了状态码,日志还能告诉你一个更隐蔽的问题:新发布的文章明明在 sitemap 里,爬虫却迟迟不来抓。判断方法是把 sitemap 中的 URL 列表与日志中出现过的 URL 做交集运算。如果新文章发布的头三天在日志里完全找不到记录,说明发现机制出了问题,而不是抓取机制出了问题。
常见原因有三种。第一,sitemap 没有在 robots.txt 里声明,爬虫不知道去哪里找这份清单。第二,sitemap.xml 返回的 Content-Type 不对(比如返回了 text/html 而不是 application/xml),部分爬虫会直接忽略。第三,站点没有主动向搜索引擎提交 sitemap,只靠爬虫自己周期性巡站,而这个周期可能长达数周。
用下面这条命令可以直接验证爬虫是否抓取过 sitemap:
grep -i 'sitemap' /www/wwwlogs/zz1984.log | tail -20
# 确认 sitemap 的可访问性和类型
curl -sI https://www.zz1984.com/sitemap.xml | grep -i content-type
# 正确应返回:content-type: application/xml另一个高频信号是「抓取深度过浅」。如果日志显示爬虫只抓过首页和少量一级页面,从不进入文章详情页,那多半是内链结构的问题:首页文章列表用了 JavaScript 动态加载,或者链接用了 onclick 跳转而不是标准的 <a href>。爬虫不执行 JS 的情况下,这些链接对它来说根本不存在。修复方式是把关键链接改成服务端渲染的标准超链接,保证在关闭 JS 的情况下页面依然有完整的可点击路径。
建立每日爬虫监控
把下面这段脚本放进 crontab,每天生成一份爬虫概况,改动 SEO 之后能立刻看到效果:
#!/bin/bash
LOG="/www/wwwlogs/zz1984.log"
OUT="/var/log/seo/crawler-$(date +%F).txt"
mkdir -p /var/log/seo
{
echo "=== 报告日期: $(date '+%F %T') ==="
echo
echo "--- 各爬虫请求量 ---"
for ua in Baiduspider Googlebot bingbot YisouSpider 360Spider Sogou; do
printf "%-14s %s\n" "$ua" "$(grep -c -i "$ua" "$LOG")"
done
echo
echo "--- 爬虫状态码分布 ---"
grep -iE 'spider|bot' "$LOG" | awk '{print $9}' \
| sort | uniq -c | sort -rn
echo
echo "--- 被爬虫请求最多的 20 个页面 ---"
grep -iE 'spider|bot' "$LOG" | awk '{print $7}' \
| sort | uniq -c | sort -rn | head -20
echo
echo "--- 4xx/5xx 合计 ---"
grep -iE 'spider|bot' "$LOG" | awk '$9 >= 400' | wc -l
} > "$OUT"
# 只保留 30 天
find /var/log/seo -name 'crawler-*.txt' -mtime +30 -delete加进定时任务:
10 6 * * * /bin/bash /opt/seo/crawler-report.sh每天六点生成前一天的概况,改动 robots.txt、调整内链、发布新文章之后,第二天就能从数字上看到爬虫反应是否积极,而不是干等站长平台的延迟数据。
结语
SEO 的效果反馈慢,但爬虫的行为反馈是即时的。日志里的每一条记录都在告诉你:爬虫来没来、拿到了什么、卡在哪里。与其反复猜测算法喜好,不如先把这套基于日志的观测体系建起来——把不可观测的问题变成可测量的数字,剩下的优化才有方向。