Получение внешнего IP-адреса машины с помощью Python

Ищу лучший способ получить текущий внешний IP-адрес машины # ... Ниже работает, но я бы предпочел не полагаться на внешний сайт для сбора информации ... Я ограничен использованием стандартных библиотек Python 2.5.1 в комплекте с Mac OS 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)

person cit    schedule 22.02.2010    source источник
comment
связанные: Программное обнаружение общедоступного IP-адреса   -  person jfs    schedule 27.02.2014


Ответы (27)


Если вы находитесь за маршрутизатором, который получает внешний IP-адрес, боюсь, у вас нет другого выбора, кроме как использовать внешнюю службу, как вы. Если у самого маршрутизатора есть некоторый интерфейс запросов, вы можете его использовать, но решение будет очень специфичным для среды и ненадежным.

person Sunny Milenov    schedule 22.02.2010
comment
Да согласен. Все облачные серверы, предоставляемые AWS и GoogleGCP, предоставляют только внутренний IP-адрес в запросе локального интерфейса. Мы должны использовать external для запроса его общедоступного IP-адреса. - person Clock ZHONG; 01.01.2020

Мне понравился 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: {}'.format(ip))
person Sergiy Ostrovsky    schedule 24.03.2016

Python3, используя только стандартную библиотеку

Как упоминалось ранее, можно использовать внешнюю службу, например https://ident.me, чтобы узнать внешний IP-адрес вашего маршрутизатора.

Вот как это делается с python3, не используя ничего, кроме стандартной библиотеки:

import urllib.request

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

print(external_ip)
person Serge Stroobandt    schedule 02.01.2017
comment
Хотя OP был для python 2, я думаю, что это должен быть принятый ответ для Python 3, потому что он не использует сторонние библиотеки. Однако обратите внимание, что identify.me (и другие, такие как ipv4bot.whatismyipaddress.com) запросы занимают примерно в два раза время, которое требуется api.ipify.org или ipinfo.io/ip, используя тот же код, что и этот ответ. Самый быстрый и простой ответ, который я нашел (среди полудюжины), - это api.ipify.org. - person Oliver; 20.06.2019
comment
@Oliver Следуя вашему совету, я протестировал и api.ipify.org, и ident.me Здесь, в Европе, ident.me примерно в три раза быстрее, чем api.ipify.org. Я так понимаю, вы находитесь в Канаде. - person Serge Stroobandt; 21.06.2019
comment
Серж, хаха, приятно осознавать, что это имеет смысл, спасибо за ответ. Да, Канада. - person Oliver; 21.06.2019
comment
Обратите внимание, что ident.me вернул IPv6 адрес, когда я использовал его со своего хоста, в то время как другие вернули IPv4 адреса из того же места. - person jcoppens; 19.06.2020

Вы должны использовать протокол UPnP, чтобы запросить эту информацию у своего маршрутизатора. Что наиболее важно, это не зависит от внешней службы, что, по-видимому, предполагает все остальные ответы на этот вопрос.

Есть библиотека Python miniupnp, которая может это сделать, см., Например, 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()))
person Vegard    schedule 29.12.2016
comment
Это работает, даже если вы подключены к VPN. Спасибо - person pumazi; 25.12.2018
comment
не будет работать при подключении к openvpn. Exception: No UPnP device discovered - person nurettin; 16.06.2019
comment
Хороший способ сделать! в зависимости от внешнего сервиса может блокировать запросы на основании Too many requests - person SIslam; 09.04.2021

Я предпочитаю эту конечную точку Amazon AWS:

import requests
ip = requests.get('https://checkip.amazonaws.com').text.strip()
person Max Malysh    schedule 20.08.2019
comment
Специально для тех, кто использует boto3! - person Ernesto Monroy; 21.05.2020

На мой взгляд, самое простое решение -

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

Это все.

person Jit9    schedule 27.06.2015
comment
Вероятно, стоит упомянуть, что вам нужно import requests. См. pypi.python.org/pypi/requests. - person John; 11.09.2015
comment
Технически не отвечает на вопрос, поскольку Requests официально поддерживает Python 2.6–2.7 и 3.3–3.7, а также отлично работает на PyPy. Тем не менее, это по-прежнему полезно для других. - person JerodG; 23.03.2017

Если вы думаете, что внешний источник слишком ненадежен, вы можете объединить несколько разных сервисов. Для большинства страниц IP-поиска они требуют, чтобы вы очистили html, но некоторые из них создали бережливые страницы для таких скриптов, как ваш, - также, чтобы они могли уменьшить количество обращений на своих сайтах:

person Thomas Ahle    schedule 22.02.2010

Если вы не хотите использовать внешние службы (IP-сайты и т. Д.), Вы можете использовать протокол UPnP .

Для этого мы используем простую клиентскую библиотеку 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')

