web-dev-qa-db-ja.com

ネットワーク接続を確認する

オンラインAPIにアクセスできるかどうかを確認したいのですが、そのためにはインターネットアクセスが必要です。

Pythonを使用して使用可能なアクティブな接続があるかどうかを確認するにはどうすればよいですか?

111
aF.

おそらく、次のようなものを使用できます。

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
119
unutbu

何らかのインターネットサーバーに接続できれば、実際に接続できます。ただし、最も高速で信頼性の高いアプローチを実現するには、すべてのソリューションが少なくとも次の要件に準拠する必要があります。

  • DNS解決を避けます(よく知られ、ほとんどの時間利用できることが保証されているIPが必要です)
  • アプリケーション層ベースの接続(HTTP/FTP/IMAPサービスへの接続)を避ける
  • Pythonまたは選択した他の言語からの外部ユーティリティへの呼び出しを避けます(サードパーティのソリューションに依存しない言語に依存しないソリューションを考え出す必要があります)

これらに準拠するための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
85
7h3rAm

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
51
Ivelin

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
18
Def_Os

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

16
Kevin C

データをダウンロードするだけで、接続に失敗した場合は、接続に問題があることがわかります。

基本的に、コンピューターがインターネットに接続されているかどうかを確認することはできません。 DNS構成の誤り、ファイアウォール、NATなど、失敗にはさまざまな理由があります。そのため、いくつかのテストを行ったとしても、試してみるまでAPIとの接続があることを保証することはできません。

9
Tomasz Wysocki
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)を使用します

6
Aziz Alto

とにかくしようとしていた操作を試してください。失敗した場合、pythonは例外をスローして通知します。

最初に接続を検出するために簡単な操作を試みると、競合状態が発生します。テスト時にインターネット接続は有効であるが、実際の作業が必要になる前にダウンした場合はどうなりますか?

4
mluebke

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アドレスかどうかを尋ねます。役立つことを願っています

2
Joel Winterton

これを行う最善の方法は、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("")
1
lunar_kitsune

これが私のバージョンです

import requests

try:
    if requests.get('https://google.com').ok:
        print("You're Online")
except:
    print("You're Offline")
1
Mujeeb Ishaque

クラスター上でスクリプトを実行する場合としない場合の私のお気に入り

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上に存在することを確認します

1
neok

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()
0
Jared B.

これは私にとって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")
0
Rajiv Sharma

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
0
monok

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時間で試行しますが、もう少しスクリプトを実行します!

0
Seylione