如何根据 IP 获取位置?

本文涉及的产品
云解析DNS-重点域名监控,免费拨测 20万次(价值200元)
简介: 现在很多带有社交性质的应用都陆续的添加了显示地区的功能。为什么要公布属地呢?其实主要目的还是为了净化网络空间,减少网暴的或者谣言的出现。那么如何判断用户的地址呢?答:IP。

现在很多带有社交性质的应用都陆续的添加了显示地区的功能。为什么要公布属地呢?

其实主要目的还是为了净化网络空间,减少网暴的或者谣言的出现。

那么如何判断用户的地址呢?

答:IP

不同的IP 都有不同的属地,这些具体的属地信息一般由运营商来负责维护,也有部分组织或者个人收集维护了IP 对应地理位置的数据库供开发者付费或者免费使用(因为维护一个如此庞大的的数据库会耗费比较大的精力,所以大部分产品都是收费的)。

本文演示所用的 ipdb 是 ipip.net 提供的试用版,试用版比起付费版会少很多功能,我们只用来学习使用方式足够了(商用一定要选择付费版本,否则可能会律师函警告⚠️)。

由于 ipip 的 SDK 文档几乎是没有,所以我记录得详细一点 ipdb 文件和代码示例已经上传到文末 github,有需要可以去下载试用。


核心使用


因为我是个切图仔,所以我选择用 nodejs,我们需要需要下载 ipip 对应的nodejs SDK(全部语言 SDK可以去 github 自行查找)。

$ npm install ipip-ipdb
复制代码

然后编写 JS 脚本来解析,github 的文档基本没有,我在测试文件中发现的这几个 API

import { fileURLToPath } from 'node:url'
import { dirname, resolve } from 'node:path'
import ipdb from 'ipip-ipdb'
const __dirname = dirname(fileURLToPath(import.meta.url))
const client = new ipdb.City(resolve(__dirname, '../db/ipipfree.ipdb'))
function parseIP(ip) {
  console.log(client.findMap(ip, 'CN'))
  console.log(client.findInfo(ip, 'CN'))
}
复制代码

ipip-ipdb 最核心的 API 是一个 City 构造函数,可以创建一个实例。该实例有两个方法,findMap 和 findInfo,findMap 会返回国家、省份、城市的一个 Map 结构,findInfo 会返回一个包含多个信息的对象(试用版只能看到国家、省份、城市),内容如下

1682566140(1).png

总体来说原理就是通过他们维护的 ipdb 文件来查询 ip 的地理位置之间的映射关系,因为 IP 会发生变动,所以维护起来比较麻烦,而且试用版的更新频率也不确定,想要正常商用此功能还是要付费订阅比较好。


锦上添花


核心内容到上面就结束了,后面基础内容较多,可以顺便复习一下 koa 的使用

解析 IP 的工作一般是由后端来完成,所以我们需要搭建一个服务端程序。因为只演示这一个小功能,我们就不去使用那些花里胡哨的框架了,就用最简洁的 koa(或者你想用express等其他的都可以),页面渲染也直接使用模板渲染。

安装 koa 用到的中间件

$ npm install koa @koa/router koa-views ejs
复制代码

准备工作完成之后开始上才艺。还是经典的三段式,在根目录下新建 server.js

import Koa from 'koa'
import Router from '@koa/router'
const app = new Koa()
const router = new Router()
app.use(router.routes())
app.listen(4000, () => {
  console.log('IP 查询服务启动: 4000');
})
复制代码

然后编写路由,并通过ejs模板引擎进行渲染

import views from 'koa-views'
import { fileURLToPath } from 'node:url'
import { dirname } from 'node:path'
const __dirname = dirname(fileURLToPath(import.meta.url))
app.use(views(__dirname + '/views', {
  extension: 'ejs'
}))
router.get('/', async (ctx) => {
  await ctx.render('index', {ip: ''}) // 参数用于渲染内容,默认填入空
})
复制代码

模板引擎加载完成下一步开始编写模板,在 views 目录下新建index.ejs 文件并添加如下代码(省略了 style代码),逻辑控制部分的变量都是通过findInfo方法解析 IP 之后填入的数据。

<body>
  <script>
    window.onload = () => {
      // 加载完成时添加事件绑定
      const search = document.getElementById("search");
      search.addEventListener("keydown", (e) => {
        if(e.code === 'Enter') {
          location.search = '?ip=' + search.value
        }
      })
    }
  </script>
  <div class="container">
    <input id="search" class="search" placeholder="请输入 IP 地址" value="<%- ip %>" />
    <% if(locals.msg) { %>
      <p class="error-msg"><%- msg %> </p>
    <% } else if(locals.res) { %>
      <ul>
        <% if(res.countryName) { %>
          <li><%- res.countryName %> </li>
        <% } %>
        <% if(res.regionName) { %>
          <li><%- res.regionName %> </li>
        <% } %>
        <% if(res.cityName) { %>
          <li><%- res.cityName %> </li>
        <% } %>
      </ul>      
    <% } %> 
  </div>
