Heim >Computer-Tutorials >Computerwissen >So fragen Sie den IP-Standort von Douyin ab (wie Sie den IP-Standort von Douyin anzeigen)

So fragen Sie den IP-Standort von Douyin ab (wie Sie den IP-Standort von Douyin anzeigen)

PHPz
PHPznach vorne
2024-02-15 14:42:061486Durchsuche

So fragen Sie den IP-Standort von Douyin ab (wie Sie den IP-Standort von Douyin anzeigen)

1. Hintergrund

Der Herausgeber von PHP, Xiaoxin, zeigt Ihnen, wie Sie den IP-Standort von Douyin abfragen. Bei der Nutzung der Douyin APP möchten wir oft wissen, wo die IP-Adresse eines bestimmten Benutzers hingehört. Durch die Abfrage des IP-Standorts können wir die ungefähren Standortinformationen des Benutzers erfahren. Wie kann man also den IP-Standort von Douyin überprüfen? Als nächstes geben wir Ihnen detaillierte Antworten.

Als nächstes konzentrieren wir uns darauf, wie das Java-Backend die IP-Zuordnungsfunktion implementiert. Tatsächlich sind nur die folgenden zwei Schritte erforderlich:

2. Besorgen Sie sich die Client-IP-Schnittstelle.

Jeder, der Webentwicklung durchgeführt hat, wird verstehen, ob dies der Fall ist Ob auf Mobilgeräten oder PCs: Die Anforderungsschnittstelle wird in ein HttpServletRequest-Objekt gekapselt. Dieses Objekt enthält verschiedene vom Client angeforderte Informationen, wie z. B. Anforderungsadresse, Parameter, übermittelte Daten usw.

Wenn der Server die IP direkt offenlegt, kann request.getRemoteAddr() die Client-IP abrufen.

In der derzeit gängigen Architektur legen die meisten Server ihre IP-Adressen nicht direkt offen, sondern verarbeiten Anfragen über eine oder mehrere Schichten von Reverse-Proxys. Ein gängiges Reverse-Proxy-Tool ist Nginx. Durch die Einführung eines Proxys gibt es eine zusätzliche Schicht zwischen dem Server und dem Client, sodass die mit der Methode request.getRemoteAddr() erhaltene IP-Adresse die IP-Adresse des Proxyservers und nicht die IP-Adresse des Clients ist. Um die IP-Adresse des ursprünglichen Clients zu verfolgen, werden normalerweise Informationen wie „X-Forwarded-For“ zum Weiterleitungsheader hinzugefügt. Mithilfe dieser Informationen kann die wahre Quelle der Anfrage ermittelt werden.

X-Forwarded-For ist ein von Squid entwickeltes Feld und wird nur hinzugefügt, wenn es über einen HTTP-Proxy oder Lastausgleichsserver geleitet wird. Sein Format ist X-Forwarded-For:client1,proxy1,proxy2. Normalerweise ist die erste IP-Adresse die echte IP des Clients und die nachfolgenden IP-Adressen sind die IPs der durchgereichten Proxyserver. Gemäß den obigen Codekommentaren kann die erste IP-Adresse direkt abgefangen werden. Proxy-Client-IP/WL-Proxy-Client-IP ist ein Header, der nur vorhanden ist, wenn er vom Apache HTTP-Server angefordert wird. Bei Verwendung von Apache HTTP als Proxy wird normalerweise der Anforderungsheader Proxy-Client-IP hinzugefügt, und WL-Proxy-Client-IP ist ein Header, der vom WebLogic-Plug-in hinzugefügt wird. In diesem Fall können die Header-Informationen auch direkt bezogen werden. HTTP_CLIENT_IP ist ein Anforderungsheader, den einige Proxyserver möglicherweise hinzufügen. X-Real-IP ist ein Anforderungsheader, der normalerweise von Nginx verwendet wird.

In der täglichen Entwicklung ist nicht klar angegeben, welche Header-Informationen zum Verfolgen des Clients verwendet werden sollen. Sie müssen es einzeln versuchen, bis Sie es erhalten. Das Folgende ist der entsprechende Code:

ini

Code kopieren

