Abrufen der externen IP-Adresse eines Computers mit Python

79

Auf der Suche nach einem besseren Weg, um die aktuelle externe IP-Nummer eines Computers zu erhalten ... Das Folgende funktioniert, würde sich aber nicht auf eine externe Site verlassen, um die Informationen zu sammeln ... Ich kann nur Standard-Python 2.5.1-Bibliotheken verwenden, die mit Mac OS gebündelt sind 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)
cit
quelle

Antworten:

36

Wenn Sie sich hinter einem Router befinden, der die externe IP-Adresse erhält, haben Sie leider keine andere Wahl, als den externen Dienst wie Sie zu nutzen. Wenn der Router selbst über eine Abfrageoberfläche verfügt, können Sie diese verwenden, die Lösung ist jedoch sehr umgebungsspezifisch und unzuverlässig.

Sunny Milenov
quelle
Ja zustimmen. Die von AWS & GoogleGCP bereitgestellten Cloud-Server geben in ihrer lokalen Schnittstellenabfrage nur die interne IP-Adresse an. Wir müssen external verwenden, um die öffentliche IP-Adresse abzufragen.
Uhr ZHONG
93

Ich mochte die http://ipify.org . Sie stellen sogar Python-Code für die Verwendung ihrer API bereit.

# 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))
Sergiy Ostrovsky
quelle
50

Python3 verwendet nichts anderes als die Standardbibliothek

Wie bereits erwähnt, kann ein externer Dienst wie https://ident.me verwendet werden, um die externe IP-Adresse Ihres Routers zu ermitteln.

So wird es gemacht python3, indem nichts anderes als die Standardbibliothek verwendet wird:

import urllib.request

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

print(external_ip)
Serge Stroobandt
quelle
3
Obwohl das OP für Python 2 war, sollte dies die akzeptierte Antwort für Python 3 sein, da keine Bibliotheken von Drittanbietern verwendet werden. Beachten Sie jedoch, dass Anfragen von ident.me (und anderen wie ipv4bot.whatismyipaddress.com ) etwa doppelt so lange dauern , wie von api.ipify.org oder ipinfo.io/ip gefordert , und denselben Code wie diese Antwort verwenden. Die schnellste und einfachste Antwort, die ich gefunden habe (unter einem halben Dutzend), ist die von api.ipify.org.
Oliver
@Oliver Auf Ihren Vorschlag hin habe ich beide getestet api.ipify.orgund ident.mehier in Europa ident.meist es ungefähr dreimal schneller als api.ipify.orgich verstehe, dass Sie sich in Kanada befinden.
Serge Stroobandt
Serge haha ​​gut zu wissen, dass das Sinn macht, danke für die Rückmeldung. Ja, Kanada.
Oliver
Beachten Sie, dass ident.meeine IPv6Adresse zurückgegeben wurde, als ich sie von meinem Host verwendet habe, während die anderen IPv4Adressen vom selben Speicherort zurückgegeben haben.
jcoppens
26

Sie sollten das UPnP-Protokoll verwenden , um Ihren Router nach diesen Informationen abzufragen. Am wichtigsten ist jedoch, dass dies nicht auf einem externen Dienst beruht, was alle anderen Antworten auf diese Frage zu suggerieren scheinen.

Es gibt eine Python-Bibliothek namens miniupnp, die dies kann, siehe z . B. miniupnpc / testupnpigd.py .

pip install miniupnpc

Anhand ihres Beispiels sollten Sie in der Lage sein, Folgendes zu tun:

import miniupnpc

u = miniupnpc.UPnP()
u.discoverdelay = 200
u.discover()
u.selectigd()
print('external ip address: {}'.format(u.externalipaddress()))
Vegard
quelle
1
Dies funktioniert auch, wenn Sie mit einem VPN verbunden sind. Danke
Pumazi
funktioniert nicht, wenn eine Verbindung zu openvpn besteht. Exception: No UPnP device discovered
Nurettin
15

Ich bevorzuge diesen Amazon AWS-Endpunkt:

