Skip to content

Python批量查询IP归属地,几千个IP也能快速跑完

做数据分析的朋友常会遇到这种需求:手里有一批IP,可能是访问日志里的,可能是订单里的,想知道它们分别来自哪个省哪个市。一个一个查太蠢,写个批量脚本才是正经事。

这篇文章分享一个我用IP9做的批量查询脚本,重点讲三件事:怎么查得快、怎么不被打爆限流、结果怎么整理

基础版:一条龙查完

先来个能跑的最小版本:

python
import requests

def query_ip(ip: str) -> dict:
    url = f"https://ip9.com.cn/get?ip={ip}"
    try:
        r = requests.get(url, timeout=3)
        data = r.json()
        if data.get("ret") == 200:
            return data["data"]
    except Exception:
        pass
    return {}

ips = ["58.30.0.0", "114.114.114.114", "8.8.8.8", "240e:3a1::1234"]
for ip in ips:
    info = query_ip(ip)
    print(ip, "->", info.get("country"), info.get("prov"), info.get("city"))

关键:加缓存,去重

批量场景下最大的坑就是重复查询。日志里同一个IP可能出现几百上千次,不缓存的话全是无效请求,还容易触发限流。

functools.lru_cache 一键搞定:

python
from functools import lru_cache

@lru_cache(maxsize=100000)
def query_ip(ip: str) -> dict:
    ...  # 同上

这样同一个IP只会真正查询一次,剩下的直接命中缓存,速度提升几十倍。

再进一步:并发 + 限速

几千个IP,如果全是不同IP,串行跑会慢。可以开线程池,但要控制速率,别把免费接口薅到限流。

IP9 免费版是每IP每分钟60次,我们批量查的是不同IP,压力不大,但稳妥起见还是加个整体限速:

python
import requests
from concurrent.futures import ThreadPoolExecutor
from functools import lru_cache
import time

@lru_cache(maxsize=100000)
def query_ip(ip: str) -> dict:
    url = f"https://ip9.com.cn/get?ip={ip}"
    for _ in range(3):          # 失败重试3次
        try:
            r = requests.get(url, timeout=3)
            data = r.json()
            if data.get("ret") == 200:
                return data["data"]
        except Exception:
            time.sleep(0.5)
    return {}

def run(ips: list[str]) -> list[dict]:
    with ThreadPoolExecutor(max_workers=8) as pool:
        return list(pool.map(query_ip, ips))

max_workers=8 对免费接口来说足够了,别贪多。

结果导出成表格

查完的数据建议直接导成 CSV,方便后续用 Excel 或 BI 工具分析:

python
import csv

results = run(all_ips)
with open("ip_result.csv", "w", newline="", encoding="utf-8-sig") as f:
    writer = csv.DictWriter(f, fieldnames=["ip", "country", "prov", "city", "isp", "big_area"])
    writer.writeheader()
    for info in results:
        if info:
            writer.writerow(info)

注意编码用 utf-8-sig,不然 Excel 打开中文会乱码——这是我踩过的坑,写出来免得大家再踩一次。

几点经验

  • 先清洗再去重:批量前先把IP列表去重,能省一大半请求。
  • 失败要容忍:网络抖动很正常,单个失败别让整个脚本挂掉,记下来最后补查。
  • 统计维度用好 big_area:IP9返回里有 big_area(华北、华南这种大区),做区域统计直接按它分组,比拿着城市名再归类省事。

数据到手之后,画个分布图、做个地域报表,就是下一篇的事了。先把这个脚本跑起来吧,接口文档在 https://www.ip9.com.cn