微信、QQ 内置浏览器打开提示与爬虫身份校验

微信、QQ 内置浏览器打开提示与爬虫身份校验

微信和 QQ 的内置浏览器,在文件下载、视频播放或外部链接跳转时,可能和系统浏览器表现不同。遇到兼容性问题,可以尝试调用客户端提供的接口,或者提示用户从菜单中选择“在浏览器中打开”。下面分别整理 QQ 跳转、微信提示,以及搜索引擎爬虫的身份校验。

破壁行动:救救被困在内置浏览器里的用户 插图1

1. QQ 内置浏览器:尝试打开系统浏览器

代码示例:

<?php
// 检测 QQ 内置浏览器
// 配置开关
$settings = [
    'qq_redirect' => true
];

// 判断是否为 QQ 内置浏览器
$userAgent = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : '';
if ($settings['qq_redirect'] && stripos($userAgent, 'QQ/') !== false) {
    $currentUrl = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? 'https://' : 'http://')
                . $_SERVER['HTTP_HOST']
                . $_SERVER['REQUEST_URI'];
    ?>
    <!DOCTYPE html>
    <html lang="zh-CN">
    <head>
        <meta charset="UTF-8">
        <title>正在跳转到系统浏览器...</title>
        <script src="https://open.mobile.qq.com/sdk/qqapi.js?_bid=152"></script>
        <script>
            (function(){
                mqq.ui.openUrl({
                    target: 2,
                    url: <?php echo json_encode($currentUrl, JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT); ?>
                });
            })();
        </script>
    </head>
    <body>
    </body>
    </html>
    <?php
    exit;
}
?>
  • 实现方法:检查 User-Agent 中是否包含 QQ/,再调用 QQ JS-SDK 的 mqq.ui.openUrl。
  • 预期效果:客户端支持该接口时,尝试在系统浏览器中打开当前页面。
  • 兼容性:接口行为会受 QQ 版本、系统和客户端策略影响。这里保留这一写法,不能据此保证当前所有设备都能自动跳转;失败时应保留手动打开的提示。URL 写入 JavaScript 前用 json_encode 编码,避免引号等字符破坏脚本。
破壁行动:救救被困在内置浏览器里的用户 插图2

2. 微信与 QQ:提示用户手动打开

无法可靠地自动唤起外部浏览器时,可以给出清楚的手动操作提示。下面的 WordPress 示例会在检测到微信或 QQ 的 User-Agent 后显示提示。

代码示例:

<?php
// 在微信或 QQ 内置浏览器中提示用户
// 在微信或 QQ 内置浏览器中弹出温馨提示
function show_wechat_qq_notice() {
    $ua = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : '';
    if (stripos($ua, 'MicroMessenger') !== false || stripos($ua, 'QQ') !== false) {
        ?>
        <script>
            window.addEventListener('load', function () {
                alert("温馨提示:为获得更稳定的文件下载体验,建议使用系统浏览器下载。\n请点击右上角菜单,选择【在浏览器中打开】进行下载。");
            });
        </script>
        <?php
    }
}
add_action('wp_head', 'show_wechat_qq_notice');
  • 实现方法:通过 User-Agent 中的 MicroMessenger 或 QQ 做兼容性判断,再在页面加载完成后弹出提示。User-Agent 只能作为提示依据,可以被修改,也可能存在误判。
  • 优缺点:alert 接入简单,但会打断操作。实际使用时可以改为不遮挡内容的提示,并清楚说明“点击右上角菜单,选择在浏览器中打开”。

处理策略:QQ 可以先尝试客户端接口;微信或调用失败的 QQ 则提供手动打开的方法。两段代码需要结合页面流程接入,不能把它们简单拼接后就假定拥有完整的失败回退逻辑。

破壁行动:救救被困在内置浏览器里的用户 插图3

3. 用正反向 DNS 校验搜索引擎爬虫

User-Agent 写着 Googlebot 或 Baiduspider,并不能单独证明请求来自对应搜索引擎。可以对来源 IP 做反向 DNS 查询,再对返回域名做正向查询,最后匹配搜索引擎的域名规则。