import requests
ip = requests.get('https://checkip.amazonaws.com').text.strip()
Max Malysh
quelle
Besonders für diejenigen, die boto3 verwenden!
Ernesto Monroy
10

Meiner Meinung nach ist die einfachste Lösung

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

Das ist alles.

Jit9
quelle
2
Es ist wahrscheinlich erwähnenswert, dass Sie müssen import requests. Siehe pypi.python.org/pypi/requests
John
Beantwortet die Frage technisch nicht, da " Requests Python 2.6–2.7 & 3.3–3.7 offiziell unterstützt und auf PyPy hervorragend läuft." Es ist jedoch immer noch nützlich für andere.
JerodG
6

Wenn Sie der Meinung sind, dass eine externe Quelle zu unzuverlässig ist, können Sie einige verschiedene Dienste zusammenfassen. Für die meisten IP-Suchseiten müssen Sie HTML kratzen, aber einige von ihnen haben schlanke Seiten für Skripte wie Ihres erstellt - auch, damit sie die Treffer auf ihren Websites reduzieren können:

Thomas Ahle
quelle
4

Versuchen:

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

Hoffe das ist hilfreich

NUACHE
quelle
3

Wenn Sie keine externen Dienste (IP-Websites usw.) verwenden möchten, können Sie das UPnP-Protokoll verwenden .

Dazu verwenden wir eine einfache UPnP-Client-Bibliothek ( https://github.com/flyte/upnpclient ).

Installieren :

pip install upnpclient

Einfacher Code :

import upnpclient

devices = upnpclient.discover()

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

Vollständiger Code (um weitere Informationen zu erhalten, wie in der Github-Readme-Datei erwähnt)

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'}
Eli
quelle
3

Verwendung anfordert Modul:

import requests

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

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

Ich habe die meisten anderen Antworten auf diese Frage hier ausprobiert und festgestellt, dass die meisten verwendeten Dienste bis auf einen nicht mehr funktionieren.

Hier ist ein Skript, das den Trick machen und nur eine minimale Menge an Informationen herunterladen sollte:

#!/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() )
Christian Jensen
quelle
Regex ist kaputt. Sollte \ d {1,3} sein.
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"
Nikita Rovda
quelle
Verdammt, das ist ein bisschen schneller als nur mit BeautifulSoup, danke
Eli
2

Es gibt einige andere Möglichkeiten, die nicht darauf beruhen, dass Python eine externe Website überprüft, das Betriebssystem kann dies jedoch. Ihr Hauptproblem hierbei ist, dass selbst wenn Sie Python nicht verwenden, wenn Sie die Befehlszeile verwenden, es keine "integrierten" Befehle gibt, die Ihnen einfach die externe (WAN) IP mitteilen können. Befehle wie "ip addr show" und "ifconfig -a" zeigen Ihnen die IP-Adresse des Servers im Netzwerk. Nur der Router hält tatsächlich die externe IP. Es gibt jedoch Möglichkeiten, die externe IP-Adresse (WAN-IP) über die Befehlszeile zu ermitteln.

Diese Beispiele sind:

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

Daher wäre der Python-Code:

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

ODER

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

ODER

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

Oder schließen Sie ein anderes der oben genannten Beispiele an einen Befehl wie os.popen, os.popen2, os.popen3 oder os.system an.

PyTis
quelle
2

So einfach wie das Ausführen in Python3:

import os

externalIP  = os.popen('curl -s ifconfig.me').readline()
print(externalIP)
JavDomGom
quelle
1
Dies erfordert die Installation von Curl
Mojimi
2

Nur Linux-Lösung.

Auf Linux-Systemen können Sie mit Python einen Befehl für die Shell ausführen. Ich denke, es könnte jemandem helfen.

So etwas in der Art (vorausgesetzt, 'Dig / Drill' arbeitet am Betriebssystem)

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

Für Arch-Benutzer ersetzen Sie bitte 'dig' durch 'fill'.

Arpan Srivastava
quelle
führt zu sh: 1: Syntaxfehler:
Nicht abgeschlossene
@ Havlock Korrigiert. Bitte prüfen.
Arpan Srivastava
1

Wenn es sich bei dem Computer um eine Firewall handelt, ist Ihre Lösung sehr sinnvoll: Die Alternative besteht darin, die Firewall abzufragen, die letztendlich stark vom Firewall-Typ abhängt (sofern dies überhaupt möglich ist).

jldupont
quelle
1

Die einfachste (nicht Python) funktionierende Lösung, die ich mir vorstellen kann, ist

wget -q -O- icanhazip.com

Ich möchte eine sehr kurze Python3-Lösung hinzufügen, die die JSON-API von http://hostip.info verwendet .

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'])

Sie können natürlich einige Fehlerprüfungen, eine Zeitüberschreitungsbedingung und einige Annehmlichkeiten hinzufügen:

#!/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
timgeb
quelle
1
In [1]: import stun

stun.get_ip_info()
('Restric NAT', 'xx.xx.xx.xx', 55320)
Enthusiasten
quelle
1
Woher kommt die Betäubungsbibliothek?
Score_Under
1

Arbeiten mit Python 2.7 .6 und 2.7.13

import urllib2  
req = urllib2.Request('http://icanhazip.com', data=None)  
response = urllib2.urlopen(req, timeout=5)  
print(response.read())
user3526918
quelle
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]

