Получение внешнего 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)

35 ответов

Решение

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

Мне понравился 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

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

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

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

import urllib.request

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

print(external_ip)

Я написал для этого модуль: ipgetter. Предназначен для получения вашего внешнего IP-адреса из Интернета. Он используется в основном за NAT. Он выбирает ваш IP случайным образом из списка серверов, чтобы минимизировать накладные расходы на запрос на одном сервере. Фактически с 44 сервером и тестовой функцией, чтобы проверить, возвращают ли серверы тот же IP.

https://github.com/phoemur/ipgetter

выглядит так:

>>> import ipgetter
>>> IP = ipgetter.myip()
>>> print(IP)
'xxx.xxx.xxx.xxx'

>>> ipgetter.IPgetter().test()
Number of servers: 44
IP's :
'xxx.xxx.xxx.xxx' = 44 ocurrencies

I prefer this Amazon AWS endpoint:

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

Вы должны использовать протокол 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()))

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

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

Это все.

Использовать модуль запросов:

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)

Если вы не хотите использовать внешние сервисы (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'}

Пытаться:

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

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

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

Я использую 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))

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

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

Вы можете использовать модуль для получения внешних IP-адресов. Он не имеет зависимостей за пределами стандартной библиотеки Python 3. Он подключается к общедоступным серверам STUN и веб-сайтам what-is-my-ip, чтобы найти адрес IPv4 или IPv6. Бежать pip install whatismyip

Пример:

      >>> import whatismyip
>>> whatismyip.amionline()
True
>>> whatismyip.whatismyip()  # Prefers IPv4 addresses, but can return either IPv4 or IPv6.
'69.89.31.226'
>>> whatismyip.whatismyipv4()
'69.89.31.226'
>>> whatismyip.whatismyipv6()
'2345:0425:2CA1:0000:0000:0567:5673:23b5'
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"

Единственное решение для 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: замените "копать" на "сверлить".

Самое простое (не 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

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

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

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

Работа с 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())
In [1]: import stun

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

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

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

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

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

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

Вышеуказанные ответы либо устарели, либо сложны. В настоящее время это работает на последней версии Python 3.11=

      import urllib.request
import json

def get_external_ip():
    try:
        response = urllib.request.urlopen("https://httpbin.org/ip")
        data = json.load(response)
        address = data['origin']
        return address
    except Exception as e:
        return str(e)

if __name__ == '__main__':
    print(get_external_ip())

import ospublic_ip = os.system("inxi -i |grep 'WAN IP'")print(public_ip)

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

Чтобы получить внешний IP-адрес, используйте этот код:

      from requests import get

def get_external_ip()->str:
    return get('https://api.ipify.org/').text

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

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

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

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

Другие вопросы по тегам