オンラインAPIにアクセスできるかどうかを確認したいのですが、そのためにはインターネットアクセスが必要です。
Pythonを使用して使用可能なアクティブな接続があるかどうかを確認するにはどうすればよいですか?
おそらく、次のようなものを使用できます。
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
何らかのインターネットサーバーに接続できれば、実際に接続できます。ただし、最も高速で信頼性の高いアプローチを実現するには、すべてのソリューションが少なくとも次の要件に準拠する必要があります。
これらに準拠するための1つの方法は、 GoogleのパブリックDNSサーバー の1つが到達可能かどうかを確認することです。これらのサーバーのIPv4アドレスは、8.8.8.8
および8.8.4.4
です。それらのいずれかに接続してみることができます。
ホスト8.8.8.8
のクイックNmapの結果は以下のとおりです。
$ 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
ご覧のとおり、TCP/53は開いており、フィルタリングされていません。非ルートユーザーの場合は、NmapにSudo
または-Pn
引数を使用して、細工されたプローブパケットを送信し、ホストが起動しているかどうかを確認してください。
Pythonを試す前に、外部ツールNetcatを使用して接続性をテストしましょう。
$ nc 8.8.8.8 53 -zv
Connection to 8.8.8.8 53 port [tcp/domain] succeeded!
Netcatは、TCP/53を介して8.8.8.8
に到達できることを確認します。これで、Pythonの8.8.8.8:53/TCPへのソケット接続をセットアップして、接続を確認できます。
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のコメントのおかげで、タイムアウトは引数になり、デフォルトで3に初期化されます。
更新#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
HTMLが取得されないように、HEADリクエストを行う方が高速です。
また、グーグルはこの方法のほうが望ましいと確信しています:)
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
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との接続があることを保証することはできません。
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アドレスかどうかを尋ねます。役立つことを願っています
これを行う最善の方法は、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("")
これが私のバージョンです
import requests
try:
if requests.get('https://google.com').ok:
print("You're Online")
except:
print("You're Offline")
クラスター上でスクリプトを実行する場合としない場合の私のお気に入り
import subprocess
def online(timeout):
try:
return subprocess.run(
['wget', '-q', '--spider', 'google.com'],
timeout=timeout
).returncode == 0
except subprocess.TimeoutExpired:
return False
これはwgetを静かに実行し、何もダウンロードせずに、指定されたリモートファイルがWeb上に存在することを確認します
nutbu's answer を開始点とし、過去に「静的な」IPアドレスの変更によって焼かれたため、DNSルックアップを使用して1回チェックする単純なクラスを作成しました(つまり、 URL " https://www.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()
これは私にとって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")
Ivelin's answer を取得し、ルーターが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
Six 'の答えを取ると、どうにかして単純化できると思います。これは、非常に技術的な問題で新参者が失われるため、重要な問題です。
ここで、PV監視のために1日に1回接続(3G、低速)が確立されるのを待つために最終的に使用するもの。
Raspbian 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時間で試行しますが、もう少しスクリプトを実行します!