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

问题描述 投票:47回答:20

寻找一种更好的方法来获取机器当前的外部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)
python standard-library
20个回答
27
投票

如果你在获得外部IP的路由器后面,我恐怕你别无选择,只能像你一样使用外部服务。如果路由器本身有一些查询接口,您可以使用它,但解决方案将非常环境且不可靠。


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
投票
In [1]: import stun

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

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

1
投票

如果您不想使用外部服务(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'}

1
投票

Use requests module:

import requests

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

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

1
投票

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

import os

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

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不是一个痛苦。


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


0
投票

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

我特别感兴趣的是当我不在家时让我知道我的家庭IP地址,所以我可以通过VNC回来。还有几行Python将地址存储在Dropbox中以供外部访问,如果发现更改,甚至会通过电子邮件发送给我。我已经预定它会在开机时发生,之后每小时发生一次。


50
投票

我喜欢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

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
投票

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)

0
投票

我更喜欢这个亚马逊AWS端点:

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

31
投票

Python3, using nothing else but the standard library

如前所述,可以使用像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)

19
投票

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

6
投票

如果您认为外部源太不可靠,您可以汇集一些不同的服务。对于大多数ip查找页面,他们要求你抓取html,但其中一些已经创建了像你这样的脚本的精简页面 - 这样他们就可以减少他们网站上的点击量:


3
投票

在我看来,最简单的解决方案是

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

就这样。


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

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"

2
投票

还有一些其他方法不依赖于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等命令中。

© www.soinside.com 2019 - 2024. All rights reserved.