Пинговать сайт на Python?

Как проверить связь с веб-сайтом или IP-адресом с помощью Python?

Определите, пожалуйста, "пинг". Вы хотите использовать протокол ping ICMP или посмотреть, работает ли веб-сервер? Или что-то другое?

S.Lott 25.11.2008 14:13

это оказалось более полезным для проблемы, которую я решал: stackoverflow.com/questions/3764291/checking-network‌ -соединение

jedierikb 07.05.2012 21:16

вот реализация чистого питона: falatic.com/index.php/39/pinging-with-python

thinker007 19.05.2012 09:32
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
82
3
231 908
16

Ответы 16

В зависимости от того, чего вы хотите достичь, вам, вероятно, проще всего вызвать системную команду ping.

Использование модуля subprocess - лучший способ сделать это, хотя вы должны помнить, что команда ping отличается в разных операционных системах!

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

Вам не нужно беспокоиться о escape-символах оболочки. Например..

host = "google.com; `echo test`

..выполнит ли нет команду echo.

Теперь, чтобы получить результаты пинга, вы можете проанализировать переменную out. Пример вывода:

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

Пример регулярного выражения:

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')

Опять же, помните, что вывод будет зависеть от операционной системы (и даже от версии ping). Это не идеально, но во многих ситуациях он будет работать нормально (когда вы знаете, на каких машинах будет работать скрипт).

Я обнаружил, что мне нужно настроить выражение соответствия регулярному выражению, поскольку out содержит закодированный \ n, который, похоже, мешает сопоставлению: matcher = re.compile("\nround-trip min/avg/max/stddev = (\d+.\d+)/(\d+.\d+)/(\d+.\d+)/(\d+.\d+)")

Pierz 13.12.2014 00:44

@Pierz: просто вместо этого используйте matcher.search без изменения регулярного выражения.

jfs 30.03.2015 19:51

В Windows следует использовать -n вместо -c. (См. Ответ ePi272314)

Stevoisiak 24.06.2019 22:09

Трудно сказать, в чем заключается ваш вопрос, но есть несколько альтернатив.

Если вы хотите буквально выполнить запрос с использованием протокола проверки связи ICMP, вы можете получить библиотеку ICMP и выполнить запрос проверки связи напрямую. Погуглите "Python ICMP", чтобы найти такие вещи, как этот icmplib. Вы можете также посмотреть на чешуйчатый.

Это будет намного быстрее, чем при использовании os.system("ping " + ip ).

Если вы хотите в общем «пропинговать» окно, чтобы проверить, работает ли он, вы можете использовать протокол эха на порту 7.

Для эха вы используете библиотеку разъем, чтобы открыть IP-адрес и порт 7. Вы что-то пишете на этот порт, отправляете возврат каретки ("\r\n") и затем читаете ответ.

Если вы хотите «пинговать» веб-сайт, чтобы узнать, работает ли он, вы должны использовать протокол http на порту 80.

Для правильной проверки веб-сервера вы используете urllib2, чтобы открыть определенный URL. (/index.html всегда популярен) и прочтите ответ.

Есть еще больше потенциальных значений «ping», включая «traceroute» и «finger».

Когда-то эхо было широко распространено, но теперь оно отключено по умолчанию в большинстве систем. Таким образом, это непрактичный способ проверить, нормально ли работает машина.

bortzmeyer 25.11.2008 18:21

Вы можете найти Ной Гифт презентацию Создание гибких инструментов командной строки с помощью Python. В нем он объединяет подпроцесс, очередь и потоки для разработки решения, способного одновременно проверять связь с хостами и ускорять процесс. Ниже представлена ​​базовая версия до того, как он добавит синтаксический анализ командной строки и некоторые другие функции. Код этой и других версий можно найти здесь

#!/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()

Он также является автором: Python для системного администрирования Unix и Linux

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

Не знаю, действительно ли это отвечает на вопрос, но это очень полезная информация!

ig0774 11.05.2010 21:15

Я знаю, что это идет от PyCon ... но это очень плохо. Выполнение системных вызовов - это пустая трата времени и ресурсов, при этом они невероятно зависят от системы и их трудно анализировать. Вам лучше выбрать метод, использующий Python для отправки / получения запросов ICMP, поскольку в этом потоке есть и другие.

Cukic0d 13.07.2019 15:44

См. Этот чистый Python ping от Мэттью Диксон Коулз и Йенс Димер. Также помните, что Python требует root для создания сокетов ICMP (т. Е. Ping) в 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

Сам исходный код легко читается, см. Реализации verbose_ping и Ping.do для вдохновения.

ping использует time.clock, который не дает ничего полезного на моем Linux-компьютере. timeit.default_timer (на моей машине он равен time.time) работает. time.clock -> timeit.default_timergist.github.com/255009
jfs 12.12.2009 22:14

@Vinicius - спасибо! Обновлено с новой локацией на github. Кажется, он тоже постоянно поддерживается!

orip 13.09.2011 18:55

ping не имеет метода do_one. Я не мог найти простого способа узнать время пинга.

Joseph Turian 18.11.2011 15:39

@JosephTurian, ты прав. Я обновил пример, чтобы он соответствовал текущей версии источника.

orip 26.12.2011 19:55

это больше не работает - kwarg 'run' исчез, и я получаю error: Operation not permitted - Note that ICMP messages can only be sent from processes running as root.

wim 22.02.2012 07:54

'run' был переименован в 'count'

pferate 10.07.2013 03:55

Почему этой библиотеке требуется root, а бинарный файл ping в Linux можно запустить от имени любого пользователя?

Chris Withers 09.09.2016 17:09