@Slf4jpublic class IpUtils { private static final String UNKNOWN_VALUE = „unknown“; private static final String LOCALHOST_V4 = „127.0.0.1“; private static final String LOCALHOST_V6 = „ 0:0:0:0:0:0:0:1“; privater statischer finaler String -Client-IP“; privater statischer finaler String WL_PROXY_CLIENT_IP = „WL-Proxy-Client-IP“; privater statischer finaler String HTTP_CLIENT_IP = „HTTP_CLIENT_IP“; privater statischer finaler String IP_DATA_PATH = „/Users/shepherdmy /Desktop/ip2region.xdb“; privates statisches Byte[] contentBuff;
/*** Holen Sie sich die Client-IP-Adresse * @param request * @return*/ public static String getRemoteHost(HttpServletRequest request) { String ip = request. getHeader(X_FORWARDED_FOR); if ( StringUtils.isNotEmpty(ip) && !UNKNOWN_VALUE.equalsIgnoreCase(ip)) { // Nach mehreren Reverse-Proxys gibt es mehrere IP-Werte und die erste IP ist die echte IP int index = ip.indexOf(“,”) ; if (index != -1) { return ip.substring(0, index);
} else { return ip; } }ip = request.getHeader( X_REAL_IP); if (StringUtils.isNotEmpty (ip) && !UNKNOWN_VALUE.equalsIgnoreCase(ip)) { return ip; } if (StringUtils.isBlank(ip) ||UNKNOWN_VALUE.equalsIgnoreCase(ip)) {ip = request.getHeader(PROXY_CLIENT_IP)
; } if (StringUtils.isBlank(ip) ||UNKNOWN_VALUE.equalsIgnoreCase(ip)) {ip = request.getHeader(WL_PROXY_CLIENT_IP)
; } if (StringUtils.isBlank(ip) ||UNKNOWN_VALUE.equalsIgnoreCase(ip)) {ip = request.getRemoteAddr()
;} if (StringUtils.isBlank(ip) ||UNKNOWN_VALUE.equalsIgnoreCase(ip)) {ip = request.getHeader(HTTP_CLIENT_IP)
; } if (StringUtils.isBlank(ip ) ||UNKNOWN_VALUE.equalsIgnoreCase(ip)) {ip = request.getRemoteAddr()
; } return ip.equals(LOCALHOST_V6) ? LOCALHOST_V4 : ip;
} }

项目推荐:基于SpringBoot2.x、SpringCloud和SpringCloudAlibaba企业级系统架构底层框架封装,解决业务开发时常见的非功能性需求,防止重复造轮子,方便业务快速开发和企业技术栈框架统一管理。引入组件化的思想实现高内聚低耦合并且高度可配置化,做到可插拔。严格控制包依赖和统一版本管理,做到最少化依赖。注重代码规范和注释,非常适合个人学习和企业使用

Github地址:github.com/plasticene/…

Gitee地址:gitee.com/plasticene3…

微信公众号:Shepherd进阶笔记

交流探讨群:Shepherd_126

3.获取ip归属地

通过上面我们就能获取到客户端用户的ip地址,接下来就可以通过ip解析获取归属地了。

如果我们在网上搜索资料教程,大部分都是说基于各大平台(eg:淘宝,新浪)提供的ip库进行查询,不过不难发现这些平台已经不怎么维护这个功能,现在处于“半死不活”的状态,根本不靠谱,当然有些平台提供可靠的获取ip属地接口,但是收费、收费、收费。

本着作为一个程序员的严谨:“能白嫖的就白嫖,避免出现要买的是你,不会用也是你的尴尬遭遇”。扯远了言归正传,为了寻求可靠有效的解决方案,只能去看看github有没有什么项目能满足需求,果然功夫不负有心人,发现一个宝藏级项目:ip2region,一个准确率 99.9% 的离线 IP 地址定位库,0.0x 毫秒级查询,ip2region.db 数据库只有数 MB的项目,提供了众多主流编程语言的 xdb 数据生成和查询客户端实现,这里只能说:开源真香,开源万岁。

3.1 Ip2region 特性

标准化的数据格式

每个 ip 数据段的 region 信息都固定了格式:国家|区域|省份|城市|ISP,只有中国的数据绝大部分精确到了城市,其他国家部分数据只能定位到国家,其余选项全部是0。

数据去重和压缩

