寻找一种更好的方法来获取机器当前的外部IP#...下面工作,但宁愿不依赖外部网站来收集信息......我只能使用与Mac OS捆绑在一起的标准Python 2.5.1库X 10.5.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)
如果你在获得外部IP的路由器后面,我恐怕你别无选择,只能像你一样使用外部服务。如果路由器本身有一些查询接口,您可以使用它,但解决方案将非常环境且不可靠。
如果机器是防火墙,那么你的解决方案是一个非常明智的解决方案:能够查询防火墙的替代方案最终依赖于防火墙的类型(如果可能的话)。
我能想到的最简单(非python)工作解决方案是
wget -q -O- icanhazip.com
我想添加一个非常简短的Python3解决方案,该解决方案利用了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
In [1]: import stun
stun.get_ip_info()
('Restric NAT', 'xx.xx.xx.xx', 55320)
使用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())
如果您不想使用外部服务(IP网站等),您可以使用UPnP Protocol。
我们使用一个简单的UPnP客户端库(https://github.com/flyte/upnpclient)
安装:
pip install upnpclient
简单代码:
import upnpclient
devices = upnpclient.discover()
if(len(devices) > 0):
externalIP = devices[0].WANIPConn1.GetExternalIPAddress()
print(externalIP)
else:
print('No Connected network interface detected')
完整代码(以获取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)
就像在Python3中运行它一样简单:
import os
externalIP = os.popen('curl -s ifconfig.me').readline()
print(externalIP)
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不是一个痛苦。
这是另一个替代脚本。
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
如果您只是为自己而不是为通用应用程序编写,您可能能够在路由器的设置页面上找到该地址,然后从该页面的html中删除它。使用我的SMC路由器,这对我来说很好。一次读取和一次简单的RE搜索,我找到了它。
我特别感兴趣的是当我不在家时让我知道我的家庭IP地址,所以我可以通过VNC回来。还有几行Python将地址存储在Dropbox中以供外部访问,如果发现更改,甚至会通过电子邮件发送给我。我已经预定它会在开机时发生,之后每小时发生一次。
我喜欢http://ipify.org。他们甚至提供Python代码来使用他们的API。
# 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').text
print 'My public IP address is:', ip
使用此脚本:
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
Linux唯一解决方案。
在Linux系统上,您可以使用Python在shell上执行命令。我认为这可能对某人有所帮助。
像这样的东西,(假设'挖'正在使用os)
import os
command = '''dig TXT +short o-o.myaddr.l.google.com @ns1.google.com | awk -F'"' '{ print $2}'''
ip = os.system(command)
我更喜欢这个亚马逊AWS端点:
import requests
ip = requests.get('https://checkip.amazonaws.com').text.strip()
如前所述,可以使用像external service这样的https://ident.me来发现路由器的外部IP地址。
这是如何用python3
完成的,除了the standard library:之外别无其他
import urllib.request
external_ip = urllib.request.urlopen('https://ident.me').read().decode('utf8')
print(external_ip)
您应该使用UPnP protocol查询路由器以获取此信息。最重要的是,这并不依赖于外部服务,这个问题的所有其他答案似乎都表明了这一点。
有一个名为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()))
如果您认为外部源太不可靠,您可以汇集一些不同的服务。对于大多数ip查找页面,他们要求你抓取html,但其中一些已经创建了像你这样的脚本的精简页面 - 这样他们就可以减少他们网站上的点击量:
在我看来,最简单的解决方案是
f = requests.request('GET', 'http://myip.dnsomatic.com')
ip = f.text
就这样。
我在这个问题上尝试了大多数其他答案,然后发现除了一个之外,大多数使用的服务都已解散。
这是一个脚本应该做的技巧,只下载最少量的信息:
#!/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() )
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检查外部网站,但操作系统可以。这里的主要问题是,即使您没有使用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等命令中。