使用 Python 获取计算机的外部 IP 地址

寻找一个更好的方法来获得一台机器当前的外部 IP # ... 下面的工作,但宁愿不依赖外部网站收集信息... 我被限制使用与 Mac OS X 10.5捆绑的标准 Python 2.5.1库。X

import os
import urllib2


def check_in():


fqn = os.uname()[1]
ext_ip = urllib2.urlopen('http://whatismyip.org').read()
print ("Asset: %s " % fqn, "Checking in from IP#: %s " % ext_ip)
181746 次浏览

如果机器是一个防火墙,那么您的解决方案是一个非常明智的选择: 替代方案是能够查询防火墙,结果是非常依赖于防火墙的类型(如果有可能的话)。

如果你的路由器获得外部 IP,恐怕你没有其他选择,只能使用外部服务,像你这样做。如果路由器本身有一些查询接口,您可以使用它,但解决方案将是非常特定于环境和不可靠的。

如果您认为外部资源太不可靠,您可以合并一些不同的服务。对于大多数 ip 查找页面,他们要求你抓取 html,但是他们中的一些已经创建了像你的脚本精简页面-也因此他们可以减少点击他们的网站:

ipWebCode = urllib.request.urlopen("http://ip.nefsc.noaa.gov").read().decode("utf8")
ipWebCode=ipWebCode.split("color=red> ")
ipWebCode = ipWebCode[1]
ipWebCode = ipWebCode.split("</font>")
externalIp = ipWebCode[0]

这是我为另一个程序编写的一小段代码。诀窍是找到一个足够简单的网站,以便解剖 HTML 不是一个痛苦。

我在这里尝试了大多数关于这个问题的其他答案,发现除了一个之外,大多数使用的服务都已经停用了。

下面是一个脚本,它应该可以做到这一点,并且只下载最少量的信息:

#!/usr/bin/env python


import urllib
import re


def get_external_ip():
site = urllib.urlopen("http://checkip.dyndns.org/").read()
grab = re.findall('([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)', site)
address = grab[0]
return address


if __name__ == '__main__':
print( get_external_ip() )

这是另一个备选剧本。

def track_ip():
"""
Returns Dict with the following keys:
- ip
- latlong
- country
- city
- user-agent
"""


conn = httplib.HTTPConnection("www.trackip.net")
conn.request("GET", "/ip?json")
resp = conn.getresponse()
print resp.status, resp.reason


if resp.status == 200:
ip = json.loads(resp.read())
else:
print 'Connection Error: %s' % resp.reason


conn.close()
return ip

编辑: 不要忘记导入 httplib 和 json

In [1]: import stun


stun.get_ip_info()
('Restric NAT', 'xx.xx.xx.xx', 55320)

如果您只是为自己而不是为通用应用程序编写,那么您可能能够在路由器的设置页面上找到地址,然后从该页面的 html 中获取它。这对我的 SMC 路由器工作得很好。一次阅读和一次简单的 RE 搜索,我就找到了。

我对这样做特别感兴趣的是,当我不在家的时候,让我知道我家的 IP 地址,这样我就可以通过 VNC 进入。Python 的另外几行代码将地址存储在 Dropbox 中,以便外部访问,如果发现变化,甚至会给我发电子邮件。我已经安排好在启动时发生,之后每小时发生一次。

我能想到的最简单(非 python)的工作解决方案是

wget -q -O- icanhazip.com

我想添加一个非常简短的 Python 3解决方案,它利用了 http://hostip.info的 JSON API。

from urllib.request import urlopen
import json
url = 'http://api.hostip.info/get_json.php'
info = json.loads(urlopen(url).read().decode('utf-8'))
print(info['ip'])

当然,您可以添加一些错误检查、超时条件和一些便利条件:

#!/usr/bin/env python3
from urllib.request import urlopen
from urllib.error import URLError
import json


try:
url = 'http://api.hostip.info/get_json.php'
info = json.loads(urlopen(url, timeout = 15).read().decode('utf-8'))
print(info['ip'])
except URLError as e:
print(e.reason, end=' ') # e.g. 'timed out'
print('(are you connected to the internet?)')
except KeyboardInterrupt:
pass

在我看来,最简单的解决办法是

