Как проверить связь с веб-сайтом или IP-адресом с помощью Python?
это оказалось более полезным для проблемы, которую я решал: stackoverflow.com/questions/3764291/checking-network -соединение
вот реализация чистого питона: falatic.com/index.php/39/pinging-with-python






В зависимости от того, чего вы хотите достичь, вам, вероятно, проще всего вызвать системную команду 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: просто вместо этого используйте matcher.search без изменения регулярного выражения.
В Windows следует использовать -n вместо -c. (См. Ответ ePi272314)
Трудно сказать, в чем заключается ваш вопрос, но есть несколько альтернатив.
Если вы хотите буквально выполнить запрос с использованием протокола проверки связи ICMP, вы можете получить библиотеку ICMP и выполнить запрос проверки связи напрямую. Погуглите "Python ICMP", чтобы найти такие вещи, как этот icmplib. Вы можете также посмотреть на чешуйчатый.
Это будет намного быстрее, чем при использовании os.system("ping " + ip ).
Если вы хотите в общем «пропинговать» окно, чтобы проверить, работает ли он, вы можете использовать протокол эха на порту 7.
Для эха вы используете библиотеку разъем, чтобы открыть IP-адрес и порт 7. Вы что-то пишете на этот порт, отправляете возврат каретки ("\r\n") и затем читаете ответ.
Если вы хотите «пинговать» веб-сайт, чтобы узнать, работает ли он, вы должны использовать протокол http на порту 80.
Для правильной проверки веб-сервера вы используете urllib2, чтобы открыть определенный URL. (/index.html всегда популярен) и прочтите ответ.
Есть еще больше потенциальных значений «ping», включая «traceroute» и «finger».
Когда-то эхо было широко распространено, но теперь оно отключено по умолчанию в большинстве систем. Таким образом, это непрактичный способ проверить, нормально ли работает машина.
Вы можете найти Ной Гифт презентацию Создание гибких инструментов командной строки с помощью 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
Не знаю, действительно ли это отвечает на вопрос, но это очень полезная информация!
Я знаю, что это идет от PyCon ... но это очень плохо. Выполнение системных вызовов - это пустая трата времени и ресурсов, при этом они невероятно зависят от системы и их трудно анализировать. Вам лучше выбрать метод, использующий Python для отправки / получения запросов ICMP, поскольку в этом потоке есть и другие.
См. Этот чистый 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@Vinicius - спасибо! Обновлено с новой локацией на github. Кажется, он тоже постоянно поддерживается!
ping не имеет метода do_one. Я не мог найти простого способа узнать время пинга.
@JosephTurian, ты прав. Я обновил пример, чтобы он соответствовал текущей версии источника.
это больше не работает - kwarg 'run' исчез, и я получаю error: Operation not permitted - Note that ICMP messages can only be sent from processes running as root.
'run' был переименован в 'count'
Почему этой библиотеке требуется root, а бинарный файл ping в Linux можно запустить от имени любого пользователя?
@ChrisWithers двоичный файл ping запускается от имени пользователя root через бит setuid. superuser.com/a/1035983/4706
Получаю AttributeError: 'module' object has no attribute 'verbose_ping'. Как я могу это исправить?
@ AlperenGörmez Я не уверен, какой модуль ping вы импортируете - можете попробовать print ping, чтобы перепроверить. При установке пакета из PyPI ping.py устанавливается только как двоичный сценарий. Однако вы может импортируете его, например, копируя в другое место. Я только что еще раз проверил, что у него есть функция verbose_ping
Страница python-ping GitHub больше не существует и проект PyPI не обновлялись с 2011 года. Я не рекомендую его использовать.
используя системную команду 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 просто для удовольствия.
p = Popen('ping -n 1 ' + self.host, stdout=PIPE) Должен быть p = Popen(['ping','-n','1','self.host'], stdout=PIPE)Я сделал нечто подобное в качестве вдохновения:
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
Что делать, если нет index.html?
Что еще более важно, что делать, если нет веб-сервера?
Действительно, нет необходимости объединять этот /index.html; на любом сайте, где действительно был бы документ под названием index.html, он был бы прямо там, в корне сервера. Вместо этого вы должны передать хосту добавитьhttp:// или https://.
Хотя на самом деле это не ICMP-пинг, а скорее TCP-порт 80 "ping" + HTTP-тест, вероятно, было бы лучше выполнить запрос HEAD (или OPTIONS), поскольку вы фактически не получите никакого контента, поэтому пропускная способность будет повлиять на это меньше. Если вам нужно что-то более запасное, вы можете просто попытаться открыть сокет TCP 80 для хоста и немедленно закрыть его.
Вы можете найти обновленную версию упомянутого скрипта, которая работает как в Windows, так и в Linux здесь
Связанный код не работает на Python 3.8. «SyntaxError: недопустимый синтаксис»
Вот небольшой фрагмент с использованием 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, а логика кода возврата другая)
прочтите имя файла, файл содержит по одному 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
Также не работает, потому что command - это строка, включающая все аргументы, а не список, поэтому запускает command not found для полной строки в Linux.
Если вам действительно нужно что-то на 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.
Вот еще несколько интересных моментов:
Чтобы установить его (требуется 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
Надеюсь, вы найдете эту библиотеку полезной.
вы можете попробовать 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])
Определите, пожалуйста, "пинг". Вы хотите использовать протокол ping ICMP или посмотреть, работает ли веб-сервер? Или что-то другое?