Python IP地址获取的5种精妙方法与案例解析
📖 文章导读目录
- 为什么要用Python获取IP地址?
- 使用socket库获取本机IP(最基础)
- 通过第三方ipify API获取公网IP(跨平台)
- 利用netifaces库获取多网卡IP(企业级)
- 解析SSL证书IP(进阶安全场景)
- 结合requests+在线API获取地理IP(实用场景)
- 常见问题与解决方案(Q&A)
- 总结与最佳实践建议
为什么要用Python获取IP地址?
在运维监控、网络爬虫、远程设备管理、地理定位服务等场景中,获取准确的IP地址是基础需求,Python因其丰富的标准库和第三方生态,成为实现这一功能的首选语言,但初学者常遇到以下困扰:
- 获取的是127.0.0.1(回环地址)而非真正对外IP
- 多网卡环境下无法准确选择
- 公网IP与内网IP混淆
- 跨平台兼容性问题
本文将通过5个实操案例,从浅入深解决这些痛点。
方法一:使用socket库获取本机IP(最基础)
适用场景: 单网卡、快速获取本机在局域网内的IP地址。
import socket
def get_host_ip():
try:
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect(('8.8.8.8', 80)) # 连接外部服务器但不发送数据
ip = s.getsockname()[0]
s.close()
return ip
except Exception as e:
print(f"Error: {e}")
return None
print(f"本机IP: {get_host_ip()}")
技术要点: 此方法通过创建UDP连接(实际不通信)获取当前网络接口的真实IP,避免了读取hostname可能获取127.0.0.1的问题,但注意:需要联网,且必须能访问8.8.8.8。
方法二:通过第三方ipify API获取公网IP(跨平台)
适用场景: 需要获取本机对外公网IP(例如爬虫代理IP判断)。
import requests
def get_public_ip():
try:
# ipify 是全球可靠的API,无需API Key
resp = requests.get('https://api.ipify.org', timeout=5)
if resp.status_code == 200:
return resp.text.strip()
else:
return f"API返回错误: {resp.status_code}"
except requests.exceptions.RequestException as e:
return f"请求超时/连接错误: {e}"
print(f"公网IP: {get_public_ip()}")
备选API推荐: ipinfo.io/ip(每日免费5万次)、curlmyip.com(轻量级),注意ipify完全免费,适合自动化脚本。
方法三:利用netifaces库获取多网卡IP(企业级)
适用场景: 服务器多网卡(如Docker、VPN、桥接网络),需要区分网络接口。
pip install netifaces
import netifaces
def get_all_ips():
ips = {}
for interface in netifaces.interfaces():
try:
addrs = netifaces.ifaddresses(interface)
if netifaces.AF_INET in addrs:
ips[interface] = addrs[netifaces.AF_INET][0]['addr']
except Exception:
continue
return ips
result = get_all_ips()
for iface, ip in result.items():
print(f"接口 {iface}: {ip}")
注意: 此方法能返回所有接口,但需管理员权限(部分系统),常见输出如wlan0(WiFi)、eth0(有线)、docker0(虚拟网桥)。
方法四:解析SSL证书IP(进阶安全场景)
适用场景: 检测目标网站的服务器IP(绕过CDN真实IP)。
import ssl
import socket
def get_server_ip(hostname):
try:
ctx = ssl.create_default_context()
with ctx.wrap_socket(socket.socket(), server_hostname=hostname) as s:
s.connect((hostname, 443))
cert = s.getpeercert()
# 从subjectAltName提取IP地址
for entry in cert.get('subjectAltName', []):
if entry[0] == 'IP Address':
return entry[1]
return "未直接暴露IP"
except Exception as e:
return f"证书解析失败: {e}"
# 示例:获取百度的某台服务器真实IP
print(f"服务器IP: {get_server_ip('example.com')}")
Warning: 只有部分网站会在证书中包含IP SAN,多数CDN网站会隐藏真实源站IP。
方法五:结合requests+在线API获取地理IP(实用场景)
适用场景: 需要从IP查询地理位置(如用户定位、访问分析)。
import requests
def ip_location(ip):
try:
# ip-api.com 免费版每分钟限制45次
resp = requests.get(f'http://ip-api.com/json/{ip}', timeout=3)
data = resp.json()
if data['status'] == 'success':
return {
'country': data['country'],
'city': data['city'],
'isp': data['isp'],
'lat': data['lat'],
'lon': data['lon']
}
else:
return f"查询失败: {data['message']}"
except Exception as e:
return f"网络异常: {e}"
# 获取本机公网地理位置
my_public_ip = get_public_ip()
location = ip_location(my_public_ip)
print(f"IP {my_public_ip} 地理位置: {location}")
替代API: ipinfo.io(返JSON更丰富,需Token)、geoplugin.net(免费但慢)、api.bigdatacloud.net(隐私友好)。
常见问题与解决方案(Q&A)
Q: 为什么我的socket方法获取到的是172.17.0.x开头的IP?
A: 这是Docker默认的bridge网段,如果运行在容器内,需获取宿主机IP,可尝试读取环境变量或使用hostname -I命令。
Q: 公网IP API有时返回空或500错误怎么办?
A: 设置重试机制,并预留备用API列表(如ipify.org→ipinfo.io→curlmyip.com),示例:
import time
apis = ['https://api.ipify.org', 'https://ipinfo.io/ip', 'https://curlmyip.com']
for api in apis:
try:
resp = requests.get(api, timeout=5)
if resp.status_code == 200:
return resp.text.strip()
except:
time.sleep(1)
return "所有API均超时"
Q: 在Windows/Linux/macOS上脚本表现一致吗?
A: socket和requests方法跨平台一致;netifaces库在Windows需额外安装WinPcap或Npcap驱动支持,建议生产环境使用platform.system()做分支处理。
Q: 可以获取IPv6地址吗?
A: 可以,修改上述代码中socket.AF_INET为socket.AF_INET6,或使用netifaces的AF_INET6,注意多数公网API只返回IPv4。
Q: 如何屏蔽代理和VPN后的真实IP?
A: 无法从本机脚本完全屏蔽,因为代理最终会修改出站IP,若要原样获取,需使用STUN协议(如pystun3库)向STUN服务器查询NAT映射后的实际IP。
总结与最佳实践建议
| 方法 | 适用场景 | 优点 | 缺点 |
|---|---|---|---|
| socket | 开发环境,快速获取内网IP | 无需第三方库 | 需联网有发往其他设备的数据包 |
| ipify API | 获取公网IP | 免费稳定跨平台 | 对网络依赖性高 |
| netifaces | 多网卡服务器 | 全面识别网络接口 | 需安装二进制依赖 |
| SSL证书 | 安全审计 | 绕过CDN | 依赖站点配置 |
| IP定位API | 地理分析 | 完整地理信息 | 有调用频率限制 |
最终推荐:
- 普通开发者:
socket + ipify组合 - 运维工程师:
netifaces + requests轮询 - 安全工程师:
SSL证书解析 + STUN
延伸阅读建议: 进一步了解Python的ipaddress库(IP地址计算、子网检测)、whois查询(IP归属运营商)。
本文代码经Python 3.10+测试,兼容Linux/Windows/macOS不同发行版,更多实战案例请关注作者后续更新。
标签: 实操方法