ฉันต้องการดูว่าฉันสามารถเข้าถึง API ออนไลน์ได้หรือไม่ แต่ฉันต้องเข้าถึงอินเทอร์เน็ตได้
ฉันจะดูได้อย่างไรว่ามีการเชื่อมต่อและใช้งานได้โดยใช้ Python
ฉันต้องการดูว่าฉันสามารถเข้าถึง 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 เป็นหนึ่งในที่อยู่ IP สำหรับ google.com เปลี่ยนhttp://216.58.192.142
เพื่อสิ่งที่เว็บไซต์คาดว่าจะสามารถตอบสนองอย่างรวดเร็ว
IP คงที่นี้จะไม่จับคู่กับ google.com ตลอดไป ดังนั้นรหัสนี้จึงไม่แข็งแรง - จำเป็นต้องมีการบำรุงรักษาอย่างต่อเนื่องเพื่อให้ใช้งานได้
สาเหตุที่โค้ดด้านบนใช้ที่อยู่ IP แบบคงที่แทนชื่อโดเมนแบบเต็ม (FQDN) เนื่องจาก FQDN ต้องการการค้นหา DNS เมื่อเครื่องไม่มีการเชื่อมต่ออินเทอร์เน็ตที่ใช้งานได้การค้นหา DNS เองอาจบล็อกการโทรไปurllib_request.urlopen
นานกว่าหนึ่งวินาที ขอบคุณ @rzetterberg ที่ชี้ให้เห็นสิ่งนี้
หากที่อยู่ IP คงที่ด้านบนไม่ทำงานคุณสามารถค้นหาที่อยู่ IP ปัจจุบันสำหรับ google.com (บน unix) ได้โดยเรียกใช้
% dig google.com +trace
...
google.com. 300 IN A 216.58.192.142
urlopen
จะใช้เวลาไม่นานเกิน 1 วินาทีแม้ว่าอินเทอร์เน็ตจะไม่" เปิด "ก็ตาม - คำพูด สิ่งนี้ไม่เป็นความจริงหาก url ที่ให้มาไม่ถูกต้องการค้นหา DNS จะบล็อก เป็นจริงสำหรับการเชื่อมต่อกับเว็บเซิร์ฟเวอร์จริงเท่านั้น วิธีที่ง่ายที่สุดในการหลีกเลี่ยงบล็อกการค้นหา DNS นี้คือใช้ที่อยู่ IP แทนจากนั้นรับประกันว่าจะใช้เวลาเพียง 1 วินาที :)
http://google.com
แล้วคุณก็แก้ปัญหาที่ทุกคนพูดถึงที่นี่ ไม่จำเป็นต้องใช้ที่อยู่ IP ...
หากเราสามารถเชื่อมต่อกับเซิร์ฟเวอร์อินเทอร์เน็ตได้แสดงว่าเรามีการเชื่อมต่ออย่างแน่นอน อย่างไรก็ตามเพื่อแนวทางที่รวดเร็วและน่าเชื่อถือที่สุดโซลูชันทั้งหมดควรเป็นไปตามข้อกำหนดต่อไปนี้อย่างน้อยที่สุด:
เพื่อให้เป็นไปตามนี้แนวทางหนึ่งคือตรวจสอบว่าเซิร์ฟเวอร์ DNS สาธารณะของ Googleสามารถเข้าถึงได้หรือไม่ ที่อยู่ 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
คือเปิดและไม่มีการกรอง หากคุณเป็นผู้ใช้ที่ไม่ใช่รูทอย่าลืมใช้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 ที่สร้างขึ้นเองไปยังเซิร์ฟเวอร์เหล่านี้และรอการตอบกลับ แต่ฉันคิดว่ามันอาจพิสูจน์ได้ช้ากว่าในการเปรียบเทียบเนื่องจากแพ็คเก็ตลดลงการแก้ปัญหา 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
นอกจากนี้ฉันแน่ใจว่า Google ต้องการให้ดีกว่านี้ :)
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 / 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
โบนัส: สามารถขยายไปยังฟังก์ชันนี้ที่ส่ง 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 ของเรา มีวิธีอื่นไหม.?
เพียงเพื่ออัปเดตสิ่งที่ unutbu กล่าวสำหรับโค้ดใหม่ใน Python 3.2
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 ของ localhost หรือไม่ หวังว่าจะช่วยได้
นี่คือเวอร์ชันของฉัน
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
วิธีที่ดีที่สุดคือตรวจสอบกับที่อยู่ IP ที่ python ให้ไว้เสมอหากไม่พบเว็บไซต์ ในกรณีนี้นี่คือรหัสของฉัน:
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 subprocess
def online(timeout):
try:
return subprocess.run(
['wget', '-q', '--spider', 'google.com'],
timeout=timeout
).returncode == 0
except subprocess.TimeoutExpired:
return False
สิ่งนี้ทำงานอย่างเงียบ ๆ ไม่ดาวน์โหลดอะไรเลยนอกจากตรวจสอบว่ามีไฟล์ระยะไกลที่ระบุอยู่บนเว็บ
การใช้คำตอบของ unutbuเป็นจุดเริ่มต้นและในอดีตเคยถูกเบิร์นโดยการเปลี่ยนที่อยู่ IP "คงที่" ฉันได้สร้างคลาสง่ายๆที่ตรวจสอบครั้งเดียวโดยใช้การค้นหา DNS (เช่นใช้ URL " https: // www .google.com ") แล้วจัดเก็บที่อยู่ IP ของเซิร์ฟเวอร์ที่ตอบสนองเพื่อใช้ในการตรวจสอบในภายหลัง ด้วยวิธีนี้ที่อยู่ IP จะเป็นปัจจุบันอยู่เสมอ (โดยสมมติว่าคลาสนั้นได้รับการเริ่มต้นใหม่อย่างน้อยหนึ่งครั้งในทุกๆสองสามปี) ฉันยังให้เครดิตกับ 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()
การตอบคำถามหกข้อฉันคิดว่าเราสามารถทำให้ง่ายขึ้นได้ปัญหาที่สำคัญเนื่องจากผู้มาใหม่จะหลงทางในเรื่องทางเทคนิคขั้นสูง
ต่อไปนี้คือสิ่งที่ฉันจะใช้เพื่อรอการเชื่อมต่อ (3G ช้า) วันละครั้งสำหรับการตรวจสอบ PV ของฉัน
ทำงานภายใต้ Pyth3 กับ 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)
วิ่งสูงสุด: 5 นาทีหากไปถึงฉันจะพยายามในเวลาหนึ่งชั่วโมง แต่เป็นสคริปต์อีกเล็กน้อย!
การตอบ Ivelin ของและเพิ่มบางตรวจสอบเป็นพิเศษเราเตอร์ของฉันให้อยู่ 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
สิ่งนี้ใช้ได้กับฉันใน 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
สำหรับโครงการของฉันฉันใช้สคริปต์ที่แก้ไขเพื่อ ping เซิร์ฟเวอร์ DNS สาธารณะของ Google 8.8.8.8 ใช้การหมดเวลา 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 วินาทีในตัวอย่างนี้
ตรวจสอบให้แน่ใจว่า pip ของคุณทันสมัยโดยการเรียกใช้
pip install --upgrade pip
ติดตั้งแพ็คเกจการร้องขอโดยใช้
pip install requests
import requests
import webbrowser
url = "http://www.youtube.com"
timeout = 6
try:
request = requests.get(url, timeout=timeout)
print("Connected to the Internet")
print("browser is loading url")
webbrowser.open(url)
except (requests.ConnectionError, requests.Timeout) as exception:
print("poor or no internet connection.")
คำขอนำเข้าและลองใช้รหัส python แบบธรรมดานี้
def check_internet():
url = 'http://www.google.com/'
timeout = 5
try:
_ = requests.get(url, timeout=timeout)
return True
except requests.ConnectionError:
return False