Ping một trang web bằng Python?


80

Làm cách nào để ping một trang web hoặc địa chỉ IP bằng Python?


2
Hãy xác định "ping". Ý của bạn là sử dụng giao thức ping ICMP hay xem máy chủ web có đang chạy không? Hay cái gì khác?
S.Lott

này tỏ ra hữu ích hơn cho một vấn đề tôi đã giải quyết: stackoverflow.com/questions/3764291/checking-network-connection
jedierikb

1
đây là triển khai của python thuần túy: falatic.com/index.php/39/pinging-with-python
thinker007

Câu trả lời:


82

Xem ping Python thuần túy này của Matthew Dixon CowlesJens Diemer . Ngoài ra, hãy nhớ rằng Python yêu cầu root để tạo ra các socket ICMP (tức là ping) trong linux.

import ping, socket
try:
    ping.verbose_ping('www.google.com', count=3)
    delay = ping.Ping('www.wikipedia.org', timeout=2000).do()
except socket.error, e:
    print "Ping Error:", e

Bản thân mã nguồn rất dễ đọc, xem việc triển khai verbose_pingPing.dolấy cảm hứng.


4
pingsử dụng time.clockkhông mang lại bất cứ điều gì hữu ích trên hộp Linux của tôi. timeit.default_timer(nó bằng time.timetrên máy của tôi) hoạt động. time.clock-> timeit.default_timer gist.github.com/255009
JFS

@Vinicius - cảm ơn! Đã cập nhật vị trí mới trên github. Có vẻ như nó cũng được duy trì liên tục!
orip

3
ping không có phương thức nào được gọi là do_one. Tôi không thể tìm thấy cách đơn giản để lấy thời gian ping.
Joseph Turian

1
'run' đã được đổi tên thành 'count'
pferate

1
@ChrisWithers tệp nhị phân 'ping' chạy dưới dạng root thông qua bit 'setuid'. superuser.com/a/1035983/4706
ban đầu

42

Tùy thuộc vào những gì bạn muốn đạt được, bạn có thể dễ dàng nhất gọi lệnh ping hệ thống ..

Sử dụng mô-đun quy trình con là cách tốt nhất để làm điều này, mặc dù bạn phải nhớ lệnh ping khác nhau trên các hệ điều hành khác nhau!

import subprocess

host = "www.google.com"

ping = subprocess.Popen(
    ["ping", "-c", "4", host],
    stdout = subprocess.PIPE,
    stderr = subprocess.PIPE
)

out, error = ping.communicate()
print out

Bạn không cần phải lo lắng về các ký tự thoát shell. Ví dụ..

host = "google.com; `echo test`

..sẽ không thực hiện lệnh echo.

Bây giờ, để thực sự nhận được kết quả ping, bạn có thể phân tích cú pháp outbiến. Ví dụ đầu ra:

round-trip min/avg/max/stddev = 248.139/249.474/250.530/0.896 ms

Ví dụ regex:

import re
matcher = re.compile("round-trip min/avg/max/stddev = (\d+.\d+)/(\d+.\d+)/(\d+.\d+)/(\d+.\d+)")
print matcher.search(out).groups()

# ('248.139', '249.474', '250.530', '0.896')

Một lần nữa, hãy nhớ đầu ra sẽ khác nhau tùy thuộc vào hệ điều hành (và thậm chí cả phiên bản của ping). Điều này không phải là lý tưởng, nhưng nó sẽ hoạt động tốt trong nhiều tình huống (nơi bạn biết các máy mà tập lệnh sẽ chạy)


Tôi thấy rằng tôi đã phải chỉnh sửa biểu thức đối sánh regex của bạn vì outhàm chứa được mã hóa \ n có vẻ như cản trở việc đối sánh:matcher = re.compile("\nround-trip min/avg/max/stddev = (\d+.\d+)/(\d+.\d+)/(\d+.\d+)/(\d+.\d+)")
Pierz


Trên Windows, bạn nên sử dụng -nthay vì -c. ( Câu trả lời Xem ePi272314 của )
Stevoisiak

39

Bạn có thể tìm thấy bài thuyết trình của Noah Gift Tạo các công cụ dòng lệnh nhanh nhẹn với Python . Trong đó, ông kết hợp quy trình con, hàng đợi và phân luồng để phát triển giải pháp có khả năng ping các máy chủ đồng thời và tăng tốc quá trình. Dưới đây là phiên bản cơ bản trước khi anh ấy thêm phân tích cú pháp dòng lệnh và một số tính năng khác. Có thể tìm thấy mã của phiên bản này và các phiên bản khác tại đây

#!/usr/bin/env python2.5
from threading import Thread
import subprocess
from Queue import Queue