Полный код (чтобы получить дополнительную информацию, как указано в файле readme на 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'}
person Eli    schedule 25.11.2018

Используйте модуль запросы:

import requests

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

print("\n[+] Public IP: "+myip)
person Ahmed    schedule 08.02.2019

Пытаться:

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

Надеюсь, это будет полезно

person NUACHE    schedule 07.08.2020

Так же просто, как запустить это в Python3:

import os

externalIP  = os.popen('curl -s ifconfig.me').readline()
print(externalIP)
person JavDomGom    schedule 02.03.2019
comment
Для этого требуется установленный curl - person Mojimi; 10.02.2020

Я попробовал большинство других ответов на этот вопрос здесь и обнаружил, что большинство используемых служб, кроме одной, не работают.

Вот сценарий, который должен помочь и загрузить минимальный объем информации:

#!/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() )
person Christian Jensen    schedule 05.06.2013
comment
Регулярное выражение не работает. Должно быть \ d {1,3}. - person Thanos Diacakis; 30.09.2013

Есть несколько других способов, которые не зависят от 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

OR

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

OR

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.

person PyTis    schedule 19.09.2018

Только решение для Linux.

В системах Linux вы можете использовать Python для выполнения команды в оболочке. Думаю, это может кому-то помочь.

Что-то вроде этого (при условии, что в ОС работает «копать / сверлить»)

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

Для пользователей Arch: замените «копать» на «сверлить».

person Arpan Srivastava    schedule 05.08.2019
comment
приводит к sh: 1: Синтаксическая ошибка: незавершенная строка в кавычках - person havlock; 07.02.2020
comment
@havlock Исправил. Пожалуйста, проверьте. - person Arpan Srivastava; 04.03.2020

Я использую IPGrab, потому что его легко запомнить:

# 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))
person Incogma    schedule 04.01.2021

Если машина является брандмауэром, ваше решение является очень разумным: альтернатива - возможность запросить брандмауэр, который в конечном итоге очень зависит от типа брандмауэра (если это вообще возможно).

person jldupont    schedule 22.02.2010

Самое простое (не Python) рабочее решение, о котором я могу думать, это

wget -q -O- icanhazip.com

Я хотел бы добавить очень короткое решение Python3, которое использует JSON API http://hostip.info.

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
person timgeb    schedule 09.05.2014

Работа с 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())
person user3526918    schedule 26.03.2018

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 не был проблемой.

person Malcolm Boyd    schedule 05.02.2013
comment
Злополучный на службе ушел: c - person jkmartindale; 01.10.2019

Вот еще один альтернативный сценарий.

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

person dr4ke616    schedule 19.01.2014
comment
Этот ответ раньше работал у меня, но пакеты ломаются при обновлении с использованием conda, поэтому я отказался от этого ответа ради более простого решения @Hors Sujet в stackoverflow.com/questions/24508730/ - person nagordon; 13.07.2015

Если вы пишете только для себя, а не для общего приложения, вы можете найти адрес на странице настройки вашего маршрутизатора, а затем очистить его от html этой страницы. У меня это отлично сработало с моим маршрутизатором SMC. Одно чтение и один простой поиск по RE, и я его нашел.

В частности, я был заинтересован в том, чтобы сообщить мне свой домашний IP-адрес, когда я был вдали от дома, чтобы я мог вернуться через VNC. Еще несколько строк Python хранит адрес в Dropbox для внешнего доступа и даже отправляет мне электронное письмо, если видит изменения. Я запланировал, чтобы это происходило при загрузке, а затем раз в час.

person Bruce    schedule 04.05.2014

Используйте этот скрипт:

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
person A-312    schedule 29.02.2016

Мне понравился ответ Сергея Островского, но я думаю, что сейчас есть еще более аккуратный способ сделать это.

  1. Установите библиотеку ipify.
pip install ipify
  1. Импортируйте и используйте библиотеку в своей программе Python.
import ipify
ip = ipify.get_ip()
person meicholtz    schedule 26.05.2021

Если вы не заинтересованы в том, чтобы нажимать какой-либо URL-адрес для получения общедоступного IP-адреса, я думаю, что следующий код может помочь вам получить общедоступный IP-адрес с использованием python вашей машины.

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

Строка sed -n 3p зависит от сети, которую вы используете для подключения устройства.

Я столкнулся с той же проблемой, мне нужен был общедоступный IP-адрес iot-устройства, которое попадает на мой сервер. но общедоступный IP-адрес полностью отличается в команде ifconfig и IP-адрес, который я получаю на сервере из объекта запроса. после этого я добавляю дополнительный параметр в свой запрос для отправки ip устройства на мой сервер.

надеюсь, что это будет полезно

person vishal-mote    schedule 14.01.2020

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

некоторые числа, возможно, потребуется изменить, но это работает для меня

person classy rat    schedule 03.01.2021
comment
ipconfig показывает частный IP - person PepeElMago33; 07.02.2021

person    schedule
comment
Черт, это немного быстрее, чем просто использовать BeautifulSoup, спасибо - person Eli; 09.10.2017

person    schedule
comment
Откуда берется библиотека оглушения? - person Score_Under; 28.02.2019