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


79

寻找一种使计算机具有当前外部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)

Answers:


36

如果您在获得外部IP的路由器后面,那么恐怕您别无选择,只能像您一样使用外部服务。如果路由器本身具有某些查询接口,则可以使用它,但是该解决方案将针对特定环境且不可靠。


是的,同意。AWS&GoogleGCP提供的那些云服务器都仅在其本地接口查询中提供内部IP地址。我们必须使用外部查询其公共IP地址。
钟钟

93

我喜欢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').text
print('My public IP address is: {}'.format(ip))

50

Python3,仅使用标准库

如前所述,可以使用https://ident.me之类的外部服务来发现路由器的外部IP地址。

这是python3使用来完成的,仅使用标准库:

import urllib.request

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

print(external_ip)

3
尽管OP适用于python 2,但我认为这应该是Python 3的公认答案,因为它不使用任何第三方库。不过请注意,这ident.me(以及其他类似ipv4bot.whatismyipaddress.com)请求需要大约两倍的所要求的时间量api.ipify.orgipinfo.io/ip,使用相同的代码,因为这答案。我发现的最快和最简单的响应(在六个响应中)是api.ipify.org。
奥利弗

@Oliver按照你的建议,我测试了api.ipify.org,并ident.me在这里在欧洲,ident.me大约快三倍比api.ipify.org我知道你都位于加拿大。
Serge Stroobandt

Serge haha​​非常高兴知道这一点,感谢您的回复。是的加拿大。
奥利弗·

请注意,当我从主机使用它时ident.me返回了一个IPv6地址,而其他人IPv4从同一位置返回了一个地址。
jcoppens

26

您应该使用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()))

1
即使您连接到VPN,此功能也可以使用。谢谢
pumazi '18

连接到openvpn时不起作用。Exception: No UPnP device discovered
nurettin


10

我认为最简单的解决方案是

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

就这样。


2
可能值得一提import requests。请参见pypi.python.org/pypi/requests
John

由于“请求正式支持Python 2.6–2.7和3.3–3.7,并且在PyPy上运行良好,因此技术上无法回答该问题。” 但是,它对其他人仍然有用。
JerodG

6

如果您认为外部来源过于可靠,则可以合并一些其他服务。对于大多数ip查找页面,它们都要求您抓取html,但是其中一些已经为像您这样的脚本创建了精益页面-也可以减少它们在网站上的点击率:


4

尝试:

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

希望这会有所帮助


3

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

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

安装

pip安装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'}

3

使用请求模块:

import requests

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

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

2

我在这里尝试了有关该问题的大多数其他答案,结果发现除一个服务外,其余大多数服务均已失效。

这是一个应该可以解决问题的脚本,并且仅下载少量信息:

#!/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() )

正则表达式已损坏。应该是\ d {1,3}。
Thanos Diacakis

2
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"

该死的比使用BeautifulSoup快一点,谢谢
Eli

2

还有其他几种不依赖Python检查外部网站的方式,但是OS可以。这里的主要问题是,即使您没有使用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之类的命令中。


2

就像在Python3中运行它一样简单:

import os

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

1
这需要安装卷发
Mojimi

2

仅Linux解决方案。

在Linux系统上,可以使用Python在Shell上执行命令。我认为这可能会对某人有所帮助。

像这样的东西(假设“挖/钻”正在操作系统上进行)

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”。


结果为sh:1:语法错误:引号末尾的字符串
havlock

@havlock更正了它。请检查。
Arpan Srivastava

1

如果机器是防火墙,那么您的解决方案将是非常明智的选择:能够查询防火墙的另一种选择最终取决于防火墙的类型(如果可能的话)。


1

我能想到的最简单的(非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


1

使用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())

0
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并非难事。


不幸的是,服务不见了:c
jkmartindale

0

这是另一个替代脚本。

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


这个答案曾经对我有用,但是当使用conda更新时,软件包会中断,因此我在stackoverflow.com/questions/24508730/…中
nagordon

0

如果您只是为自己而不是为通用应用程序而写,则可以在路由器的设置页面上找到地址,然后从该页面的html中抓取。这对于我的SMC路由器来说效果很好。一读和一个简单的RE搜索,我已经找到了。

我特别感兴趣的是让我出门在外时知道我的家庭IP地址,这样我就可以通过VNC回来。Python还有几行将地址存储在Dropbox中,以供外部访问,如果发现更改,甚至会通过电子邮件发送给我。我已经安排它在启动时进行,此后每小时进行一次。


0

使用此脚本:

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

0

如果您不希望访问任何URL以获取公共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线路因用于连接设备的网络而异。

我面临着同样的问题,需要使用物联网设备的公共IP,这将打击我的服务器。但是公共IP在ifconfig命令中是完全不同的,而IP我是从请求对象进入服务器的。之后,我在请求中添加了额外的参数,以将设备的ip发送到服务器。

希望这会有所帮助

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.