xdb 格式生成程序会自动去重和压缩部分数据,默认的全部 IP 数据,生成的 ip2region.xdb 数据库是 11MiB,随着数据的详细度增加数据库的大小也慢慢增大。

极速查询响应

即使是完全基于 xdb 文件的查询,单次查询响应时间在十微秒级别,可通过如下两种方式开启内存加速查询:

vIndex 索引缓存 :使用固定的 512KiB 的内存空间缓存 vector index 数据,减少一次 IO 磁盘操作,保持平均查询效率稳定在10-20微秒之间。xdb 整个文件缓存:将整个 xdb 文件全部加载到内存,内存占用等同于 xdb 文件大小,无磁盘 IO 操作,保持微秒级别的查询效率。

IP 数据管理框架

v2.0 格式的 xdb 支持亿级别的 IP 数据段行数,region 信息也可以完全自定义,例如:你可以在 region 中追加特定业务需求的数据,例如:GPS信息/国际统一地域信息编码/邮编等。也就是你完全可以使用 ip2region 来管理你自己的 IP 定位数据。

99.9% 准确率

数据聚合了一些知名 ip 到地名查询提供商的数据,这些是他们官方的的准确率,经测试着实比经典的纯真 IP 定位准确一些。

ip2region 的数据聚合自以下服务商的开放 API 或者数据(升级程序每秒请求次数 2 到 4 次):

01,>80%,淘宝IP地址库,ip.taobao.com/%5C02,≈10%,GeoIP,geoip.com/%5C03,≈2%,纯真 IP 库,www.cz88.net/%5C

备注:如果上述开放 API 或者数据都不给开放数据时 ip2region 将停止数据的更新服务。

3.2 整合Ip2region客户端进行查询

提供了众多主流编程语言的 xdb 数据生成和查询客户端实现,已经集成的客户端有:java、C#、php、c、python、nodejs、php扩展(php5 和 php7)、golang、rust、lua、lua_c,nginx。这里讲一下java的客户端。

首先我们需要引入依赖:

xml

复制代码

org.lionsoulip2region2.6.5

接下来我们需要先去下载数据文件ip2region.xdb到本地,然后基于数据文件进行查询,下面查询方法文件路径改为你本地路径即可,ip2region提供三种查询方式:

完全基于文件的查询

java

复制代码

import
org.lionsoul.ip2region.xdb.Searcher;import java.io.*;import
java.util.concurrent.TimeUnit;publicclassSearcherTest {publicstaticvoidmain(String[] args) {// 1、创建 searcher 对象StringdbPath=”ip2region.xdb file path”;Searchersearcher=null;try { searcher = Searcher.newWithFileOnly(dbPath); } catch (IOException e) { System.out.printf(“failed to create searcher with `%s`: %s\\n”, dbPath, e);return; }// 2、查询try {Stringip=”1.2.3.4″;longsTime= System.nanoTime();Stringregion= searcher.search(ip);longcost=
TimeUnit.NANOSECONDS.toMicros((long) (System.nanoTime() – sTime)); System.out.printf(“{region: %s, ioCount: %d, took: %d μs}\\n”, region, searcher.getIOCount(), cost); } catch (Exception e) { System.out.printf(“failed to search(%s): %s\\n”, ip, e); }// 3、关闭资源 searcher.close();// 备注:并发使用,每个线程需要创建一个独立的 searcher 对象单独使用。 }}

缓存 VectorIndex 索引

我们可以提前从 xdb 文件中加载出来 VectorIndex 数据,然后全局缓存,每次创建 Searcher 对象的时候使用全局的 VectorIndex 缓存可以减少一次固定的 IO 操作,从而加速查询,减少 IO 压力。

java

复制代码

import
org.lionsoul.ip2region.xdb.Searcher;import java.io.*;import
java.util.concurrent.TimeUnit;publicclassSearcherTest {publicstaticvoidmain(String[] args) {StringdbPath=”ip2region.xdb file path”;// 1、从 dbPath 中预先加载 VectorIndex 缓存,并且把这个得到的数据作为全局变量,后续反复使用。byte[] vIndex;try { vIndex =
Searcher.loadVectorIndexFromFile(dbPath); } catch (Exception e) { System.out.printf(“failed to load vector index from `%s`: %s\\n”, dbPath, e);return; }// 2、使用全局的 vIndex 创建带 VectorIndex 缓存的查询对象。 Searcher searcher;try { searcher =
Searcher.newWithVectorIndex(dbPath, vIndex); } catch (Exception e) { System.out.printf(“failed to create vectorIndex cached searcher with `%s`: %s\\n”, dbPath, e);return; }// 3、查询try {Stringip=”1.2.3.4″;longsTime= System.nanoTime();Stringregion= searcher.search(ip);longcost=
TimeUnit.NANOSECONDS.toMicros((long) (System.nanoTime() – sTime)); System.out.printf(“{region: %s, ioCount: %d, took: %d μs}\\n”, region, searcher.getIOCount(), cost); } catch (Exception e) { System.out.printf(“failed to search(%s): %s\\n”, ip, e); }// 4、关闭资源 searcher.close();// 备注:每个线程需要单独创建一个独立的 Searcher 对象,但是都共享全局的制度 vIndex 缓存。 }}