import requests
f = requests.request('GET', 'http://myip.dnsomatic.com')
ip = f.text

仅此而已。

使用这个脚本:

import urllib, json


data = json.loads(urllib.urlopen("http://ip.jsontest.com/").read())
print data["ip"]

没有 json:

import urllib, re


data = re.search('"([0-9.]*)"', urllib.urlopen("http://ip.jsontest.com/").read()).group(1)
print data

我喜欢 http://ipify.org,他们甚至提供了使用 API 的 Python 代码。

# This example requires the requests library be installed.  You can learn more
# about the Requests library here: http://docs.python-requests.org/en/latest/
from requests import get


ip = get('https://api.ipify.org').content.decode('utf8')
print('My public IP address is: {}'.format(ip))

您应该使用 UPnP 协议来查询您的路由器以获得此信息。最重要的是,这并不依赖于外部服务,对于这个问题的所有其他答案似乎都表明了这一点。

有一个名为 miniupnp 的 Python 库可以做到这一点,参见 Miniupnpc/testupnPigd.py

pip install miniupnpc

根据他们的例子,你应该能够做到这样的事情:

import miniupnpc


u = miniupnpc.UPnP()
u.discoverdelay = 200
u.discover()
u.selectigd()
print('external ip address: {}'.format(u.externalipaddress()))

Python 3,只使用标准库

如前所述,可以使用像 认出我这样的外部服务来发现您的路由器的外部 IP 地址。

下面是如何使用 python3,只使用 标准图书馆:

import urllib.request


external_ip = urllib.request.urlopen('https://ident.me').read().decode('utf8')


print(external_ip)

根据可用性和客户端首选项,可以返回 IPv4和 IPv6地址; 仅对 IPv4使用 https://v4.ident.me/,或者仅对 IPv6使用 https://v6.ident.me/

import requests
import re




def getMyExtIp():
try:
res = requests.get("http://whatismyip.org")
myIp = re.compile('(\d{1,3}\.){3}\d{1,3}').search(res.text).group()
if myIp != "":
return myIp
except:
pass
return "n/a"

使用 Python 2.7.6和2.7.13

import urllib2
req = urllib2.Request('http://icanhazip.com', data=None)
response = urllib2.urlopen(req, timeout=5)
print(response.read())

还有一些其他的方法,不依赖于 Python 检查外部网站,但是操作系统可以。这里的主要问题是,即使您没有使用 Python,如果您使用的是命令行,也没有“内置”命令可以简单地告诉您外部(WAN) IP。诸如“ IP addr show”和“ ifconfig-a”之类的命令显示服务器在网络中的 IP 地址。只有路由器实际上拥有外部 IP。但是,有一些方法可以从命令行查找外部 IP 地址(WAN IP)。

这些例子是:

http://ipecho.net/plain ; echo
curl ipinfo.io/ip
dig +short myip.opendns.com @resolver1.opendns.com
dig TXT +short o-o.myaddr.l.google.com @ns1.google.com

因此,python 代码应该是:

import os
ip = os.popen('wget -qO- http://ipecho.net/plain ; echo').readlines(-1)[0].strip()
print ip

或者

import os
iN, out, err = os.popen3('curl ipinfo.io/ip')
iN.close() ; err.close()
ip = out.read().strip()
print ip

或者

import os
ip = os.popen('dig +short myip.opendns.com @resolver1.opendns.com').readlines(-1)[0].strip()
print ip

或者,将上面的任何其他示例插入到 os.popen、 os.popen2、 os.popen3或 os.system 等命令中。

另外,您可以使用“ pip3 install pytis”并使用/看一下用 Python 编写的“ getip”程序。 你也可以在这里找到它的代码: < a href = “ https://github.com/PyTis/PyTis/blob/development/src/pytis/getip.py”rel = “ nofollow norefrer”> https://github.com/pytis/pytis/blob/development/src/pytis/getip.py

如果你不想使用外部服务(IP 网站等) ,你可以使用 UPnP 协议