</body>
复制代码

此时我们的渲染还没有传入数据,再回来完善一下这部分逻辑。执行过程大致为:判断 IP 是否传入,没有传入渲染空页面,有 IP 的话进行正则校验,格式错误报错,否则渲染解析后的数据。

router.get('/', async (ctx) => {
  const { ip } = ctx.request.query
  if (!ip) {
    // 没有 ip 渲染空页面
    await ctx.render('index', {ip: ''})
    return
  }
  if (!isIP(ip)) {
    // 不合法 IP 报错
    await ctx.render('index', { ip, msg: 'IP格式错误' })
  } else {
    // 检索省市区
    const res = parseIP(ip)
    // 返回带数据的页面
    await ctx.render('index', {ip, res})
  }
})
复制代码

此时的效果如下,比之前在控制台中执行要舒服一些

1682566170(1).png

再提供一个接口供 ajax 请求使用,直接返回解析的数据即可

router.get('/json', async (ctx) => {
  const { ip } = ctx.request.query
  if (!ip) {
    ctx.status = 400
    ctx.body = errorFormat(40001, 'IP 不能为空')
    return
  }
  if (!isIP(ip)) {
    ctx.status = 400
    ctx.body = errorFormat(40002, 'IP 格式错误')
  } else {
    const res = parseIP(ip)
    ctx.body = responseFormat(res)
  }
})
复制代码

代码已经上传 github,有需要可以自行拉取

相关文章
|
自然语言处理 安全 搜索推荐
强大的工具:IP归属地查询API
强大的工具: IP归属地查询API
2223 1
|
搜索推荐 前端开发 JavaScript
什么是百度优化?百度SEO优化解决方案
百度优化的解决方案不仅可以帮助企业提升网站在百度PC端的收录与关键词排名,也可以获得更好的移动端收录与关键词排名,从而达到品牌SEO推广及引流的目的。接下来小编为你详细分享什么是百度优化以及实用的解决方案,一起来看看吧。
1688 0
|
人工智能 文字识别 达摩院
阿里云文字识别(OCR)服务 Quick Start
阿里云文字识别(Optical Character Recognition,OCR)可以将图片中的文字信息转换为可编辑文本,是一款由阿里巴巴达摩院权威AI团队打造的全栈全场景OCR文本识别类产品。根据客户的业务场景和需求,将产品分为了通用文字识别、个人证照识别、票据凭证识别、教育场景识别、车辆物流识别、企业资质识别、小语种文字识别等,满足各种客户的图片识别需求。 由于阿里云视觉智能开放平台和云市场这两个渠道下也具备阿里文字识别服务,一些不熟悉的客户很容易将三者搞混淆,这边简单做下对比。然后再针对个人证照识别下常见的服务-身份证识别功能简单介绍下产品的开通及使用。
7791 0
阿里云文字识别(OCR)服务 Quick Start
|
JSON API PHP
Python/PHP:免费IP归属地查询接口和通过ip获取大致位置信息
Python/PHP:免费IP归属地查询接口和通过ip获取大致位置信息
1686 0
|
弹性计算
查看阿里云服务器IP地址的三种方法
查看阿里云服务器IP地址的三种方法
8314 1
|
存储 Java 定位技术
获取ip所在城市
本文介绍了如何在SpringBoot应用中通过IP地址快速获取用户的国家、省份和城市信息。首先,通过引入GeoLite2 City数据库并整合相关依赖,接着下载并配置GeoLite2 City数据库文件。然后,创建地址获取工具类和Controller接口,最后进行测试以确保功能正常。此方法简单高效,适用于多种应用场景。
|
JavaScript 前端开发 索引
JavaScript字符串检查:从基础到高级
【2月更文挑战第26天】
342 0
JavaScript字符串检查:从基础到高级
|
API 定位技术
查IP[查指定IP归属地]免费API接口教程
该API用于查询指定IPv4地址的归属地信息,支持POST和GET请求。需提供用户ID和KEY,可选填查询IP,默认为请求接口IP。返回信息包括状态码、地理位置及运营商等。示例请求和响应详见文档。
1939 3
|
Linux 开发工具 Python
【Deepin 20系统】Linux系统从零打造完美VScode for Python环境
如何在Deepin 20系统中从零开始配置一个完美的VScode for Python开发环境,包括安装Anaconda、VScode、必要的插件、汉化、主题和字体设置,以及如何运行和调试Python程序。
506 6
|
数据采集 JSON 数据格式
Python大麦网演唱会数据爬取
Python大麦网演唱会数据爬取
1010 0