num_threads = 4
queue = Queue()
ips = ["10.0.1.1", "10.0.1.3", "10.0.1.11", "10.0.1.51"]
#wraps system ping command
def pinger(i, q):
    """Pings subnet"""
    while True:
        ip = q.get()
        print "Thread %s: Pinging %s" % (i, ip)
        ret = subprocess.call("ping -c 1 %s" % ip,
            shell=True,
            stdout=open('/dev/null', 'w'),
            stderr=subprocess.STDOUT)
        if ret == 0:
            print "%s: is alive" % ip
        else:
            print "%s: did not respond" % ip
        q.task_done()
#Spawn thread pool
for i in range(num_threads):

    worker = Thread(target=pinger, args=(i, queue))
    worker.setDaemon(True)
    worker.start()
#Place work in queue
for ip in ips:
    queue.put(ip)
#Wait until worker threads are done to exit    
queue.join()

Ông cũng là tác giả của: Python for Unix và Linux System Administration

http://ecx.images-amazon.com/images/I/515qmR%2B4sjL._SL500_AA240_.jpg


4
Không biết rằng điều này thực sự trả lời câu hỏi, nhưng nó là thông tin rất hữu ích!
ig0774,

Tôi biết nó đến từ PyCon ... nhưng nó khá tệ. Thực hiện các cuộc gọi hệ thống là một sự lãng phí thời gian và tài nguyên, đồng thời phụ thuộc vào hệ thống và khó phân tích cú pháp. Bạn nên chọn một phương thức sử dụng Python để gửi / nhận các yêu cầu ICMP, vì có những phương thức khác trên chuỗi này.
Cukic0d

9

Thật khó để nói câu hỏi của bạn là gì, nhưng có một số lựa chọn thay thế.

Nếu bạn muốn thực hiện một yêu cầu theo nghĩa đen bằng giao thức ping ICMP, bạn có thể lấy thư viện ICMP và thực hiện yêu cầu ping trực tiếp. Google "Python ICMP" để tìm những thứ như icmplib này . Bạn cũng có thể muốn nhìn vào scpy .

Điều này sẽ nhanh hơn nhiều so với sử dụng os.system("ping " + ip ).

Nếu bạn muốn "ping" một hộp nói chung để xem nó có lên hay không, bạn có thể sử dụng giao thức echo trên cổng 7.

Đối với echo, bạn sử dụng thư viện socket để mở địa chỉ IP và cổng 7. Bạn viết một cái gì đó trên cổng đó, gửi một ký tự xuống dòng ( "\r\n") và sau đó đọc câu trả lời.

Nếu bạn muốn "ping" một trang web để xem trang đó có đang chạy hay không, bạn phải sử dụng giao thức http trên cổng 80.

Để kiểm tra hoặc kiểm tra chính xác máy chủ web, bạn sử dụng urllib2 để mở một URL cụ thể. ( /index.htmlluôn luôn phổ biến) và đọc phản hồi.

Vẫn còn nhiều ý nghĩa tiềm năng hơn của "ping" bao gồm "traceroute" và "ngón tay".


5
echo đã từng phổ biến nhưng giờ nó bị vô hiệu hóa theo mặc định trên hầu hết các hệ thống. Vì vậy, nó không phải là một cách thực tế để kiểm tra xem máy chạy tốt hay không.
bortzmeyer

8

Tôi đã làm điều gì đó tương tự theo cách này, như một nguồn cảm hứng:

import urllib
import threading
import time

def pinger_urllib(host):
  """
  helper function timing the retrival of index.html 
  TODO: should there be a 1MB bogus file?
  """
  t1 = time.time()
  urllib.urlopen(host + '/index.html').read()
  return (time.time() - t1) * 1000.0


def task(m):
  """
  the actual task
  """
  delay = float(pinger_urllib(m))
  print '%-30s %5.0f [ms]' % (m, delay)

# parallelization
tasks = []
URLs = ['google.com', 'wikipedia.org']
for m in URLs:
  t = threading.Thread(target=task, args=(m,))
  t.start()
  tasks.append(t)

# synchronization point
for t in tasks:
  t.join()

1
vui mừng bạn ở xa thư viện bên ngoài vàsubprocess
tshepang

Điều gì xảy ra nếu không có index.html?
sbose

4
Quan trọng hơn, nếu không có máy chủ web thì sao?
Kim Gräsman 17/02/15

Thật vậy, không cần phải nối điều đó /index.html; trong bất kỳ trang web nào thực sự có một tài liệu được gọi index.html, nó sẽ ở ngay đó, trong thư mục gốc của máy chủ. Thay vào đó bạn muốn thêm vào trước http:// hoặc https://để lưu trữ
Antti Haapala

