Nuxt 3 流量暴涨但广告没涨:我用日志采样和 UA 过滤摘掉爬虫流量
一次后台流量冲高,广告收入却没动。我从 Node 日志、Redis 计数和客户端埋点入手,区分真实访问与爬虫流量,避免被虚假 PV 带偏。

作者
ZHOUYI
晚上看统计,博客 PV 翻了一倍,广告收入却几乎没变。第一反应不是广告位坏了,而是流量不干净:如果只有服务端请求,没有真实浏览器执行 JS,广告曝光自然不会涨。这类问题最容易误导人:看起来站点火了,实际只是被扫了一遍。
从 Node 日志里先采样
我没一上来全量入库,而是在服务端中间件里按路径采样,记录 UA、IP、路径和是否命中缓存。高频文章页全采,静态资源少采。采样不是偷懒,是为了先保住线上性能。日志先进 Redis 做小时级计数,再定期落到 MongoDB 里慢慢看,避免把主服务拖慢。
用客户端埋点做对照
真实用户通常会执行客户端脚本,所以我给页面加了一个很轻的上报:页面可见且停留超过几秒才记一次有效阅读。服务端 PV 和客户端有效阅读一对比,差异最大的来源就显出来了:一些 UA 很规整、只请求 HTML、没有后续资源,也没有广告可见事件。
// 仅示意:按小时聚合 UA 计数
export default defineEventHandler(async (event) => {
const ua = getHeader(event, 'user-agent') || ''
const path = getRequestURL(event).pathname
if (!path.startsWith('/blog/')) return
const hour = new Date().toISOString().slice(0, 13)
await redis.hincrby(`traffic:${hour}`, normalizeUA(ua), 1)
})具体计数我用 Redis 的哈希,按小时存,字段是归一化后的 UA。这样看哪个 UA 突增很明显。等确认模式后,再用定时任务把异常样本写入 MongoDB,方便后续做报表和排除。
我把这类流量标记为 suspect,而不是直接封掉。规则也很保守:UA 包含常见爬虫词、同一 IP 短时间大量访问列表页、只有服务端 PV 没有客户端埋点,三者命中两个才计入无效流量。这样能减少误伤。
踩坑和收口
- 别只看 PV,广告收入要看曝光和可视事件;
- UA 过滤只是第一层,真实浏览器爬虫也可能带 JS,需要结合行为频率;
- 保留原始日志样本,方便回查误判;
- 广告平台口径可能延迟,最终以官方报表为准。
“这次最大的收获不是抓了多少爬虫,而是把流量问题变成了可复盘的数据链路:先采样、再对照、后过滤,避免凭感觉下结论。”