效果

image-20250423164016384

前言

在网站的隐私政策中往往需要用到获取信息用来告知用户获取了哪些信息,显示当前用户的个人信息可以直观的感受。

我最开始在网上看到像安知鱼以及其他个人博客网站的隐私政策都会有一个获取用户信息并呈现出来的效果。

一顿搜索后只有这一篇文章可以用。引用文章Hexo隐私政策中的IP客户端信息 | 青桔气球

不过这是两年前的文章了,还好API接口能用。

获取IP和地理信息用到的APIAPI聚合网站名称-免费、稳定、易用的webapi接口调用

这个网站推荐一下,获取IP和地理位置信息都是免费的。以后不知道需不需要收费。本人的API接口也是调用的这个网站

一、html表格添加id

准备好自己的md文件,并把下面html表格代码粘贴到md文件内

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
<!-- 在表格中添加 id 以便于通过 JavaScript 获取元素 -->
<table>
<thead>
<tr>
<th>类型</th>
<th>信息</th>
</tr>
</thead>
<tbody>
<tr>
<td colspan="2"><b>网络信息</b></td>
</tr>
<tr>
<td>IP地址</td>
<td><div id="userAgentIp"></div></td>
</tr>
<tr>
<td>国家</td>
<td><div id="userAgentCountry"></div></td>
</tr>
<tr>
<td>省份</td>
<td><div id="userAgentProv"></div></td>
</tr>
<tr>
<td>城市</td>
<td><div id="userAgentCity"></div></td>
</tr>
<tr>
<td>运营商</td>
<td><div id="userAgentISP"></div></td>
</tr>
<tr>
<td colspan="2"><b>设备信息</b></td>
</tr>
<tr>
<td>设备</td>
<td><div id="userAgentDevice"></div></td>
</tr>
<!-- <tr>
<td>操作系统</td>
<td><div id="userAgentOS"></div></td>
</tr>
<tr>
<td>浏览器</td>
<td><div id="userAgentBrowser"></div></td>
</tr> -->
</tbody>
</table>

二、js获取ID更改内容

api key获取步骤

API聚合网站奶思猫登录进去找到用户控制台

image-20250423165147996

找到左侧密钥管理image-20250423165245401

然后在md文章的最下面粘贴JavaScript文件

根据引用的Hexo隐私政策中的IP客户端信息 | 青桔气球文章,JavaScript文章内的接口已经维护了,我又找的另一个ipv4的api接口,是一样的。

把你的API密钥粘贴到script代码中的https://api.nsmao.net/api/ipip/query?key=你的API密钥

最好访问检查一下网址路径https://api.nsmao.net/api/ipip/query?key=你的API密钥

访问这个路径后,正常的应该是这样

image-20250423165731574

正常显示说明api接口调用成功,然后开始用JavaScript脚本进行获取api信息和设备信息

基于原文章的JavaScript的内容进行了更改

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
<script>
//获取设备信息
let userAgent = navigator.userAgent;
console.log(userAgent);
document.getElementById("userAgentDevice").textContent = userAgent
// 获取ip信息函数
async function getIpInfo() {
try {
// 更改此处API密钥
const response = await fetch(`https://api.nsmao.net/api/ipip/query?key=你的API密钥`);

if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}

const json = await response.json();

// 修正1:根据API实际返回结构调整数据映射
document.getElementById("userAgentIp").textContent = json.data.ip || "未能获取到信息";
document.getElementById("userAgentCountry").textContent = json.data.country || "未能获取到信息";
document.getElementById("userAgentProv").textContent = json.data.province || "未能获取到信息";
document.getElementById("userAgentCity").textContent = json.data.city || "未能获取到信息";
document.getElementById("userAgentISP").textContent = json.data.isp || "未能获取到信息";

} catch (error) {
console.error('获取IP信息失败:', error);
// 失败时显示默认值
document.getElementById("userAgentIp").textContent = "未能获取到信息";
document.getElementById("userAgentCountry").textContent = "未能获取到信息";
document.getElementById("userAgentProv").textContent = "未能获取到信息";
document.getElementById("userAgentCity").textContent = "未能获取到信息";
document.getElementById("userAgentISP").textContent = "未能获取到信息";
}
}

// 修正2:添加获取用户IP的辅助函数
function getUserIP() {
// 通过WebRTC获取本地IP(需要HTTPS环境)
return new Promise((resolve, reject) => {
const pc = new RTCPeerConnection({iceServers: []});
pc.createDataChannel('');
pc.createOffer().then(offer => pc.setLocalDescription(offer));

pc.onicecandidate = (ice) => {
if (!ice.candidate) return;
const ip = ice.candidate.candidate.split(' ')[4];
resolve(ip);
pc.close();
};
});
}
// 修正3:添加页面加载完成后执行
window.onload = getIpInfo;
</script>

