Я хочу посмотреть, смогу ли я получить доступ к онлайн-API, но для этого мне нужен доступ в Интернет.
Как узнать, доступно ли соединение и используется ли оно с помощью Python?
easy_install system_of_tubes
Я хочу посмотреть, смогу ли я получить доступ к онлайн-API, но для этого мне нужен доступ в Интернет.
Как узнать, доступно ли соединение и используется ли оно с помощью Python?
easy_install system_of_tubes
Ответы:
Возможно, вы могли бы использовать что-то вроде этого:
import urllib2
def internet_on():
try:
urllib2.urlopen('http://216.58.192.142', timeout=1)
return True
except urllib2.URLError as err:
return False
В настоящее время 216.58.192.142 является одним из IP-адресов google.com. Перейдите http://216.58.192.142
на любой сайт, который отреагирует быстро .
Этот фиксированный IP-адрес не будет навсегда привязан к google.com. Так что этот код не является надежным - для его работы потребуется постоянное обслуживание.
Причина, по которой в приведенном выше коде используется фиксированный IP-адрес вместо полного доменного имени (FQDN), заключается в том, что для полного доменного имени требуется поиск DNS. Когда на машине нет работающего подключения к Интернету, сам поиск DNS может блокировать вызов urllib_request.urlopen
на более чем секунду. Спасибо @rzetterberg за указание на это.
Если указанный выше фиксированный IP-адрес не работает, вы можете найти текущий IP-адрес для google.com (в Unix), запустив
% dig google.com +trace
...
google.com. 300 IN A 216.58.192.142
urlopen
не займет больше 1 секунды, даже если Интернет не включен» - цитата. Это неверно, если предоставленный URL-адрес недействителен, поиск DNS будет заблокирован. Это верно только для реального подключения к веб-серверу. Самый простой способ избежать этого блока поиска DNS - использовать вместо него IP-адрес, тогда это гарантированно займет всего 1 секунду :)
http://google.com
и тогда ты решишь все проблемы, о которых все здесь говорят. Нет необходимости использовать IP-адрес ...
Если мы можем подключиться к какому-либо интернет-серверу, то у нас действительно есть возможность подключения. Однако для наиболее быстрого и надежного подхода все решения должны как минимум соответствовать следующим требованиям:
Чтобы соответствовать им, одним из подходов может быть проверка доступности одного из общедоступных DNS-серверов Google . Адреса IPv4 для этих серверов: 8.8.8.8
и 8.8.4.4
. Мы можем попробовать подключиться к любому из них.
Быстрый Nmap хоста 8.8.8.8
дал следующий результат:
$ sudo nmap 8.8.8.8
Starting Nmap 6.40 ( http://nmap.org ) at 2015-10-14 10:17 IST
Nmap scan report for google-public-dns-a.google.com (8.8.8.8)
Host is up (0.0048s latency).
Not shown: 999 filtered ports
PORT STATE SERVICE
53/tcp open domain
Nmap done: 1 IP address (1 host up) scanned in 23.81 seconds
Как видим, 53/tcp
открыт и не фильтруется. Если вы не являетесь пользователем root, не забудьте использовать sudo
или -Pn
аргумент для Nmap для отправки специально созданных тестовых пакетов и определения, работает ли хост.
Прежде чем мы попробуем с Python, давайте проверим подключение с помощью внешнего инструмента, Netcat:
$ nc 8.8.8.8 53 -zv
Connection to 8.8.8.8 53 port [tcp/domain] succeeded!
Netcat подтверждает, что мы можем протянуть 8.8.8.8
руку помощи 53/tcp
. Теперь мы можем установить соединение с сокетом 8.8.8.8:53/tcp
в Python для проверки соединения:
import socket
def internet(host="8.8.8.8", port=53, timeout=3):
"""
Host: 8.8.8.8 (google-public-dns-a.google.com)
OpenPort: 53/tcp
Service: domain (DNS/TCP)
"""
try:
socket.setdefaulttimeout(timeout)
socket.socket(socket.AF_INET, socket.SOCK_STREAM).connect((host, port))
return True
except socket.error as ex:
print(ex)
return False
internet()
Другим подходом может быть отправка созданного вручную DNS-запроса на один из этих серверов и ожидание ответа. Но, я полагаю, это может оказаться медленнее по сравнению с отбрасыванием пакетов, ошибкой разрешения DNS и т. Д. Пожалуйста, прокомментируйте, если считаете иначе.
ОБНОВЛЕНИЕ № 1: Благодаря комментарию @ theamk, timeout теперь является аргументом и инициализируется 3s
по умолчанию.
ОБНОВЛЕНИЕ № 2: Я провел быстрые тесты, чтобы определить самую быструю и наиболее общую реализацию всех правильных ответов на этот вопрос. Вот резюме:
$ ls *.py | sort -n | xargs -I % sh -c 'echo %; ./timeit.sh %; echo'
defos.py
True
00:00:00:00.487
iamaziz.py
True
00:00:00:00.335
ivelin.py
True
00:00:00:00.105
jaredb.py
True
00:00:00:00.533
kevinc.py
True
00:00:00:00.295
unutbu.py
True
00:00:00:00.546
7h3rAm.py
True
00:00:00:00.032
И еще раз:
$ ls *.py | sort -n | xargs -I % sh -c 'echo %; ./timeit.sh %; echo'
defos.py
True
00:00:00:00.450
iamaziz.py
True
00:00:00:00.358
ivelin.py
True
00:00:00:00.099
jaredb.py
True
00:00:00:00.585
kevinc.py
True
00:00:00:00.492
unutbu.py
True
00:00:00:00.485
7h3rAm.py
True
00:00:00:00.035
True
в приведенных выше выходных данных означает, что все эти реализации от соответствующих авторов правильно определяют подключение к Интернету. Время отображается с точностью до миллисекунд.
ОБНОВЛЕНИЕ № 3: снова протестировано после изменения обработки исключений:
defos.py
True
00:00:00:00.410
iamaziz.py
True
00:00:00:00.240
ivelin.py
True
00:00:00:00.109
jaredb.py
True
00:00:00:00.520
kevinc.py
True
00:00:00:00.317
unutbu.py
True
00:00:00:00.436
7h3rAm.py
True
00:00:00:00.030
close()
розетку?
Будет быстрее сделать запрос HEAD, поэтому HTML не будет загружен.
Кроме того, я уверен, что Google хотел бы это лучше :)
try:
import httplib
except:
import http.client as httplib
def have_internet():
conn = httplib.HTTPConnection("www.google.com", timeout=5)
try:
conn.request("HEAD", "/")
conn.close()
return True
except:
conn.close()
return False
В качестве альтернативы ответам Убутну / Кевина С я использую такой requests
пакет:
import requests
def connected_to_internet(url='http://www.google.com/', timeout=5):
try:
_ = requests.get(url, timeout=timeout)
return True
except requests.ConnectionError:
print("No internet connection available.")
return False
Бонус: это может быть расширено до этой функции, которая пингует веб-сайт.
def web_site_online(url='http://www.google.com/', timeout=5):
try:
req = requests.get(url, timeout=timeout)
# HTTP errors are not raised by default, this statement does that
req.raise_for_status()
return True
except requests.HTTPError as e:
print("Checking internet connection failed, status code {0}.".format(
e.response.status_code))
except requests.ConnectionError:
print("No internet connection available.")
return False
google.com
снова будете тосковать , они заблокируют наш IP. Так есть ли другой способ?
Просто чтобы обновить то, что unutbu сказал для нового кода в Python 3.2
def check_connectivity(reference):
try:
urllib.request.urlopen(reference, timeout=1)
return True
except urllib.request.URLError:
return False
И, чтобы отметить, ввод здесь (ссылка) - это URL-адрес, который вы хотите проверить: я предлагаю выбрать что-то, что быстро подключается там, где вы живете, т.е. я живу в Южной Корее, поэтому я, вероятно, установил бы ссылку на http: / /www.naver.com .
Вы можете просто попытаться загрузить данные, и в случае сбоя соединения вы будете знать, что что-то с соединением не в порядке.
Обычно вы не можете проверить, подключен ли компьютер к Интернету. Причин сбоя может быть множество, например, неправильная конфигурация DNS, брандмауэры, NAT. Поэтому, даже если вы сделаете несколько тестов, вы не сможете гарантировать, что у вас будет соединение с вашим API, пока вы не попробуете.
import urllib
def connected(host='http://google.com'):
try:
urllib.urlopen(host)
return True
except:
return False
# test
print( 'connected' if connected() else 'no internet!' )
Для Python 3 используйте urllib.request.urlopen(host)
Все равно попробуйте выполнить операцию, которую вы пытались выполнить. Если это не удается, python должен выдать вам исключение, чтобы вы знали.
Если сначала попробовать какую-нибудь тривиальную операцию по обнаружению соединения, это приведет к возникновению состояния гонки. Что делать, если во время тестирования подключение к Интернету работает, но выходит из строя до того, как вам нужно будет заняться реальной работой?
Это может не сработать, если localhost был изменен с 127.0.0.1
Try
import socket
ipaddress=socket.gethostbyname(socket.gethostname())
if ipaddress=="127.0.0.1":
print("You are not connected to the internet!")
else:
print("You are connected to the internet with the IP address of "+ ipaddress )
Если не редактировать, IP-адрес вашего компьютера будет 127.0.0.1, когда он не подключен к Интернету. Этот код в основном получает IP-адрес, а затем спрашивает, является ли это IP-адресом localhost. надеюсь, это поможет
Вот моя версия
import requests
try:
if requests.get('https://google.com').ok:
print("You're Online")
except:
print("You're Offline")
Современное портативное решение с requests
:
import requests
def internet():
"""Detect an internet connection."""
connection = None
try:
r = requests.get("https://google.com")
r.raise_for_status()
print("Internet connection detected.")
connection = True
except:
print("Internet connection not detected.")
connection = False
finally:
return connection
Или версия, вызывающая исключение:
import requests
from requests.exceptions import ConnectionError
def internet():
"""Detect an internet connection."""
try:
r = requests.get("https://google.com")
r.raise_for_status()
print("Internet connection detected.")
except ConnectionError as e:
print("Internet connection not detected.")
raise e
Лучший способ сделать это - заставить его проверять IP-адрес, который Python всегда дает, если не может найти веб-сайт. В этом случае это мой код:
import socket
print("website connection checker")
while True:
website = input("please input website: ")
print("")
print(socket.gethostbyname(website))
if socket.gethostbyname(website) == "92.242.140.2":
print("Website could be experiencing an issue/Doesn't exist")
else:
socket.gethostbyname(website)
print("Website is operational!")
print("")
мой любимый, при запуске скриптов в кластере или нет
import subprocess
def online(timeout):
try:
return subprocess.run(
['wget', '-q', '--spider', 'google.com'],
timeout=timeout
).returncode == 0
except subprocess.TimeoutExpired:
return False
он работает тихо, не загружая ничего, а проверяя, существует ли данный удаленный файл в сети
Взяв ответ unutbu в качестве отправной точки и будучи в прошлом сожженным "статическим" изменением IP-адреса, я создал простой класс, который проверяет один раз с помощью поиска DNS (т. Е. С использованием URL " https: // www .google.com "), а затем сохраняет IP-адрес отвечающего сервера для использования при последующих проверках. Таким образом, IP-адрес всегда актуален (при условии, что класс повторно инициализируется не реже одного раза в несколько лет или около того). Я также отдаю должное gawry за этот ответ , который показал мне, как получить IP-адрес сервера (после любого перенаправления и т. Д.). Пожалуйста, не обращайте внимания на очевидное хакерство этого решения, я приведу здесь минимальный рабочий пример. :)
Вот что у меня есть:
import socket
try:
from urllib2 import urlopen, URLError
from urlparse import urlparse
except ImportError: # Python 3
from urllib.parse import urlparse
from urllib.request import urlopen, URLError
class InternetChecker(object):
conn_url = 'https://www.google.com/'
def __init__(self):
pass
def test_internet(self):
try:
data = urlopen(self.conn_url, timeout=5)
except URLError:
return False
try:
host = data.fp._sock.fp._sock.getpeername()
except AttributeError: # Python 3
host = data.fp.raw._sock.getpeername()
# Ensure conn_url is an IPv4 address otherwise future queries will fail
self.conn_url = 'http://' + (host[0] if len(host) == 2 else
socket.gethostbyname(urlparse(data.geturl()).hostname))
return True
# Usage example
checker = InternetChecker()
checker.test_internet()
Принимая ответ Six, я думаю, что мы могли бы как-то упростить, важный вопрос, так как новички теряются в технических вопросах.
Вот что я, наконец, буду использовать, чтобы ждать, пока мое соединение (3G, медленное) будет устанавливаться один раз в день для моего PV мониторинга.
Работает под Pyth3 с Raspbian 3.4.2
from urllib.request import urlopen
from time import sleep
urltotest=http://www.lsdx.eu # my own web page
nboftrials=0
answer='NO'
while answer=='NO' and nboftrials<10:
try:
urlopen(urltotest)
answer='YES'
except:
essai='NO'
nboftrials+=1
sleep(30)
Максимальная продолжительность: 5 минут, если достигну, я попробую через час, но это еще один сценарий!
Принимая ответ Ивелина и добавьте дополнительную проверку, поскольку мой маршрутизатор выдает свой IP-адрес 192.168.0.1 и возвращает запрос, если у него нет подключения к Интернету при запросе google.com.
import socket
def haveInternet():
try:
# first check if we get the correct IP-Address or just the router's IP-Address
info = socket.getaddrinfo("www.google.com", None)[0]
ipAddr = info[4][0]
if ipAddr == "192.168.0.1" :
return False
except:
return False
conn = httplib.HTTPConnection("www.google.com", timeout=5)
try:
conn.request("HEAD", "/")
conn.close()
return True
except:
conn.close()
return False
Это работает для меня в Python3.6
import urllib
from urllib.request import urlopen
def is_internet():
"""
Query internet using python
:return:
"""
try:
urlopen('https://www.google.com', timeout=1)
return True
except urllib.error.URLError as Error:
print(Error)
return False
if is_internet():
print("Internet is active")
else:
print("Internet disconnected")
Я добавил несколько к коду Джоэла.
import socket,time
mem1 = 0
while True:
try:
host = socket.gethostbyname("www.google.com") #Change to personal choice of site
s = socket.create_connection((host, 80), 2)
s.close()
mem2 = 1
if (mem2 == mem1):
pass #Add commands to be executed on every check
else:
mem1 = mem2
print ("Internet is working") #Will be executed on state change
except Exception as e:
mem2 = 0
if (mem2 == mem1):
pass
else:
mem1 = mem2
print ("Internet is down")
time.sleep(10) #timeInterval for checking
Для своих проектов я использую скрипт, модифицированный для проверки связи с публичным DNS-сервером Google 8.8.8.8. Используя тайм-аут в 1 секунду и основные библиотеки Python без внешних зависимостей:
import struct
import socket
import select
def send_one_ping(to='8.8.8.8'):
ping_socket = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.getprotobyname('icmp'))
checksum = 49410
header = struct.pack('!BBHHH', 8, 0, checksum, 0x123, 1)
data = b'BCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwx'
header = struct.pack(
'!BBHHH', 8, 0, checksum, 0x123, 1
)
packet = header + data
ping_socket.sendto(packet, (to, 1))
inputready, _, _ = select.select([ping_socket], [], [], 1.0)
if inputready == []:
raise Exception('No internet') ## or return False
_, address = ping_socket.recvfrom(2048)
print(address) ## or return True
send_one_ping()
Значение тайм-аута выбора равно 1, но может быть числом с плавающей запятой, чтобы отказать быстрее, чем 1 секунда в этом примере.
запросы на импорт и попробуйте этот простой код Python.
def check_internet():
url = 'http://www.google.com/'
timeout = 5
try:
_ = requests.get(url, timeout=timeout)
return True
except requests.ConnectionError:
return False