@ChrisWithers двоичный файл ping запускается от имени пользователя root через бит setuid. superuser.com/a/1035983/4706

orip 09.09.2016 17:15

Получаю AttributeError: 'module' object has no attribute 'verbose_ping'. Как я могу это исправить?

Alperen Görmez 15.02.2018 10:37

@ AlperenGörmez Я не уверен, какой модуль ping вы импортируете - можете попробовать print ping, чтобы перепроверить. При установке пакета из PyPI ping.py устанавливается только как двоичный сценарий. Однако вы может импортируете его, например, копируя в другое место. Я только что еще раз проверил, что у него есть функция verbose_ping

orip 15.02.2018 12:13

Страница python-ping GitHub больше не существует и проект PyPI не обновлялись с 2011 года. Я не рекомендую его использовать.

Stevoisiak 24.06.2019 22:00

используя системную команду ping для проверки связи со списком хостов:

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)

Я собираюсь зарегистрировать www.this_one_wont_work.com просто для удовольствия.

Matthew Scouten 30.07.2009 06:36
p = Popen('ping -n 1 ' + self.host, stdout=PIPE) Должен быть p = Popen(['ping','-n','1','self.host'], stdout=PIPE)
toc777 26.04.2011 15:24

Я сделал нечто подобное в качестве вдохновения:

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()

рад, что вы держались подальше от внешних библиотек и subprocess

tshepang 09.04.2012 01:15

Что делать, если нет index.html?

sbose 03.09.2013 14:16

Что еще более важно, что делать, если нет веб-сервера?

Kim Gräsman 17.02.2015 15:44

Действительно, нет необходимости объединять этот /index.html; на любом сайте, где действительно был бы документ под названием index.html, он был бы прямо там, в корне сервера. Вместо этого вы должны передать хосту добавитьhttp:// или https://.

Antti Haapala 13.08.2016 13:15

Хотя на самом деле это не ICMP-пинг, а скорее TCP-порт 80 "ping" + HTTP-тест, вероятно, было бы лучше выполнить запрос HEAD (или OPTIONS), поскольку вы фактически не получите никакого контента, поэтому пропускная способность будет повлиять на это меньше. Если вам нужно что-то более запасное, вы можете просто попытаться открыть сокет TCP 80 для хоста и немедленно закрыть его.

Nick T 20.09.2017 18:57

Вы можете найти обновленную версию упомянутого скрипта, которая работает как в Windows, так и в Linux здесь

Связанный код не работает на Python 3.8. «SyntaxError: недопустимый синтаксис»

Stevoisiak 27.06.2019 19:52

Вот небольшой фрагмент с использованием subprocess. Метод check_call либо возвращает 0 в случае успеха, либо вызывает исключение. Таким образом, мне не нужно анализировать вывод команды ping. Я использую shlex для разделения аргументов командной строки.

  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."

Предупреждение: не работает в windows (там -c - это -n, а логика кода возврата другая)

wim 03.12.2012 10:48

прочтите имя файла, файл содержит по одному URL-адресу в строке, например:

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

используйте команду:

python url.py urls.txt

получить результат:

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

исходный код (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)
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"

Используйте это, он протестирован на python 2.7 и отлично работает, он возвращает время пинга в миллисекундах в случае успеха и возвращает False в случае неудачи.

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

Не работает на Python 3.6. ModuleNotFoundError: нет модуля с именем subproccess

Stevoisiak 27.06.2019 19:56

Также не работает, потому что command - это строка, включающая все аргументы, а не список, поэтому запускает command not found для полной строки в Linux.

arielf 04.04.2020 00:28

Если вам действительно нужно что-то на Python, с чем можно поиграть, взгляните на Scapy:

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

На мой взгляд, это намного лучше (и полностью кроссплатформенный), чем некоторые фанковые вызовы подпроцессов. Также у вас может быть столько информации об ответе (ID последовательности ...), сколько вам нужно, как и сам пакет.

Самый простой ответ:

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

используя команду subprocess ping для ping-декодирования, потому что ответ двоичный:

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

Я разрабатываю библиотеку, которая, как мне кажется, может вам помочь. Он называется icmplib (не связан с каким-либо другим кодом с таким же именем, который можно найти в Интернете) и представляет собой чистую реализацию протокола ICMP на Python.

Он полностью объектно-ориентирован и имеет простые функции, такие как классический ping, multiping и traceroute, а также низкоуровневые классы и сокеты для тех, кто хочет разрабатывать приложения на основе протокола ICMP.

Вот еще несколько интересных моментов:

  • Может работать без root-прав.
  • Вы можете настроить многие параметры, такие как полезная нагрузка пакетов ICMP и класс трафика (QoS).
  • Кроссплатформенность: протестировано на Linux, macOS и Windows.
  • Быстро и требует мало ресурсов ЦП / ОЗУ, в отличие от вызовов, выполняемых с помощью подпроцесса.
  • Легковесный и не требует дополнительных зависимостей.

Чтобы установить его (требуется Python 3.6+):

pip3 install icmplib

Вот простой пример функции 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')

Установите для параметра «привилегированный» значение False, если вы хотите использовать библиотеку без привилегий root.

Вы можете найти полную документацию на странице проекта: https://github.com/ValentinBELYN/icmplib

Надеюсь, вы найдете эту библиотеку полезной.

Примечание модератора: этот ответ соблюдает наши требования по саморекламе не является нежелательным (вопрос требует решения Python для использования ping), как и не спам по нашему определению термина.
Martijn Pieters 22.11.2020 02:07

вы можете попробовать socket, чтобы получить ip сайта и использовать scrapy для выполнения icmp ping для 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])

Другие вопросы по теме