You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP使用cookie统计独立访客数量与实际不符问题求助

问题排查与修复方案

核心问题原因

  • 爬虫过滤规则失效:原正则匹配规则过于宽泛,加入了get、java这类普通用户UA也可能包含的关键词,同时大量小众爬虫UA没有被覆盖,导致绝大多数爬虫请求没有被过滤,直接进入统计逻辑。
  • 爬虫天然不携带Cookie:爬虫每次请求都不会保存和携带Cookie,每次访问都会触发!isset($_COOKIE['Q_zWnE8_aq'])的判断分支,若爬虫IP未被记录就会被当做新访客入库,这是统计数虚高的核心原因。
  • IP获取逻辑不可靠:HTTP_X_FORWARDED_FOR和HTTP_CLIENT_IP头可以被任意伪造,爬虫可以通过修改这两个头每次生成不同的IP标识,导致重复入库。
  • 逻辑存在疏漏:原代码插入数据时用到的$id变量未定义,且仅靠IP判断是否为老访客,很容易因为IP复用、动态IP变化出现误判。

修复方案

1. 优化爬虫过滤规则

删除正则中过于宽泛的匹配关键词,仅保留明确的爬虫相关标识,避免误判同时提升爬虫覆盖率:

// 优化后的爬虫UA匹配规则
$botPattern = '/bot|crawl|spider|googlebot|bingbot|yandex|baiduspider|360spider|sogou|curl|wget|libwww-perl|facebookexternalhit|teoma|majesticsEO/i';
if (preg_match($botPattern, $_SERVER['HTTP_USER_AGENT'])) {
    // 判定为爬虫,跳过统计
    return;
}

2. 修正IP获取逻辑

如果你的站点没有使用CDN、反向代理,直接取TCP层不可伪造的REMOTE_ADDR即可;如果使用了CDN,替换为CDN约定的真实IP头,取第一个有效IP避免伪造:

// 无代理/CDN场景直接取REMOTE_ADDR
$ip = $_SERVER['REMOTE_ADDR'];

// 使用CDN的场景示例,以阿里云CDN为例,取X-Forwarded-For第一个IP
// $ip = trim(explode(',', $_SERVER['HTTP_X_FORWARDED_FOR'])[0]);

3. 调整独立访客判断逻辑

新增UA字段联合IP判断,避免同IP下不同用户误判、以及爬虫伪造IP导致的重复统计,同时移除未定义的$id变量适配自增主键:

include 'configuration.php';
$botPattern = '/bot|crawl|spider|googlebot|bingbot|yandex|baiduspider|360spider|sogou|curl|wget|libwww-perl|facebookexternalhit|teoma|majesticsEO/i';
$ua = $_SERVER['HTTP_USER_AGENT'] ?? '';
// 过滤爬虫
if (preg_match($botPattern, $ua)) {
    return;
}
// 取真实IP
$ip = $_SERVER['REMOTE_ADDR'];
// 已有Cookie直接判定为老访客,跳过统计
if (isset($_COOKIE['Q_zWnE8_aq'])) {
    return;
}
// 新访客设置Cookie
$name = 'Q_zWnE8_aq';
$value = bin2hex(random_bytes(10));
$expires = time() + 15780000; // 6个月
$path = "/";
$domain = "mydomain.in";
setcookie($name, $value, $expires, $path, $domain);

// 联合IP+UA判断是否为已记录的访客,大幅降低误判概率
$sql010 = $conn2->prepare("SELECT * FROM unique_vistor WHERE ip = ? AND ua = ?");
$sql010->bind_param("ss", $ip, $ua);
$sql010->execute();
$reS = $sql010->get_result()->fetch_all(MYSQLI_ASSOC);
if (count($reS) == 0) {
    $new_visitor = 1;
    $result55 = $conn2->prepare("INSERT INTO unique_vistor(name,value,expires,new_visitor,ip,ua) VALUES (?,?,?,?,?,?)");
    $result55->bind_param("sssiss", $name, $value, $expires, $new_visitor, $ip, $ua);
    $result55->execute();
    $result55->close();
}
$sql010->close();

额外优化建议

  • 给unique_vistor表的ip和ua字段加联合唯一索引,避免重复插入脏数据。
  • 定期清理数据库中过期的访客记录,和Cookie有效期保持一致。
  • 过滤掉非页面请求,例如静态资源、接口请求,仅统计页面访问的请求。

内容的提问来源于stack exchange,提问作者Rishabh Raj

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 15:45:03