本文约 3,470 字,预计阅读 9 分钟。文中命令与配置均经过实测,可直接参考执行。
引言:日志里 3000 次”百度蜘蛛”,百度说它没来过
资源平台显示当天抓取量 50,服务器日志里却有 3000 条 UA 含 Baiduspider 的请求。这种落差几乎只说明一件事:其中绝大部分是伪造 UA 的爬虫(采集器、扫描器、竞品监测)。它们照抄百度的 UA 字符串,目的就是绕过站长基于 UA 的白名单规则。如果你拿这些数字去评估”百度对我的态度”,结论会完全失真;更糟的是,如果你为了”照顾蜘蛛”给 UA 含 Baiduspider 的请求开了后门,等于给采集器让路。所以要学会验明正身。
原理分析:UA 可伪造,IP 与反向解析难伪造
UA(User-Agent)是客户端自己声明的字符串,想写什么就写什么,零成本伪造。真正难以伪造的是 IP 归属:百度蜘蛛的请求必然来自百度自有 IP 段。验证方法是”双向 DNS 校验”:
- 对日志里的 IP 做反向解析(PTR 记录),得到主机名;
- 该主机名应属于百度域名,常见形态为
*.baidu.com或*.baidu.jp; - 再对该主机名做正向解析(A 记录),得到的 IP 应与原始 IP 一致。
两步都对得上,才能认定为真实百度蜘蛛。百度官方也说明过,其蜘蛛的 UA 格式形如:
Mozilla/5.0 (compatible; Baiduspider/2.0; +http://www.baidu.com/search/spider.html)
移动端抓取常见 Baiduspider-render、Baiduspider-image(图片)、Baiduspider-video 等变体,末尾通常带有 +http://www.baidu.com/search/spider.html 这个说明链接。注意 UA 里带这个说明页是百度蜘蛛的重要特征,但仍需配合 IP 校验。
保姆级实操
第一步:从日志提取声称是百度的 IP
LOG=/var/log/nginx/access.log
# 提取 UA 含 Baiduspider 的来源 IP 并去重
grep -i "Baiduspider" $LOG | awk '{print $1}' | sort | uniq -c | sort -rn > /tmp/spider_ip.txt
head -20 /tmp/spider_ip.txt
# 反向解析:真蜘蛛的 PTR 应指向 baidu.com / baidu.jp
while read -r count ip; do
ptr=$(dig +short -x "$ip" | head -1)
echo "$count $ip -> ${ptr:-NONE}"
done < /tmp/spider_ip.txt | head -30
第二步:双向校验单个 IP(确认真伪后再按百度抓取诊断工具使用技巧验证页面能否被抓到)
#!/usr/bin/env bash
# verify_baidu_spider.sh <ip>
IP=$1
PTR=$(dig +short -x "$IP" | head -1 | sed 's/\.$//')
echo "IP : $IP"
echo "PTR : ${PTR:-<none>}"
if [[ "$PTR" == *.baidu.com || "$PTR" == *.baidu.jp ]]; then
A=$(dig +short "$PTR" | grep -E '^[0-9]+\.' | head -1)
echo "A : ${A:-<none>}"
if [[ "$A" == "$IP" ]]; then
echo "结论 : 真实 Baiduspider"
else
echo "结论 : PTR 属于百度但正向解析不一致,需人工确认"
fi
else
echo "结论 : 非百度 IP,疑似伪造 UA"
fi
Windows 环境可用 nslookup <ip> 做反向解析,再 nslookup <主机名> 做正向解析,逻辑完全一致。
第三步:PHP 在线校验(用于日志分析工具或插件)
<?php
function mmf_is_real_baiduspider( string $ip ): bool {
// 1) 反向解析
$ptr = gethostbyaddr( $ip );
if ( ! $ptr || $ptr === $ip ) {
return false;
}
// 2) 主机名必须属于百度域名
if ( ! preg_match( '/\.baidu\.(com|jp)$/i', $ptr ) ) {
return false;
}
// 3) 正向解析必须回到同一个 IP
$a = gethostbynamel( rtrim( $ptr, '.' ) );
return is_array( $a ) && in_array( $ip, $a, true );
}
// 使用示例
$ip = $_SERVER['REMOTE_ADDR'] ?? '';
$ua = $_SERVER['HTTP_USER_AGENT'] ?? '';
$real = ( strpos( $ua, 'Baiduspider' ) !== false ) && mmf_is_real_baiduspider( $ip );
error_log( sprintf( '[spider] ip=%s ua=%s real=%s', $ip, $ua, $real ? 'yes' : 'no' ) );
第四步:把结果用起来
- 统计真实抓取量:只统计通过双向校验的 IP。
- 防火墙白名单:可以按 UA 放行,但对”UA 是百度但 IP 非百度”的请求直接限流。
- 不要因为”蜘蛛来得多”就给资源,先确认真伪。
第五步:注意 CDN 场景
若站点接入 CDN,日志里的 REMOTE_ADDR 是 CDN 节点 IP,需要改用 X-Forwarded-For / CF-Connecting-IP 等头获取真实来源,否则校验必然失败。
常见踩坑
- 只校验 UA 就放行:伪造成本为零,这是最常见的安全与统计陷阱。
- 把 PTR 属于百度当作充分条件:必须做正向解析回验,否则可能放过利用 PTR 伪装的 IP。
- CDN 后面取错 IP:直接用 REMOTE_ADDR 得到的是节点 IP,校验全部失败,会误判”没有真蜘蛛”。
- 把 Baiduspider-image / -render 当假蜘蛛:它们是百度不同用途的抓取器,UA 不同但同样需 IP 校验。
- 案例:某站统计出”百度每天抓 5000 次”,但资源平台只显示 200。用双向 DNS 校验后发现 4800 次来自境外机房,PTR 指向某云服务商,属采集器伪造。把这部分从统计中剔除后,才看清真实抓取量其实一直在下降。
- 用 gethostbyaddr 做高频校验拖慢请求:DNS 查询有开销,应只在日志分析离线脚本里跑,不要放进前台请求。
- IP 段写死在配置里:百度 IP 段会变动,硬编码会导致后续漏判,应始终用 DNS 校验。
总结
判断标准:只有”UA 匹配 + 反向解析属百度域名 + 正向解析回到同一 IP”三者同时成立,才认定为真实 Baiduspider。行动清单:从日志提取声称百度的 IP → dig 反解 → 正向回验 → 分别统计真实与伪造量 → 防火墙按校验结果放行 → CDN 场景改取 X-Forwarded-For。确认蜘蛛真伪后,下一步就是服务器日志分析百度是否真的来过。
