オンライン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はgoogle.comのIPアドレスの1つです。迅速な対応が期待できるサイトに変更http://216.58.192.142
します。
この固定IPはgoogle.comに永久にマッピングされません。したがって、このコードは堅牢ではありません。コードを機能させるには、定期的なメンテナンスが必要です。
上記のコードが完全修飾ドメイン名(FQDN)ではなく固定IPアドレスを使用する理由は、FQDNがDNSルックアップを必要とするためです。マシンにインターネット接続が機能していない場合、DNSルックアップ自体がurllib_request.urlopen
1秒以上。これを指摘してくれた@rzetterbergに感謝します。
上記の固定IPアドレスが機能しない場合、次のコマンドを実行すると、google.com(UNIX)の現在のIPアドレスを見つけることができます
% dig google.com +trace
...
google.com. 300 IN A 216.58.192.142
urlopen
インターネットが「オン」になっていなくても、への通話に1秒以上かかることはありません。指定されたURLが無効な場合、これは当てはまりません。DNSルックアップがブロックされます。これは、Webサーバーへの実際の接続にのみ当てはまります。このDNSルックアップブロックを回避する最も簡単な方法は、代わりにIPアドレスを使用することです。1秒しか
http://google.com
ば、みんながここで話し続けている問題をすべて解決できます。IPアドレスを使用する必要はありません...
インターネットサーバーに接続できれば、接続は確立されています。ただし、最速かつ最も信頼性の高いアプローチのために、すべてのソリューションは少なくとも次の要件に準拠する必要があります。
これらに準拠するには、1つのアプローチとして、GoogleのパブリックDNSサーバーの 1つにアクセスできるかどうかを確認します。これらのサーバーの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プローブをこれらのサーバーの1つに送信して、応答を待つ方法があります。ただし、パケットのドロップやDNS解決の失敗などにより、速度が遅くなる可能性があると思います。それ以外の場合はコメントしてください。
更新#1:@theamkのコメントのおかげで、タイムアウトは引数になり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はフェッチされません。
また、グーグルはこの方法でそれをより良くしたいと思います:)
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
ubutnu's / Kevin Cの回答の代わりに、次の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
ボーナス:これは、Webサイトにpingするこの機能に拡張できます。
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がブロックされます。他に方法はありますか?
Python 3.2の新しいコードについてunutbuが言ったことを更新するだけです
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との接続が保証されるわけではありません。
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アドレスを取得し、それがlocalhost IPアドレスであるかどうかを尋ねます。それが役に立てば幸い
これが私のバージョンです
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
これを行う最良の方法は、PythonがWebサイトを見つけられない場合に常に提供するIPアドレスに対してチェックを行うことです。この場合、これは私のコードです:
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("")
撮影unutbuの答えの開始点としての、および「静的」IPアドレスを変更することで、過去に焼かれた、私はDNSルックアップを使用して一度チェックが(すなわち、「URLを使用していることを単純なクラスを作りました// WWW:HTTPS .google.com ")、次に、後続のチェックで使用するために応答サーバーのIPアドレスを保存します。このようにして、IPアドレスは常に最新の状態になります(クラスが少なくとも数年ごとに1回程度再初期化されると仮定)。また、この回答について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()
シックスの答えを取ると、私はどういうわけか単純化できると思います。非常に技術的な問題で新規参入者が失われるので、重要な問題です。
ここで、PVモニタリングのために1日に1回接続(3G、低速)が確立されるのを待つために最終的に使用するものです。
Rypbian 3.4.2のPyth3で動作します
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分に達した場合、1時間で試してみますが、もう1つのスクリプトです!
私のルーターがIPアドレス192.168.0.1を配信し、google.comへのクエリ時にインターネットに接続していない場合はヘッドを返すため、Ivelinの回答を受け取り、追加のチェックを追加します。
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")
Joelのコードにいくつか追加しました。
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
私のプロジェクトでは、GoogleパブリックDNSサーバー8.8.8.8にpingするように変更されたスクリプトを使用します。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秒よりも容易に失敗する任意の浮動小数点数であることができます。