Skip to content

给自己博客加个「IP属地」,访客来自哪一目了然

评论区显示"IP属地:广东",是这几年的流行玩法了。很多博主都想给自己的博客也加上,又怕太麻烦。其实真不难,静态博客都能做。

这篇文章以最常见的两种博客为例,讲讲思路和代码。核心服务用的是 IP9,因为免注册、免key,个人博客用着最省心。

核心思路就三步

  1. 浏览器访问你的博客,服务器能看到访客的IP;
  2. 拿这个IP去查归属地(调IP9接口);
  3. 把"省份城市"返回给前端显示。

关键点:查IP归属地的动作要在服务端做,别在前端直接调第三方接口——前端调的话拿不到真实IP(访问者IP是浏览器和服务器的,前端JS根本不知道),而且会跨域。

如果你是 WordPress / 动态站

直接用PHP查,然后在主题里输出:

php
// functions.php 里加个函数
function get_visitor_location() {
    $ip = $_SERVER['REMOTE_ADDR'];
    // 走了CDN的话,用这个取真实IP
    // $ip = $_SERVER['HTTP_X_FORWARDED_FOR'] ?? $_SERVER['REMOTE_ADDR'];
    $resp = wp_remote_get("https://ip9.com.cn/get?ip=$ip", ['timeout' => 3]);
    if (is_wp_error($resp)) return '未知';
    $data = json_decode(wp_remote_retrieve_body($resp), true);
    if ($data['ret'] != 200) return '未知';
    return $data['data']['prov'] . ' ' . $data['data']['city'];
}

然后在评论区模板里调用:

php
<p class="ip-loc">IP属地:<?php echo get_visitor_location(); ?></p>

别忘了加缓存:评论多的话,每个访客都实时查接口不划算。可以在函数里加个Session缓存,或者存成一个临时文件。

如果你是静态博客(Hexo / Hugo / VitePress)

静态博客没有后端,怎么拿IP?两条路:

方案A:评论服务带属地。如果你用的是 Gitalk / Waline / Twikoo 这类有后端的评论系统,直接在评论服务的服务端配置里加IP查询即可,前端零改动。

方案B:Serverless 中转。用云函数(Cloudflare Workers / Vercel Edge)做个代理,由它拿IP查归属地再返回。示例(Cloudflare Worker):

js
export default {
  async fetch(request) {
    const ip = request.headers.get('CF-Connecting-IP');
    const r = await fetch(`https://ip9.com.cn/get?ip=${ip}`);
    const data = await r.json();
    return new Response(JSON.stringify({
      loc: data.ret === 200 ? `${data.data.prov} ${data.data.city}` : '未知'
    }), {
      headers: { 'content-type': 'application/json', 'access-control-allow-origin': '*' }
    });
  }
}

前端再从这个代理地址拿结果渲染,就搞定了。

显示的时候注意这两点

  1. 海外用户:没有 provcity 时,就显示国家(country),别让海外访客看到一片空白。
  2. 容错:查询失败就静默,不显示或者显示"未知",别报错。

为什么我推荐这个方案

这类功能最烦的就是"注册、审核、限次数"。IP9 直接免注册用,接口又是标准GET,静态站、动态站都能接。我自己的博客就是这么挂的,跑了好久一直很稳。

如果你也想给自己博客加上属地,照上面抄就行。接口文档:https://www.ip9.com.cn