缓存整个 xdb 数据

我们也可以预先加载整个 ip2region.xdb 的数据到内存,然后基于这个数据创建查询对象来实现完全基于文件的查询,类似之前的 memory search。

java

复制代码

import
org.lionsoul.ip2region.xdb.Searcher;import java.io.*;import
java.util.concurrent.TimeUnit;publicclassSearcherTest {publicstaticvoidmain(String[] args) {StringdbPath=”ip2region.xdb file path”;// 1、从 dbPath 加载整个 xdb 到内存。byte[] cBuff;try { cBuff =
Searcher.loadContentFromFile(dbPath); } catch (Exception e) { System.out.printf(“failed to load content from `%s`: %s\\n”, dbPath, e);return; }// 2、使用上述的 cBuff 创建一个完全基于内存的查询对象。 Searcher searcher;try { searcher = Searcher.newWithBuffer(cBuff); } catch (Exception e) { System.out.printf(“failed to create content cached searcher: %s\\n”, e);return; }// 3、查询try {Stringip=”1.2.3.4″;longsTime= System.nanoTime();Stringregion= searcher.search(ip);longcost=
TimeUnit.NANOSECONDS.toMicros((long) (System.nanoTime() – sTime)); System.out.printf(“{region: %s, ioCount: %d, took: %d μs}\\n”, region, searcher.getIOCount(), cost); } catch (Exception e) { System.out.printf(“failed to search(%s): %s\\n”, ip, e); }// 4、关闭资源 – 该 searcher 对象可以安全用于并发,等整个服务关闭的时候再关闭 searcher// searcher.close();// 备注:并发使用,用整个 xdb 数据缓存创建的查询对象可以安全的用于并发,也就是你可以把这个 searcher 对象做成全局对象去跨线程访问。 }}

3.3 springboot整合示例

首先我们也需要像上面一样引入maven依赖。然后就可以基于上面的查询方式进行封装成工具类了,我这里选择了上面的第三种方式:缓存整个 xdb 数据

ini

复制代码

@Slf4jpublic class IpUtils { private static final String IP_DATA_PATH = “
/Users/shepherdmy/Desktop/ip2region.xdb“; private static byte[] contentBuff; static { try { // 从 dbPath 加载整个 xdb 到内存。contentBuff =
Searcher.loadContentFromFile(IP_DATA_PATH); } Catch (IOException e) { e.printStackTrace(); } } /*** Fragen Sie den Standort anhand der IP ab, festes Format: China|0|Provinz Zhejiang|Stadt Hangzhou|Telekom * @param ip * @return*/ public static IpRegion getIpRegion(String ip) { Searcher searcher = null; IpRegion ipRegion = new IpRegion(); try {searcher = Searcher.newWithBuffer(contentBuff); String region = searcher.search(ip); String[]info = StringUtils.split(region, „|“); ipRegion.setCountry(info[0]); ipRegion.setArea(info[1]); ipRegion.setProvince(info[2]); ipRegion.setCity(info[3 ])? ) { try { searcher.close(); } Catch (IOException e) { log.error(“close searcher error:“, e); } } } return ipRegion; }}

Das obige ist der detaillierte Inhalt vonSo fragen Sie den IP-Standort von Douyin ab (wie Sie den IP-Standort von Douyin anzeigen). Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:jingfakeji.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen