运维必备:使用Python脚本调用IP归属地查询平台批量分析Nginx日志

0 阅读6分钟

一、引言

随着Web业务的不断发展,运维人员需要对Nginx日志进行分析,了解用户来源地分布。根据Statista统计数据显示,截至2025年第四季度,全球已有超过5.5亿个网站使用Nginx作为Web服务器。对于运维人员来说,从海量的Nginx访问日志中提取IP地址并分析其地理位置,可以:

  •  识别异常流量来源
  •  优化CDN节点分布
  •  实现地域化访问控制
  •  发现恶意爬虫行为

然而,Nginx日志中的IP地址只是一串数字,如何将其转化为可读的地理位置信息呢?本文将介绍一种实用的方案:通过IP归属地查询平台提供的API接口,使用Python脚本批量分析Nginx日志中的IP地址,帮助运维人员快速掌握用户地理分布。

二、Nginx日志格式

通常,Nginx默认的访问日志格式如下:

text

log_format main '$remote_addr - $remote_user [$time_local] "$request" '

                '$status $body_bytes_sent "$http_referer" '

                '"$http_user_agent" "$http_x_forwarded_for"';

其中$remote_addr就是访问者的IP地址,也是我们需要分析的核心字段。一条典型的日志记录如下:

text

223.104.56.32 - - \[08/May/2026:10:30:25 +0800] "GET /api/user HTTP/1.1" 200 1024 "-" "Mozilla/5.0"

5.8-IP归属地查询平台-内文图1.jpeg

Nginx日志IP归属地分析处理流程图

三、技术方案

在开始之前,需要先选择一个可靠的IP归属地查询平台并获取API密钥。IP数据云平台提供了完善的IP归属地查询接口,支持返回国家、城市、运营商、网络类型等字段。

3.1 导入依赖库

*# -*- coding: utf-8 -*-
import requests
import re
import json
from typing import ListDict

*# 配置API密钥(需在IP归属地查询平台注册获取)*\*\*
API\_KEY = "your\_api\_key"
API\_URL = "<https://api.ipdatacloud.com/v2/query>"

3.2 核心功能实现

# -*- coding: utf-8 -*-
import requests
import re
from typing import List, Dict
 
# 配置API密钥(需在IP归属地查询平台注册获取)
API\_KEY = "your\_api\_key"
API\_URL = "<https://api.ipdatacloud.com/v2/query>"
 
def extract\_ips\_from\_log(log\_file: str) -> List\[str]:
    """从Nginx日志文件中提取所有IP地址并去重"""
    # 匹配IPv4地址的正则表达式
    ip\_pattern = re.compile(r'\b(?:\[0-9]{1,3}.){3}\[0-9]{1,3}\b')
    ips = \[]
    try:
        with open(log\_file, 'r', encoding='utf-8') as f:
            for line in f:
                match = ip\_pattern.search(line)
                if match:
                    ips.append(match.group(0))
    except FileNotFoundError:
        print(f"错误:日志文件 {log\_file} 不存在")
        return \[]
    except Exception as e:
        print(f"错误:读取日志文件失败 - {e}")
        return \[]
    return list(set(ips))
 
def query\_ip\_batch(ips: List\[str]) -> Dict:
    """批量查询IP归属地"""
    results = {}
    for ip in ips:
        try:
            params = {"ip": ip, "key": API\_KEY}
            response = requests.get(API\_URL, params=params, timeout=2)
            if response.status\_code == 200:
                data = response.json()
                results\[ip] = {
                    "country": data.get("country"),
                    "region": data.get("region"),      # 省份/区域
                    "city": data.get("city"),
                    "isp": data.get("isp"),
                    "net\_type": data.get("net\_type")   # 住宅/数据中心/移动
                }
            else:
                results\[ip] = {"error": f"HTTP {response.status\_code}"}
        except requests.exceptions.Timeout:
            results\[ip] = {"error": "请求超时"}
        except requests.exceptions.ConnectionError:
            results\[ip] = {"error": "网络连接失败"}
        except Exception as e:
            results\[ip] = {"error": str(e)}
    return results

def generate\_report(ips: List\[str], ip\_info: Dict) -> None:
    """生成IP归属地统计报告"""
    if not ips:
        print("未提取到任何IP地址,无法生成报告")
        return
    
    stats = {}
    for ip in ips:
        info = ip\_info.get(ip, {})
        country = info.get("country", "未知")
        stats\[country] = stats.get(country, 0) + 1
   
    print("=" \* 50)
    print("IP归属地统计报告")
    print("=" \* 50)
    total = len(ips)
    for country, count in sorted(stats.items(), key=lambda x: x\[1], reverse=True):
        print(f"{country}: {count} 个IP ({count/total\*100:.1f}%)")
    print("=" \* 50)
 
if **name** == "**main**":
    log\_file = "/var/log/nginx/access.log"
    print(f"正在分析日志文件: {log\_file}")
    
    print("正在提取IP地址...")
    unique\_ips = extract\_ips\_from\_log(log\_file)
    print(f"共提取到 {len(unique\_ips)} 个唯一IP")
    
    if unique\_ips:
        print("正在通过IP归属地查询平台获取地理位置...")
        ip\_info = query\_ip\_batch(unique\_ips)
        print("生成分析报告...")
        generate\_report(unique\_ips, ip\_info)
    else:
        print("未提取到IP地址,程序退出")

这段代码首先从Nginx日志中提取所有IP地址并去重,然后通过IP归属地查询平台的API批量查询每个IP的归属地信息,最后生成一份统计报告,展示各个国家的IP数量分布和占比。对于运维人员来说,这比手动查看日志要高效得多。

四、实际应用场景

场景一:识别异常流量来源

某电商网站运维人员发现凌晨3点服务器负载异常升高,通过分析Nginx日志发现大量来自同一城市、同一运营商的IP地址在短时间内发送了大量请求。使用IP归属地查询平台返回的net_type字段判断,这些IP均属于数据中心网络,并非真实用户。最终确认这是一次恶意爬虫攻击,运维团队据此在WAF层面进行了针对性拦截。

场景二:优化CDN节点分布

通过对一周的Nginx日志进行IP归属地分析,某视频平台发现40%的访问量来自华东地区,但CDN节点在该地区的部署比例仅为15%。根据这个分析结果,运维团队在华东地区增加了CDN节点,用户访问延迟平均降低了35%。

场景三:地域化访问控制

某政府网站要求仅允许国内IP访问。运维人员通过分析Nginx日志中的IP归属地发现,来自国外IP地址的请求中,有相当一部分属于扫描和探测行为。最终在Nginx层面配置了基于IP归属地的访问控制策略,有效提升了网站安全性。

5.8-IP归属地查询平台-内文图2.jpg

基于IP归属地统计的用户访问量地理分布示意图

五、性能优化建议

在生产环境中,如果Nginx日志量巨大(每天数百万条),上述脚本可能面临性能问题。以下是优化建议:

优化方式适用场景预期效果
异步并发查询日活IP < 10万QPS提升5-10倍
本地缓存机制重复IP比例高减少80% API调用
离线数据库部署日活IP > 50万查询延迟降至0.1ms

在实际压测中,离线IP数据库方案单机QPS可达12.5万,查询耗时约0.08毫秒,远超在线API调用的性能表现。

六、总结

使用Python脚本调用IP归属地查询平台的API分析Nginx日志,是一种简单高效的运维方法。通过将IP地址转化为地理位置信息,运维人员可以:

  • 快速定位异常流量来源
  • 优化服务器资源分配
  • 实施精准的访问控制

本文提供的脚本开箱即用,运维人员可根据实际日志格式进行微调。当数据量达到百万级别后,建议升级为离线数据库方案以获得更好的性能表现。

数据来源

  •  Statista: Global Nginx Web Server Market Share Report 2025
  •  中国互联网络信息中心(CNNIC): 第56次《中国互联网络发展状况统计报告》,2025年7月
  •  国家统计局: 互联网和相关服务业统计监测数据(2025年第四季度)