Tôi muốn xem liệu tôi có thể truy cập API trực tuyến hay không, nhưng tôi cần phải có quyền truy cập Internet.
Làm cách nào để biết liệu có kết nối khả dụng và hoạt động bằng Python không?
easy_install system_of_tubes
Tôi muốn xem liệu tôi có thể truy cập API trực tuyến hay không, nhưng tôi cần phải có quyền truy cập Internet.
Làm cách nào để biết liệu có kết nối khả dụng và hoạt động bằng Python không?
easy_install system_of_tubes
Câu trả lời:
Có lẽ bạn có thể sử dụng một cái gì đó như thế này:
import urllib2
def internet_on():
try:
urllib2.urlopen('http://216.58.192.142', timeout=1)
return True
except urllib2.URLError as err:
return False
Hiện tại, 216.58.192.142 là một trong những địa chỉ IP cho google.com. Thay đổi http://216.58.192.142
bất cứ điều gì trang web có thể được mong đợi để đáp ứng nhanh chóng .
IP cố định này sẽ không ánh xạ tới google.com mãi mãi. Vì vậy, mã này không mạnh mẽ - nó sẽ cần bảo trì liên tục để giữ cho nó hoạt động.
Lý do tại sao mã ở trên sử dụng một địa chỉ IP cố định thay vì tên miền đủ điều kiện (FQDN) là vì FQDN sẽ yêu cầu tra cứu DNS. Khi máy không có kết nối internet đang hoạt động, bản thân việc tra cứu DNS có thể chặn cuộc gọi urllib_request.urlopen
trong hơn một giây. Cảm ơn @rzetterberg đã chỉ ra điều này.
Nếu địa chỉ IP cố định ở trên không hoạt động, bạn có thể tìm địa chỉ IP hiện tại cho google.com (trên unix) bằng cách chạy
% dig google.com +trace
...
google.com. 300 IN A 216.58.192.142
urlopen
sẽ không mất nhiều hơn 1 giây ngay cả khi internet không" bật "." - trích dẫn. Điều này không đúng nếu url được cung cấp không hợp lệ, khi đó việc tra cứu DNS sẽ bị chặn. Nó chỉ đúng với kết nối thực tế với máy chủ web. Cách đơn giản nhất để tránh khối tra cứu DNS này là sử dụng địa chỉ IP thay vào đó, sau đó đảm bảo chỉ mất 1 giây :)
http://google.com
và sau đó bạn giải quyết tất cả các vấn đề mà mọi người cứ nói ở đây. Không cần sử dụng địa chỉ IP ...
Nếu chúng ta có thể kết nối với một số máy chủ Internet, thì chúng ta thực sự có kết nối. Tuy nhiên, để có cách tiếp cận nhanh nhất và đáng tin cậy nhất, tất cả các giải pháp nên tuân thủ các yêu cầu sau, ít nhất là:
Để tuân thủ những điều này, một cách tiếp cận có thể là, kiểm tra xem một trong các máy chủ DNS công cộng của Google có thể truy cập được không. Các địa chỉ IPv4 cho các máy chủ này là 8.8.8.8
và 8.8.4.4
. Chúng tôi có thể thử kết nối với bất kỳ trong số họ.
Một Nmap nhanh của máy chủ 8.8.8.8
cho kết quả dưới đây:
$ 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
Như chúng ta có thể thấy, 53/tcp
là mở và không được lọc. Nếu bạn là người dùng không phải root, hãy nhớ sử dụng sudo
hoặc -Pn
đối số cho Nmap để gửi các gói thăm dò được tạo thủ công và xác định xem máy chủ có hoạt động không.
Trước khi thử với Python, hãy kiểm tra kết nối bằng công cụ bên ngoài, Netcat:
$ nc 8.8.8.8 53 -zv
Connection to 8.8.8.8 53 port [tcp/domain] succeeded!
Xác nhân netcat rằng chúng ta có thể đạt được 8.8.8.8
qua 53/tcp
. Bây giờ chúng ta có thể thiết lập kết nối ổ cắm 8.8.8.8:53/tcp
trong Python để kiểm tra kết nối:
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()
Một cách tiếp cận khác có thể là gửi một đầu dò DNS được tạo thủ công đến một trong những máy chủ này và chờ phản hồi. Nhưng, tôi cho rằng, nó có thể chứng minh chậm hơn so với do giảm gói, lỗi độ phân giải DNS, v.v. Hãy bình luận nếu bạn nghĩ khác.
CẬP NHẬT # 1: Nhờ nhận xét của @ theamk, thời gian chờ hiện là đối số và được khởi tạo 3s
theo mặc định.
CẬP NHẬT # 2: Tôi đã làm các bài kiểm tra nhanh để xác định cách triển khai nhanh nhất và chung nhất cho tất cả các câu trả lời hợp lệ cho câu hỏi này. Đây là tóm tắt:
$ 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
Và một lần nữa:
$ 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
ở đầu ra trên biểu thị rằng tất cả các triển khai này từ các tác giả tương ứng xác định chính xác kết nối với Internet. Thời gian được hiển thị với độ phân giải mili giây.
CẬP NHẬT # 3: Đã kiểm tra lại sau khi thay đổi xử lý ngoại lệ:
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()
vào ổ cắm?
Sẽ nhanh hơn khi chỉ thực hiện một yêu cầu CHÍNH để không có HTML nào được tìm nạp.
Ngoài ra tôi chắc chắn google sẽ thích nó tốt hơn theo cách này :)
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
Thay thế cho câu trả lời của ubutnu's / Kevin C, tôi sử dụng requests
gói như thế này:
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
Phần thưởng: điều này có thể được mở rộng cho chức năng này ping trang 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
lại dồn nén một lần nữa, thì họ sẽ chặn IP của chúng tôi. Vì vậy, có cách nào khác.?
Chỉ cần cập nhật những gì unutbu đã nói cho mã mới trong Python 3.2
def check_connectivity(reference):
try:
urllib.request.urlopen(reference, timeout=1)
return True
except urllib.request.URLError:
return False
Và, chỉ cần lưu ý, đầu vào ở đây (tham chiếu) là url mà bạn muốn kiểm tra: Tôi khuyên bạn nên chọn thứ gì đó kết nối nhanh ở nơi bạn sống - tức là tôi sống ở Hàn Quốc, vì vậy tôi có thể đặt tham chiếu đến http: / /www.naver.com .
Bạn chỉ có thể thử tải xuống dữ liệu và nếu kết nối không thành công, bạn sẽ biết rằng đôi khi kết nối không ổn.
Về cơ bản, bạn không thể kiểm tra xem máy tính có được kết nối với internet không. Có thể có nhiều lý do cho sự thất bại, như cấu hình DNS sai, tường lửa, NAT. Vì vậy, ngay cả khi bạn thực hiện một số thử nghiệm, bạn không thể đảm bảo rằng bạn sẽ có kết nối với API cho đến khi bạn thử.
Hãy thử các hoạt động bạn đã cố gắng để làm anyway. Nếu nó không thành công, con trăn sẽ ném cho bạn một ngoại lệ để cho bạn biết.
Để thử một số hoạt động tầm thường trước tiên để phát hiện một kết nối sẽ đưa ra một điều kiện cuộc đua. Điều gì xảy ra nếu kết nối internet hợp lệ khi bạn kiểm tra nhưng bị hỏng trước khi bạn cần thực hiện công việc thực tế?
Điều này có thể không hoạt động nếu localhost đã được thay đổi từ 127.0.0.1
Thử
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 )
Trừ khi được chỉnh sửa, IP máy tính của bạn sẽ là 127.0.0.1 khi không được kết nối với internet. Mã này về cơ bản lấy địa chỉ IP và sau đó hỏi nếu đó là địa chỉ IP localhost. Mong rằng sẽ giúp
Đây là phiên bản của tôi
import requests
try:
if requests.get('https://google.com').ok:
print("You're Online")
except:
print("You're Offline")
Một giải pháp di động hiện đại với 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
Hoặc, một phiên bản đưa ra một ngoại lệ:
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
Cách tốt nhất để làm điều này là làm cho nó kiểm tra địa chỉ IP mà python luôn cung cấp nếu không thể tìm thấy trang web. Trong trường hợp này đây là mã của tôi:
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("")
yêu thích của tôi, khi chạy script trên một cụm hay không
import subprocess
def online(timeout):
try:
return subprocess.run(
['wget', '-q', '--spider', 'google.com'],
timeout=timeout
).returncode == 0
except subprocess.TimeoutExpired:
return False
Điều này chạy lặng lẽ, không tải xuống bất cứ thứ gì ngoài việc kiểm tra xem tệp từ xa đã cho có tồn tại trên web không
Lấy câu trả lời của unutbu làm điểm bắt đầu và đã bị đốt cháy trong quá khứ do thay đổi địa chỉ IP "tĩnh", tôi đã tạo một lớp đơn giản kiểm tra một lần bằng cách sử dụng tra cứu DNS (nghĩa là sử dụng URL " https: // www .google.com "), sau đó lưu địa chỉ IP của máy chủ phản hồi để sử dụng cho các lần kiểm tra tiếp theo. Bằng cách đó, địa chỉ IP luôn được cập nhật (giả sử lớp được khởi tạo lại ít nhất một vài năm một lần hoặc lâu hơn). Tôi cũng cung cấp tín dụng cho người đánh cá cho câu trả lời này , trong đó chỉ cho tôi cách lấy địa chỉ IP của máy chủ (sau khi chuyển hướng, v.v.). Xin vui lòng bỏ qua sự hack hack rõ ràng của giải pháp này, tôi sẽ lấy một ví dụ hoạt động tối thiểu ở đây. :)
Đây là những gì tôi có:
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()
Lấy câu trả lời của Six Tôi nghĩ rằng chúng ta có thể đơn giản hóa bằng cách nào đó, một vấn đề quan trọng vì những người mới đến bị mất trong các vấn đề kỹ thuật cao.
Ở đây, cuối cùng tôi sẽ sử dụng để chờ kết nối của mình (3G, chậm) được thiết lập mỗi ngày một lần để theo dõi PV của tôi.
Hoạt động theo Pyth3 với 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)
chạy tối đa: 5 phút nếu đạt được tôi sẽ thử trong một giờ nhưng đó là một đoạn script khác!
Lấy câu trả lời của Ivelin và thêm một số kiểm tra bổ sung vì bộ định tuyến của tôi cung cấp địa chỉ IP 192.168.0.1 và trả về một đầu nếu nó không có kết nối internet khi truy vấn 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
Điều này làm việc cho tôi trong 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")
Tôi đã thêm một vài mã của 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
Đối với các dự án của tôi, tôi sử dụng tập lệnh được sửa đổi để ping máy chủ DNS công cộng của Google 8.8.8.8. Sử dụng thời gian chờ là 1 giây và các thư viện python lõi không có phụ thuộc bên ngoài:
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()
Các chọn giá trị thời gian chờ là 1, nhưng có thể là một số điểm nổi của sự lựa chọn để thất bại dễ dàng hơn so với 1 giây trong ví dụ này.
nhập yêu cầu và thử mã python đơn giản này.
def check_internet():
url = 'http://www.google.com/'
timeout = 5
try:
_ = requests.get(url, timeout=timeout)
return True
except requests.ConnectionError:
return False