三、获取设备信息

我用的JavaScript中的navigator.userAgent方法,再将获取到的信息用document更改到表格内

1
2
3
4
//获取设备信息
let userAgent = navigator.userAgent;
console.log(userAgent);
document.getElementById("userAgentDevice").textContent = userAgent

最后

步骤其实很简单,本人也是根据原来文章的js代码进行了更改,

参考原文章的js代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<!-- 在模板文件中添加 JavaScript 代码 -->
<script>
// 获取ip
function getIpInfo(){
var fetchUrl = "https://api.nsmao.net/api/ipv4/query?key=你的key" //key申请:https://api.nsmao.net
.then(res => res.json())
.then(json =>{
var country = json.data.country || "未能获取到信息";
var ip = json.data.ip || "未能获取到信息";
var province = json.data.province || "未能获取到信息";
var city = json.data.city || "未能获取到信息";
var districts = json.data.districts || "未能获取到信息"
var isp = json.data.isp || "未能获取到信息";

document.getElementById("userAgentIp").innerHTML = ip;
document.getElementById("userAgentCountry").innerHTML = country;
document.getElementById("userAgentProv").innerHTML = province;
document.getElementById("userAgentCity").innerHTML = city;
document.getElementById("userAgentISP").innerHTML = isp;

// 使用ua-parser-js解析User-Agent
var parser = new UAParser();
var result = parser.getResult();
document.getElementById("userAgentOS").innerHTML = result.os.name + " " + result.os.version;
document.getElementById("userAgentBrowser").innerHTML = result.browser.name + " " + result.browser.version;
})
}

getIpInfo()
</script>

我访问这个api接口地址发现是维护了,

image-20250423170804148

我更改能使用的API地址发现也无法正常呈现在博客上,但是访问是可以正常访问的

然后用AI检查了一下JavaScript代码,发现存在几个需要修正的地方。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
<script>
//获取设备信息
let userAgent = navigator.userAgent;
console.log(userAgent);
document.getElementById("userAgentDevice").textContent = userAgent
// 获取ip信息函数
async function getIpInfo() {
try {
// 更改此处API密钥
const response = await fetch(`https://api.nsmao.net/api/ipip/query?key=你的API密钥`);

if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}

const json = await response.json();

// 修正1:根据API实际返回结构调整数据映射
document.getElementById("userAgentIp").textContent = json.data.ip || "未能获取到信息";
document.getElementById("userAgentCountry").textContent = json.data.country || "未能获取到信息";
document.getElementById("userAgentProv").textContent = json.data.province || "未能获取到信息";
document.getElementById("userAgentCity").textContent = json.data.city || "未能获取到信息";
document.getElementById("userAgentISP").textContent = json.data.isp || "未能获取到信息";

} catch (error) {
console.error('获取IP信息失败:', error);
// 失败时显示默认值
document.getElementById("userAgentIp").textContent = "未能获取到信息";
document.getElementById("userAgentCountry").textContent = "未能获取到信息";
document.getElementById("userAgentProv").textContent = "未能获取到信息";
document.getElementById("userAgentCity").textContent = "未能获取到信息";
document.getElementById("userAgentISP").textContent = "未能获取到信息";
}
}

// 修正2:添加获取用户IP的辅助函数
function getUserIP() {
// 通过WebRTC获取本地IP(需要HTTPS环境)
return new Promise((resolve, reject) => {
const pc = new RTCPeerConnection({iceServers: []});
pc.createDataChannel('');
pc.createOffer().then(offer => pc.setLocalDescription(offer));

pc.onicecandidate = (ice) => {
if (!ice.candidate) return;
const ip = ice.candidate.candidate.split(' ')[4];
resolve(ip);
pc.close();
};
});
}
// 修正3:添加页面加载完成后执行
window.onload = getIpInfo;
</script>

主要修改说明:

  1. 数据结构映射修正

    • 根据您提供的API响应结构,将province改为prov
    • 添加了isp字段的显示(原代码未包含)
  2. 错误处理增强

    • 添加了try-catch块捕获异常
    • 处理了HTTP错误状态码
    • 失败时显示默认值
  3. 执行时机调整

    • 将函数调用放在window.onload中,确保DOM完全加载后再执行
  4. 其他改进

    • 使用现代async/await语法
    • 添加了IP获取的超时处理(通过Promise)
    • 移除了未使用的ua-parser-js相关代码