Mặc dù đây không thực sự là ICMP ping nhiều như kiểm tra "ping" + HTTP cổng TCP 80, nhưng có lẽ tốt hơn nên thực hiện yêu cầu HEAD (hoặc OPTIONS) vì bạn sẽ không thực sự nhận được bất kỳ nội dung nào, do đó băng thông sẽ ảnh hưởng đến nó ít hơn. Nếu bạn muốn thứ gì đó rảnh rỗi hơn, bạn có thể thử mở một ổ cắm TCP 80 cho máy chủ và đóng nó ngay lập tức.
Nick T

6

Đây là một đoạn ngắn sử dụng subprocess. Các check_callphương pháp hoặc là trả về 0 cho sự thành công, hoặc đặt ra một ngoại lệ. Bằng cách này, tôi không phải phân tích cú pháp đầu ra của ping. Tôi đang sử dụng shlexđể tách các đối số dòng lệnh.

  import subprocess
  import shlex

  command_line = "ping -c 1 www.google.comsldjkflksj"
  args = shlex.split(command_line)
  try:
      subprocess.check_call(args,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
      print "Website is there."
  except subprocess.CalledProcessError:
      print "Couldn't get a ping."

3
Cảnh báo: không làm việc trên cửa sổ ( -c-nở đó, và logic về mã trở lại là khác nhau)
wim

3

đọc tên tệp, tệp chứa một url trên mỗi dòng, như sau:

http://www.poolsaboveground.com/apache/hadoop/core/
http://mirrors.sonic.net/apache/hadoop/core/

sử dụng lệnh:

python url.py urls.txt

nhận được kết quả:

Round Trip Time: 253 ms - mirrors.sonic.net
Round Trip Time: 245 ms - www.globalish.com
Round Trip Time: 327 ms - www.poolsaboveground.com

mã nguồn (url.py):

import re
import sys
import urlparse
from subprocess import Popen, PIPE
from threading import Thread


class Pinger(object):
    def __init__(self, hosts):
        for host in hosts:
            hostname = urlparse.urlparse(host).hostname
            if hostname:
                pa = PingAgent(hostname)
                pa.start()
            else:
                continue

class PingAgent(Thread):
    def __init__(self, host):
        Thread.__init__(self)        
        self.host = host

    def run(self):
        p = Popen('ping -n 1 ' + self.host, stdout=PIPE)
        m = re.search('Average = (.*)ms', p.stdout.read())
        if m: print 'Round Trip Time: %s ms -' % m.group(1), self.host
        else: print 'Error: Invalid Response -', self.host


if __name__ == '__main__':
    with open(sys.argv[1]) as f:
        content = f.readlines() 
    Pinger(content)

2
import subprocess as s
ip=raw_input("Enter the IP/Domain name:")
if(s.call(["ping",ip])==0):
    print "your IP is alive"
else:
    print "Check ur IP"

2

Nếu bạn muốn một thứ gì đó thực sự bằng Python mà bạn có thể chơi, hãy xem Scapy:

from scapy.all import *
request = IP(dst="www.google.com")/ICMP()
answer = sr1(request)

Theo ý kiến ​​của tôi, điều đó tốt hơn nhiều (và hoàn toàn đa nền tảng), so với một số lệnh gọi quy trình con sôi nổi. Ngoài ra, bạn có thể có nhiều thông tin về câu trả lời (ID trình tự .....) như bạn muốn, vì bạn có chính gói tin.


2

Câu trả lời đơn giản nhất là:

import os
os.system("ping google.com") 

1

Bạn có thể tìm thấy phiên bản cập nhật của tập lệnh được đề cập hoạt động trên cả Windows và Linux tại đây


Mã liên kết không thành công trên Python 3.8. "Lỗi Cú pháp: cú pháp không hợp lệ"
Stevoisiak

0

sử dụng lệnh ping hệ thống để ping danh sách các máy chủ:

import re
from subprocess import Popen, PIPE
from threading import Thread


class Pinger(object):
    def __init__(self, hosts):
        for host in hosts:
            pa = PingAgent(host)
            pa.start()

class PingAgent(Thread):
    def __init__(self, host):
        Thread.__init__(self)        
        self.host = host

    def run(self):
        p = Popen('ping -n 1 ' + self.host, stdout=PIPE)
        m = re.search('Average = (.*)ms', p.stdout.read())
        if m: print 'Round Trip Time: %s ms -' % m.group(1), self.host
        else: print 'Error: Invalid Response -', self.host


if __name__ == '__main__':
    hosts = [
        'www.pylot.org',
        'www.goldb.org',
        'www.google.com',
        'www.yahoo.com',
        'www.techcrunch.com',
        'www.this_one_wont_work.com'
       ]
    Pinger(hosts)

6
Tôi sẽ đăng ký www.this_one_wont_work.com chỉ để đá và cười khúc khích.
Matthew Scouten,

p = Popen('ping -n 1 ' + self.host, stdout=PIPE)Nên p = Popen(['ping','-n','1','self.host'], stdout=PIPE)
toc777

0

sử dụng lệnh ping của quy trình con để giải mã ping vì phản hồi là nhị phân:

import subprocess
ping_response = subprocess.Popen(["ping", "-a", "google.com"], stdout=subprocess.PIPE).stdout.read()
result = ping_response.decode('utf-8')
print(result)

0

bạn có thể thử socket để lấy ip của trang web và sử dụng scrapy để thực hiện ping icmp tới ip.

import gevent
from gevent import monkey
# monkey.patch_all() should be executed before any library that will
# standard library
monkey.patch_all()

import socket
from scapy.all import IP, ICMP, sr1


def ping_site(fqdn):
    ip = socket.gethostbyaddr(fqdn)[-1][0]
    print(fqdn, ip, '\n')
    icmp = IP(dst=ip)/ICMP()
    resp = sr1(icmp, timeout=10)
    if resp:
        return (fqdn, False)
    else:
        return (fqdn, True)


sites = ['www.google.com', 'www.baidu.com', 'www.bing.com']
jobs = [gevent.spawn(ping_site, fqdn) for fqdn in sites]
gevent.joinall(jobs)
print([job.value for job in jobs])

0

Tôi phát triển một thư viện mà tôi nghĩ có thể giúp bạn. Nó được gọi là icmplib (không liên quan đến bất kỳ mã nào khác cùng tên có thể tìm thấy trên Internet) và là một triển khai thuần túy của giao thức ICMP bằng Python.

Nó hoàn toàn hướng đối tượng và có các chức năng đơn giản như ping, multiping và traceroute cổ điển, cũng như các lớp và ổ cắm cấp thấp cho những ai muốn phát triển ứng dụng dựa trên giao thức ICMP.

Dưới đây là một số điểm nổi bật khác:

  • Có thể chạy mà không cần quyền root.
  • Bạn có thể tùy chỉnh nhiều tham số như tải trọng của gói ICMP và lớp lưu lượng (QoS).
  • Đa nền tảng: được thử nghiệm trên Linux, macOS và Windows.
  • Nhanh chóng và yêu cầu ít tài nguyên CPU / RAM không giống như các cuộc gọi được thực hiện bằng quy trình con.
  • Nhẹ và không dựa vào bất kỳ phụ thuộc bổ sung nào.

Để cài đặt nó (yêu cầu Python 3.6+):

pip3 install icmplib

Đây là một ví dụ đơn giản về hàm ping:

host = ping('1.1.1.1', count=4, interval=1, timeout=2, privileged=True)

if host.is_alive:
    print(f'{host.address} is alive! avg_rtt={host.avg_rtt} ms')
else:
    print(f'{host.address} is dead')

Đặt tham số "đặc quyền" thành Sai nếu bạn muốn sử dụng thư viện mà không có đặc quyền gốc.

Bạn có thể tìm thấy tài liệu đầy đủ trên trang dự án: https://github.com/ValentinBELYN/icmplib

Hy vọng bạn sẽ thấy thư viện này hữu ích.


2
Lưu ý của người điều hành : câu trả lời này tuân theo các yêu cầu của chúng tôi về tự quảng cáo , không phải là không được yêu cầu (câu hỏi yêu cầu giải pháp Python để sử dụng ping) và do đó, không phảispam theo định nghĩa của chúng tôi về thuật ngữ này.
Martijn Pieters

-1

Sử dụng điều này, nó đã được thử nghiệm trên python 2.7 và hoạt động tốt, nó trả về thời gian ping tính bằng mili giây nếu thành công và trả về False khi thất bại.

import platform,subproccess,re
def Ping(hostname,timeout):
    if platform.system() == "Windows":
        command="ping "+hostname+" -n 1 -w "+str(timeout*1000)
    else:
        command="ping -i "+str(timeout)+" -c 1 " + hostname
    proccess = subprocess.Popen(command, stdout=subprocess.PIPE)
    matches=re.match('.*time=([0-9]+)ms.*', proccess.stdout.read(),re.DOTALL)
    if matches:
        return matches.group(1)
    else: 
        return False

1
Không thành công trên Python 3.6. ModuleNotFoundError: Không có mô-đun có tên là 'subproccess'
Stevoisiak

Cũng không thành công vì commandlà một chuỗi bao gồm tất cả các đối số thay vì một danh sách để kích hoạt command not foundchuỗi đầy đủ trên Linux.
mình
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.