Dies ist ein kurzer Ausschnitt, den ich für ein anderes Programm geschrieben habe. Der Trick bestand darin, eine Website zu finden, die einfach genug war, damit das Zerlegen des HTML-Codes kein Problem war.

Malcolm Boyd
quelle
Das
Unglück
0

Hier ist ein weiteres alternatives Skript.

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

BEARBEITEN: Vergessen Sie nicht, httplib und json zu importieren

dr4ke616
quelle
Diese Antwort funktionierte früher für mich, aber die Pakete brechen beim Aktualisieren mit conda ab. Daher habe ich diese Antwort für eine einfachere Lösung aufgegeben. @Hors Sujet in stackoverflow.com/questions/24508730/…
nagordon
0

Wenn Sie nur für sich selbst und nicht für eine allgemeine Anwendung schreiben, können Sie möglicherweise die Adresse auf der Setup-Seite für Ihren Router finden und sie dann aus dem HTML-Code dieser Seite entfernen. Dies funktionierte gut mit meinem SMC-Router. Eine gelesene und eine einfache RE-Suche und ich habe sie gefunden.

Mein besonderes Interesse dabei war es, mir meine Heimat-IP-Adresse mitzuteilen, wenn ich nicht zu Hause war, damit ich über VNC wieder einsteigen konnte. Ein paar weitere Zeilen von Python speichern die Adresse in Dropbox für den Zugriff von außen und senden mir sogar eine E-Mail, wenn sich etwas ändert. Ich habe geplant, dass es beim Booten und danach einmal pro Stunde passiert.

Bruce
quelle
0

Verwenden Sie dieses Skript:

import urllib, json

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

Ohne json:

import urllib, re

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

Wenn Sie nicht daran interessiert sind, eine URL zu treffen, um eine öffentliche IP zu erhalten, kann der folgende Code Ihnen helfen, eine öffentliche IP mit Python Ihres Computers zu erhalten

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

Die sed -n 3p-Leitung hängt vom Netzwerk ab, das Sie zum Anschließen des Geräts verwenden.

Ich hatte das gleiche Problem, ich brauchte eine öffentliche IP-Adresse des iot-Geräts, die auf meinen Server trifft. Aber die öffentliche IP-Adresse unterscheidet sich völlig vom Befehl ifconfig und der IP-Adresse, die ich vom Anforderungsobjekt auf dem Server erhalte. Danach füge ich meiner Anfrage, eine IP-Adresse des Geräts an meinen Server zu senden, einen zusätzlichen Parameter hinzu.

hoffe das ist hilfreich

Vishal-Mote
quelle