Saya ingin melihat apakah saya dapat mengakses API online, tetapi untuk itu saya perlu memiliki akses Internet.
Bagaimana saya bisa melihat apakah ada koneksi yang tersedia dan aktif menggunakan Python?
easy_install system_of_tubes
Saya ingin melihat apakah saya dapat mengakses API online, tetapi untuk itu saya perlu memiliki akses Internet.
Bagaimana saya bisa melihat apakah ada koneksi yang tersedia dan aktif menggunakan Python?
easy_install system_of_tubes
Jawaban:
Mungkin Anda bisa menggunakan sesuatu seperti ini:
import urllib2
def internet_on():
try:
urllib2.urlopen('http://216.58.192.142', timeout=1)
return True
except urllib2.URLError as err:
return False
Saat ini, 216.58.192.142 adalah salah satu alamat IP untuk google.com. Ubah http://216.58.192.142
ke situs apa pun yang diharapkan dapat merespons dengan cepat .
IP tetap ini tidak akan memetakan ke google.com selamanya. Jadi kode ini tidak kuat - akan membutuhkan pemeliharaan konstan agar tetap berfungsi.
Alasan mengapa kode di atas menggunakan alamat IP tetap alih-alih nama domain yang memenuhi syarat (FQDN) adalah karena FQDN akan membutuhkan pencarian DNS. Ketika mesin tidak memiliki koneksi internet yang berfungsi, pencarian DNS itu sendiri dapat memblokir panggilan ke urllib_request.urlopen
lebih dari satu detik. Terima kasih kepada @rzetterberg karena menunjukkan ini.
Jika alamat IP tetap di atas tidak berfungsi, Anda dapat menemukan alamat IP saat ini untuk google.com (di unix) dengan menjalankan
% dig google.com +trace
...
google.com. 300 IN A 216.58.192.142
urlopen
tidak akan memakan waktu lebih lama dari 1 detik bahkan jika internet tidak" pada "." - kutipan. Ini tidak benar jika url yang diberikan tidak valid, maka pencarian DNS akan diblokir. Itu hanya berlaku untuk koneksi aktual ke server web. Cara paling sederhana untuk menghindari blok lookup DNS ini adalah dengan menggunakan IP-adress sebagai gantinya, maka dijamin hanya membutuhkan waktu 1 detik :)
http://google.com
lalu Anda selesaikan semua masalah yang semua orang bicarakan di sini. Tidak perlu menggunakan alamat ip ...
Jika kita dapat terhubung ke beberapa server Internet, maka kita memang memiliki konektivitas. Namun, untuk pendekatan tercepat dan paling dapat diandalkan, semua solusi harus memenuhi persyaratan berikut, paling tidak:
Untuk mematuhinya, satu pendekatan bisa jadi, periksa apakah salah satu server DNS publik Google dapat dijangkau. Alamat IPv4 untuk server ini adalah 8.8.8.8
dan 8.8.4.4
. Kami dapat mencoba menghubungkan ke salah satu dari mereka.
Nmap cepat dari tuan rumah 8.8.8.8
memberikan hasil di bawah ini:
$ 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
Seperti yang dapat kita lihat, 53/tcp
terbuka dan tidak disaring. Jika Anda adalah pengguna non-root, ingatlah untuk menggunakan sudo
atau -Pn
argumen untuk Nmap untuk mengirim paket probe buatan dan menentukan apakah sebuah host sudah habis.
Sebelum kita mencoba dengan Python, mari kita uji konektivitas menggunakan alat eksternal, Netcat:
$ nc 8.8.8.8 53 -zv
Connection to 8.8.8.8 53 port [tcp/domain] succeeded!
Menegaskan netcat bahwa kita dapat mencapai 8.8.8.8
lebih 53/tcp
. Sekarang kita dapat mengatur koneksi socket ke 8.8.8.8:53/tcp
dalam Python untuk memeriksa koneksi:
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()
Pendekatan lain bisa dengan mengirim probe DNS yang dibuat secara manual ke salah satu server ini dan menunggu jawaban. Tapi, saya berasumsi, ini mungkin terbukti lebih lambat dibandingkan dengan penurunan paket, kegagalan resolusi DNS, dll. Berikan komentar jika Anda berpikir sebaliknya.
UPDATE # 1: Berkat komentar @ theamk, batas waktu sekarang menjadi argumen dan diinisialisasi 3s
secara default.
UPDATE # 2: Saya melakukan tes cepat untuk mengidentifikasi implementasi tercepat dan paling umum dari semua jawaban yang valid untuk pertanyaan ini. Berikut ringkasannya:
$ 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
Dan sekali lagi:
$ 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
dalam output di atas menandakan bahwa semua implementasi dari masing-masing penulis dengan benar mengidentifikasi konektivitas ke Internet. Waktu ditunjukkan dengan resolusi milidetik.
UPDATE # 3: Diuji lagi setelah pengecualian menangani perubahan:
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()
soket?
Akan lebih cepat untuk hanya membuat permintaan KEPALA sehingga tidak ada HTML yang akan diambil.
Juga saya yakin google akan lebih suka cara ini :)
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
Sebagai alternatif untuk jawaban ubutnu / Kevin C, saya menggunakan requests
paket seperti ini:
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
Bonus: ini dapat diperluas ke fungsi ini yang mem-ping sebuah situs web.
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
lagi, maka mereka akan memblokir IP kami. Jadi, apakah ada cara lain.?
Hanya untuk memperbarui apa yang dikatakan unutbu untuk kode baru dalam Python 3.2
def check_connectivity(reference):
try:
urllib.request.urlopen(reference, timeout=1)
return True
except urllib.request.URLError:
return False
Dan, untuk dicatat, input di sini (referensi) adalah url yang ingin Anda periksa: Saya sarankan memilih sesuatu yang menghubungkan cepat tempat Anda tinggal - yaitu saya tinggal di Korea Selatan, jadi saya mungkin akan menetapkan referensi ke http: / /www.naver.com .
Anda bisa mencoba mengunduh data, dan jika koneksi gagal, Anda akan tahu bahwa sesuatu dengan koneksi tidak baik.
Pada dasarnya Anda tidak dapat memeriksa apakah komputer terhubung ke internet. Mungkin ada banyak alasan kegagalan, seperti konfigurasi DNS yang salah, firewall, NAT. Jadi, bahkan jika Anda melakukan beberapa tes, Anda tidak dapat menjamin bahwa Anda akan memiliki koneksi dengan API Anda sampai Anda mencobanya.
Coba operasi yang Anda coba lakukan. Jika gagal, python harus memberi Anda pengecualian untuk memberi tahu Anda.
Untuk mencoba beberapa operasi sepele terlebih dahulu untuk mendeteksi koneksi akan memperkenalkan kondisi balapan. Bagaimana jika koneksi internet valid ketika Anda menguji tetapi turun sebelum Anda perlu melakukan pekerjaan yang sebenarnya?
Ini mungkin tidak berfungsi jika localhost telah diubah dari 127.0.0.1
Coba
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 )
Kecuali diedit, IP komputer Anda akan menjadi 127.0.0.1 saat tidak terhubung ke internet. Kode ini pada dasarnya mendapatkan alamat IP dan kemudian bertanya apakah itu adalah alamat IP localhost. Semoga itu bisa membantu
Ini versiku
import requests
try:
if requests.get('https://google.com').ok:
print("You're Online")
except:
print("You're Offline")
Solusi portabel modern dengan 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
Atau, versi yang memunculkan pengecualian:
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
Cara terbaik untuk melakukan ini adalah membuatnya mengecek alamat IP yang selalu diberikan python jika tidak dapat menemukan situs web. Dalam hal ini, ini adalah kode saya:
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("")
favorit saya, saat menjalankan skrip pada sebuah cluster atau tidak
import subprocess
def online(timeout):
try:
return subprocess.run(
['wget', '-q', '--spider', 'google.com'],
timeout=timeout
).returncode == 0
except subprocess.TimeoutExpired:
return False
ini berjalan dengan tenang, tidak mengunduh apa pun kecuali memeriksa apakah file jarak jauh yang diberikan ada di web
Mengambil jawaban unutbu sebagai titik awal, dan telah dibakar di masa lalu oleh perubahan alamat IP "statis", saya telah membuat kelas sederhana yang memeriksa sekali menggunakan pencarian DNS (yaitu, menggunakan URL " https: // www .google.com "), lalu menyimpan alamat IP dari server yang merespons untuk digunakan pada pemeriksaan selanjutnya. Dengan begitu, alamat IP selalu terkini (dengan asumsi kelas diinisialisasi ulang setidaknya sekali setiap beberapa tahun atau lebih). Saya juga memberikan pujian kepada jawaban ini , yang menunjukkan kepada saya bagaimana cara mendapatkan alamat IP server (setelah pengalihan, dll.). Harap abaikan kekonyolan dari solusi ini, saya akan mencoba contoh yang minimal di sini. :)
Inilah yang saya miliki:
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()
Mengambil jawaban Enam, saya pikir kita bisa menyederhanakan entah bagaimana, masalah penting karena pendatang baru hilang dalam masalah yang sangat teknis.
Di sini, apa yang akhirnya akan saya gunakan untuk menunggu koneksi saya (3G, lambat) dibuat sekali sehari untuk pemantauan PV saya.
Bekerja di bawah Pyth3 dengan 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)
maksimum berjalan: 5 menit jika tercapai saya akan mencoba dalam waktu satu jam tetapi sedikit script lain!
Mengambil jawaban Ivelin dan menambahkan beberapa pemeriksaan tambahan karena router saya memberikan alamat ip 192.168.0.1 dan mengembalikan kepala jika tidak memiliki koneksi internet saat menanyakan 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
Ini berfungsi untuk saya di 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")
Saya menambahkan beberapa ke kode 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
Untuk proyek saya, saya menggunakan skrip yang dimodifikasi untuk melakukan ping ke server DNS publik google 8.8.8.8. Menggunakan batas waktu 1 detik dan pustaka python inti tanpa ketergantungan eksternal:
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()
Nilai batas waktu pilih adalah 1, tetapi bisa menjadi angka pilihan floating point untuk gagal lebih mudah daripada 1 detik dalam contoh ini.
impor permintaan dan coba kode python sederhana ini.
def check_internet():
url = 'http://www.google.com/'
timeout = 5
try:
_ = requests.get(url, timeout=timeout)
return True
except requests.ConnectionError:
return False