代码示例:下面保留域名规则表与三个测试 IP。IP 注释仅表示示例用途,不代表这些地址当前已通过验证。gethostbynamel 只返回 IPv4,因此这个示例不能完整覆盖 IPv6;生产环境还需要处理 AAAA 记录并对 IP 做标准化比较。规则表应按各搜索引擎官方文档维护,参见Google 请求校验说明及Bingbot 校验工具。

<?php
/**
 * 验证指定IP是否为真实搜索引擎蜘蛛(基于反向+正向DNS解析)
 * @param string $ip 待验证的IP地址
 * @return array 验证结果(is_valid: 是否真实, spider: 蜘蛛名称, domain: 解析域名)
 */
function verifySpiderByIp(string $ip): array {
    // 验证IP格式
    if (!filter_var($ip, FILTER_VALIDATE_IP)) {
        return [
            'is_valid' => false,
            'spider'   => '未知',
            'domain'   => '无效的IP地址'
        ];
    }

    // 反向解析 IP -> 域名
    $reverseDomain = gethostbyaddr($ip);
    if ($reverseDomain === $ip || $reverseDomain === false) {
        return [
            'is_valid' => false,
            'spider'   => '未知',
            'domain'   => '反向DNS解析失败'
        ];
    }

    // 正向解析 域名 -> IP 验证
    $forwardIps = gethostbynamel($reverseDomain); // 可能返回多个IP
    if (!$forwardIps || !in_array($ip, $forwardIps)) {
        return [
            'is_valid' => false,
            'spider'   => '未知',
            'domain'   => $reverseDomain . '(正向解析IP不匹配)'
        ];
    }

    // 搜索引擎域名规则
    $spiderRules = [
        'Googlebot'    => '/\.googlebot\.com$/',
        'Baiduspider'  => '/(\.baiduspider\.com|\.crawl\.baidu\.com)$/',
        'Bingbot'      => '/(\.search\.msn\.com|\.bingbot\.com)$/',
        'YandexBot'    => '/\.yandex\.com$/',
        'Sogou Spider' => '/\.sogou\.com$/'
    ];

    foreach ($spiderRules as $name => $pattern) {
        if (preg_match($pattern, $reverseDomain)) {
            return [
                'is_valid' => true,
                'spider'   => $name,
                'domain'   => $reverseDomain
            ];
        }
    }

    // 未匹配到
    return [
        'is_valid' => false,
        'spider'   => '未知爬虫',
        'domain'   => $reverseDomain
    ];
}

// ------------------- 测试示例 -------------------
$testIps = [
    '66.249.66.1',     // Googlebot
    '220.181.108.1',   // Baiduspider
    '114.114.114.114'  // 普通DNS服务器
];

foreach ($testIps as $ip) {
    $res = verifySpiderByIp($ip);
    echo "验证IP: {$ip}<br>";
    echo "结果: " . ($res['is_valid'] ? '✅ 真实蜘蛛' : '❌ 非真实蜘蛛') . "<br>";
    echo "蜘蛛名称: {$res['spider']}<br>";
    echo "解析域名: {$res['domain']}<br><br>";
}
?>

校验流程:

  1. 反向解析:查询来源 IP 对应的域名。没有 PTR 记录或 DNS 查询失败时,结果是“无法验证”,不能只凭这一点认定请求恶意。
  2. 正向核对:把反向查询得到的完整域名再解析为 IP,并确认结果包含最初的来源 IP。
  3. 匹配规则:确认完整域名符合对应搜索引擎的官方域名后缀规则。没有通过这套规则,只表示没有被当前规则验证,不应直接等同于伪造爬虫。

性能:DNS 查询有额外开销,可以用 Redis 或 Memcached 缓存校验结果。比如将 12 小时作为一个可调整的缓存示例,再结合 DNS TTL、查询失败和站点实际流量决定过期策略,避免每次请求都重复解析。

破壁行动:救救被困在内置浏览器里的用户 插图4

整理一下

内置浏览器兼容性和爬虫身份校验是两个不同的问题,接入时分别处理:

  • 内置浏览器:支持客户端跳转时再调用,不支持时提供明确、可操作的手动提示。
  • 爬虫校验:User-Agent 只用于识别线索,身份判断需要结合正反向 DNS 和官方规则;保留“未验证”状态,避免误伤正常请求。
破壁行动:救救被困在内置浏览器里的用户 插图5
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容