为此,我们使用一个简单的 UPnP 客户端库(https://github.com/flyte/upnpclient)

安装 :

安装 upnpclient

简单代码 :

import upnpclient


devices = upnpclient.discover()


if(len(devices) > 0):
externalIP = devices[0].WANIPConn1.GetExternalIPAddress()
print(externalIP)
else:
print('No Connected network interface detected')

Full Code (获取 github 自述文件中提到的更多信息)

In [1]: import upnpclient


In [2]: devices = upnpclient.discover()


In [3]: devices
Out[3]:
[<Device 'OpenWRT router'>,
<Device 'Harmony Hub'>,
<Device 'walternate: root'>]


In [4]: d = devices[0]


In [5]: d.WANIPConn1.GetStatusInfo()
Out[5]:
{'NewConnectionStatus': 'Connected',
'NewLastConnectionError': 'ERROR_NONE',
'NewUptime': 14851479}


In [6]: d.WANIPConn1.GetNATRSIPStatus()
Out[6]: {'NewNATEnabled': True, 'NewRSIPAvailable': False}


In [7]: d.WANIPConn1.GetExternalIPAddress()
Out[7]: {'NewExternalIPAddress': '123.123.123.123'}

使用 请求模块:

import requests


myip = requests.get('https://www.wikipedia.org').headers['X-Client-IP']


print("\n[+] Public IP: "+myip)

就像在 Python 3中运行这个程序一样简单:

import os


externalIP  = os.popen('curl -s ifconfig.me').readline()
print(externalIP)

Linux 专用解决方案。

在 Linux 系统上,您可以使用 Python 在 shell 上执行命令。

类似这样的东西,(假设“ dig/Drill”在操作系统上工作)

import os
command = "dig TXT +short o-o.myaddr.l.google.com @ns1.google.com | awk -F\'\"\' '{print $2}' "
ip = os.system(command)

Arch 用户请将“ dig”替换为“ drill”。

我更喜欢这个 Amazon AWS 端点:

import requests
ip = requests.get('https://checkip.amazonaws.com').text.strip()

如果您对通过访问任何地址获取公共 IP 不感兴趣,我认为下面的代码可以帮助您使用您的机器上的 python 获取公共 IP

import os
externalIP  = os.popen("ifconfig | grep 'inet' | cut -d: -f2 | awk '{print $2}' | sed -n 3p").readline()
print externalIP

Sed-n 3p 线路根据用于连接设备的网络而变化。

我也面临着同样的问题,我需要 iot 设备的公共 IP,它正在攻击我的服务器。但是在 ifconfig 命令中的 public ip 是完全不同的,ip 是从 request 对象进入服务器的。在此之后,我添加额外的参数到我的请求发送 ip 的设备到我的服务器。

希望这对你有帮助

试试:

import requests
ip = requests.get('http://ipinfo.io/json').json()['ip']

希望这对你有帮助

import os
externalIp = os.popen("ipconfig").read().split(":")[15][1:14]

有些数字可能需要更改,但这对我很有用

我使用 IPgrad 是因为它很容易记住:

# This example requires the requests library be installed.  You can learn more
# about the Requests library here: http://docs.python-requests.org/en/latest/
from requests import get


ip = get('http://ipgrab.io').text
print('My public IP address is: {}'.format(ip))

我喜欢 Sergiy Ostrovsky 的回答,但我认为现在有一个更整洁的方式来做这件事。

  1. 安装 开启库。
pip install ipify
  1. 导入并使用 Python 程序中的库。
import ipify
ip = ipify.get_ip()

进口操作系统 Public _ IP = os.system (“ inxi-i | grep‘ WAN IP’”) Print (public _ ip)

不幸的是,没有办法获得您的外部 IP 地址不咨询计算机在互联网上。最好的情况是,您可以得到您的网卡的本地网络 IP 地址(可能是192.16。.地址)。

可以使用 whatismyip模块获取外部 IP 地址。它在 Python3标准库之外没有任何依赖关系。它连接到公共 STUN 服务器和“我的 IP 是什么”网站,以找到 IPv4或 IPv6地址。运行 pip install whatismyip

例如:

>>> import whatismyip
>>> whatismyip.amionline()
True
>>> whatismyip.whatismyip()  # Prefers IPv4 addresses, but can return either IPv4 or IPv6.
'69.89.31.226'
>>> whatismyip.whatismyipv4()
'69.89.31.226'
>>> whatismyip.whatismyipv6()
'2345:0425:2CA1:0000:0000:0567:5673:23b5'