1
0

gorbunov.py 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482
  1. import socket
  2. import requests
  3. import uuid
  4. import psutil
  5. import netifaces
  6. from pythonping import ping as python_ping
  7. import time
  8. import os
  9. import urllib3
  10. from urllib.parse import urlparse
  11. # Отключаем предупреждения SSL для избежания ошибок сертификатов
  12. urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
  13. # --- Утилитарные функции ---
  14. def get_size(bytes_count):
  15. """
  16. Преобразует байты в удобочитаемый формат (B, KB, MB, GB, TB).
  17. """
  18. if not isinstance(bytes_count, (int, float)) or bytes_count is None:
  19. return "N/A"
  20. for unit in ['B', 'KB', 'MB', 'GB', 'TB', 'PB']:
  21. if bytes_count < 1024.0:
  22. return f"{bytes_count:.2f} {unit}"
  23. bytes_count /= 1024.0
  24. return f"{bytes_count:.2f} PB"
  25. def format_report(data, target_host):
  26. """
  27. Форматирует все собранные данные в одну строку для вывода в файл и консоль.
  28. """
  29. timestamp = time.strftime("%Y-%m-%d %H:%M:%S")
  30. report_lines = []
  31. report_lines.append("="*50)
  32. report_lines.append(" СВОДНАЯ ИНФОРМАЦИЯ О СЕТИ")
  33. report_lines.append("="*50)
  34. report_lines.append(f"Дата и время отчета: {timestamp}")
  35. report_lines.append("-" * 30)
  36. # Блок 1: Системная информация
  37. report_lines.append("🖥️ Система:")
  38. report_lines.append(f" Имя компьютера: {data.get('hostname', 'N/A')}")
  39. report_lines.append(f" Сетевой адаптер: {data.get('interface_name', 'N/A')}")
  40. report_lines.append(f" MAC-адрес: {data.get('mac_address', 'N/A')}")
  41. report_lines.append("-" * 30)
  42. # Блок 2: IP-адреса и шлюз
  43. report_lines.append(f"🌐 IP-адреса:")
  44. report_lines.append(f" Внутренний IP: {data.get('local_ip', 'N/A')}")
  45. report_lines.append(f" IP шлюза (роутера): {data.get('gateway_ip', 'N/A')}")
  46. report_lines.append(f" Внешний IP: {data.get('external_ip', 'N/A')}")
  47. report_lines.append("-" * 30)
  48. # Блок 3: Объем данных
  49. report_lines.append(f"📊 Общий объем данных (с момента загрузки ОС):")
  50. report_lines.append(f" Отправлено: {get_size(data.get('total_sent'))}")
  51. report_lines.append(f" Получено: {get_size(data.get('total_recv'))}")
  52. report_lines.append("-" * 30)
  53. # Блок 4: Пинг
  54. report_lines.append(f"⏱️ Пинг и потеря пакетов:")
  55. # Пинг до шлюза
  56. report_lines.append(f" - До шлюза ({data.get('gateway_ip', 'N/A')}):")
  57. ping_gw = data.get('ping_gateway_ms')
  58. loss_gw = data.get('loss_gateway_percent')
  59. if ping_gw is not None:
  60. report_lines.append(f" Средний пинг: {ping_gw:.2f} мс")
  61. report_lines.append(f" Потеря пакетов: {loss_gw:.2f}%")
  62. else:
  63. report_lines.append(" Не удалось проверить.")
  64. # Пинг до ya.ru
  65. report_lines.append(f" - До {target_host}:")
  66. ping_ext = data.get('ping_ya_ru_ms')
  67. loss_ext = data.get('loss_ya_ru_percent')
  68. if ping_ext is not None:
  69. report_lines.append(f" Средний пинг: {ping_ext:.2f} мс")
  70. report_lines.append(f" Потеря пакетов: {loss_ext:.2f}%")
  71. else:
  72. report_lines.append(" Не удалось проверить (проверьте подключение к Интернету).")
  73. report_lines.append("-" * 30)
  74. # Блок 5: Скорость через прямое скачивание
  75. report_lines.append(f"📶 Скорость Интернета (прямое скачивание):")
  76. dl_speed = data.get('download_speed_mbps')
  77. if dl_speed is not None:
  78. report_lines.append(f" Скорость загрузки: {dl_speed:.2f} Мбит/с")
  79. report_lines.append(f" Использованный сервер: {data.get('speed_test_server', 'N/A')}")
  80. report_lines.append(f" Размер тестового файла: {get_size(data.get('test_file_size', 0))}")
  81. report_lines.append(f" Время скачивания: {data.get('download_time', 0):.2f} сек")
  82. else:
  83. report_lines.append(" Тестирование скорости не было выполнено или завершилось ошибкой.")
  84. report_lines.append("="*50)
  85. return "\n".join(report_lines)
  86. # --- Функции для измерения ---
  87. def get_network_io_total():
  88. """Получает общий объем отправленных и полученных данных."""
  89. try:
  90. net_io = psutil.net_io_counters()
  91. return {"total_sent": net_io.bytes_sent, "total_recv": net_io.bytes_recv}
  92. except Exception:
  93. return None
  94. def test_download_speed(url, name, test_duration=10):
  95. """
  96. Тестирует скорость загрузки с одного сервера в течение заданного времени.
  97. """
  98. try:
  99. print(f" Тестируем: {name}")
  100. # Настраиваем сессию с таймаутами
  101. session = requests.Session()
  102. session.verify = False
  103. session.timeout = (10, 30) # (connect timeout, read timeout)
  104. # Начинаем замер времени
  105. start_time = time.time()
  106. total_downloaded = 0
  107. # Запрашиваем файл с потоковой передачей
  108. response = session.get(url, stream=True)
  109. response.raise_for_status()
  110. # Читаем данные порциями в течение test_duration секунд
  111. chunk_size = 1024 * 128 # 128 KB chunks
  112. last_update = start_time
  113. for chunk in response.iter_content(chunk_size=chunk_size):
  114. if not chunk:
  115. break
  116. total_downloaded += len(chunk)
  117. current_time = time.time()
  118. elapsed = current_time - start_time
  119. # Обновляем прогресс каждую секунду
  120. if current_time - last_update >= 1:
  121. speed_mbps = (total_downloaded * 8) / elapsed / (1024 * 1024)
  122. print(f" Прогресс: {elapsed:.1f} сек, скорость: {speed_mbps:.2f} Мбит/с, скачано: {get_size(total_downloaded)}")
  123. last_update = current_time
  124. # Прерываем если достигли целевого времени тестирования
  125. if elapsed >= test_duration:
  126. break
  127. download_time = time.time() - start_time
  128. # Проверяем, что тест длился достаточно долго
  129. if download_time < 1.0:
  130. print(f" ⚠ Тест слишком короткий ({download_time:.1f} сек)")
  131. return None
  132. # Рассчитываем финальную скорость
  133. speed_bps = (total_downloaded * 8) / download_time # биты в секунду
  134. speed_mbps = speed_bps / (1024 * 1024) # Мбит в секунду
  135. print(f" ✓ Успешно: {speed_mbps:.2f} Мбит/с за {download_time:.1f} сек, скачано: {get_size(total_downloaded)}")
  136. return {
  137. "download_speed_mbps": speed_mbps,
  138. "speed_test_server": name,
  139. "test_file_size": total_downloaded,
  140. "download_time": download_time
  141. }
  142. except requests.exceptions.Timeout:
  143. print(f" ✗ Таймаут подключения")
  144. except requests.exceptions.RequestException as e:
  145. print(f" ✗ Ошибка подключения: {str(e)[:80]}")
  146. except Exception as e:
  147. print(f" ✗ Неожиданная ошибка: {str(e)[:80]}")
  148. return None
  149. def download_speed_test(test_duration=10):
  150. """
  151. Измеряет скорость загрузки через прямое скачивание файлов с российских серверов.
  152. Возвращает скорость в Мбит/с.
  153. """
  154. print(f" Тестирование будет длиться {test_duration} секунд...")
  155. # Обновленный список РАБОТАЮЩИХ российских серверов с тестовыми файлами
  156. # Используем большие файлы для точного тестирования
  157. test_servers = [
  158. {
  159. 'name': 'Yandex Disk (архив)',
  160. 'url': 'https://disk.yandex.ru/d/3C3q6FmH_pj2SA/1%20%D0%93%D0%B1%20%D1%82%D0%B5%D1%81%D1%82%D0%BE%D0%B2%D1%8B%D0%B9%20%D1%84%D0%B0%D0%B9%D0%BB.bin?w=1',
  161. 'timeout': 30
  162. },
  163. {
  164. 'name': 'Ростелеком Speedtest',
  165. 'url': 'https://speedtest.rt.ru:8080/speedtest/random4000x4000.jpg',
  166. 'timeout': 30
  167. },
  168. {
  169. 'name': 'Moscow Data Center',
  170. 'url': 'http://lg.moscow.datacenter.by/speedtest/100MB.bin',
  171. 'timeout': 30
  172. },
  173. {
  174. 'name': 'Beeline Speedtest',
  175. 'url': 'http://speedtest.beeline.ru/speedtest/random1000x1000.jpg',
  176. 'timeout': 30
  177. },
  178. {
  179. 'name': 'MTS Speedtest',
  180. 'url': 'http://speedtest.mts.ru/speedtest/random4000x4000.jpg',
  181. 'timeout': 30
  182. },
  183. {
  184. 'name': 'Rostelecom Backup',
  185. 'url': 'https://mirror.rt.ru/ubuntu-releases/22.04/ubuntu-22.04.3-live-server-amd64.iso',
  186. 'timeout': 30
  187. },
  188. {
  189. 'name': 'Yandex Static',
  190. 'url': 'https://yastatic.net/s3/home-static/_/b4/b4bb7395e1b09a5f6aa182b2e2aec097.png',
  191. 'timeout': 20
  192. },
  193. {
  194. 'name': 'Mail.ru Static',
  195. 'url': 'https://imgsmail.ru/splash/v25/splash.jpg',
  196. 'timeout': 20
  197. },
  198. {
  199. 'name': 'VK Static',
  200. 'url': 'https://vk.com/images/gift/1/512.jpg',
  201. 'timeout': 20
  202. },
  203. {
  204. 'name': 'Russian Government',
  205. 'url': 'https://www.gov.ru/static/img/gerb.svg',
  206. 'timeout': 20
  207. },
  208. {
  209. 'name': 'Sberbank Static',
  210. 'url': 'https://www.sberbank.ru/portalserver/static/templates/%5BBBHOST%5D/resources/images/logo.svg',
  211. 'timeout': 20
  212. }
  213. ]
  214. print(f" Доступно серверов для тестирования: {len(test_servers)}")
  215. for server in test_servers:
  216. result = test_download_speed(server['url'], server['name'], test_duration)
  217. if result:
  218. return result
  219. # Небольшая пауза между тестами
  220. time.sleep(1)
  221. # Если все серверы недоступны, пробуем альтернативный метод
  222. print(" Все основные серверы недоступны, пробуем альтернативные методы...")
  223. return alternative_speed_test()
  224. def alternative_speed_test():
  225. """
  226. Альтернативный метод измерения скорости через многократные запросы.
  227. """
  228. try:
  229. print(" Альтернативный тест: многократные запросы к ya.ru...")
  230. test_url = "https://ya.ru"
  231. session = requests.Session()
  232. session.verify = False
  233. total_downloaded = 0
  234. start_time = time.time()
  235. iterations = 0
  236. max_iterations = 20
  237. target_duration = 8 # Целевая продолжительность теста
  238. while (time.time() - start_time) < target_duration and iterations < max_iterations:
  239. try:
  240. response = session.get(test_url, timeout=5)
  241. total_downloaded += len(response.content)
  242. iterations += 1
  243. # Небольшая пауза между запросами
  244. time.sleep(0.2)
  245. except Exception:
  246. break
  247. download_time = time.time() - start_time
  248. if download_time > 2.0 and total_downloaded > 100 * 1024:
  249. speed_bps = (total_downloaded * 8) / download_time
  250. speed_mbps = speed_bps / (1024 * 1024)
  251. print(f" ✓ Альтернативный тест: {speed_mbps:.2f} Мбит/с за {download_time:.1f} сек, {iterations} запросов")
  252. return {
  253. "download_speed_mbps": speed_mbps,
  254. "speed_test_server": "Альтернативный тест (многократные запросы к ya.ru)",
  255. "test_file_size": total_downloaded,
  256. "download_time": download_time
  257. }
  258. except Exception as e:
  259. print(f" ✗ Ошибка альтернативного теста: {str(e)[:80]}")
  260. print(" ✗ Все методы измерения скорости не удались")
  261. return None
  262. def get_ping_and_loss(target, count=8):
  263. """Измеряет средний пинг и процент потери пакетов."""
  264. try:
  265. print(f" Пинг до {target}...")
  266. result = python_ping(target, count=count, timeout=3)
  267. # Отображаем прогресс
  268. if hasattr(result, '_responses'):
  269. for i, resp in enumerate(result._responses):
  270. if resp.success:
  271. print(f" Пакет {i+1}: {resp.time_elapsed_ms:.2f} мс")
  272. else:
  273. print(f" Пакет {i+1}: потерян")
  274. return {"avg_ping_ms": result.rtt_avg_ms, "packet_loss_percent": result.packet_loss}
  275. except Exception as e:
  276. print(f" ✗ Ошибка пинга: {str(e)[:80]}")
  277. return None
  278. def get_local_net_details():
  279. """Получает локальный IP, MAC-адрес, имя активного интерфейса и IP шлюза."""
  280. details = {"local_ip": None, "mac_address": None, "interface_name": None, "gateway_ip": None}
  281. try:
  282. gws = netifaces.gateways()
  283. default_route = gws.get('default', {}).get(netifaces.AF_INET)
  284. if default_route:
  285. details['gateway_ip'] = default_route[0]
  286. active_interface = default_route[1]
  287. details['interface_name'] = active_interface
  288. addrs = netifaces.ifaddresses(active_interface)
  289. if netifaces.AF_INET in addrs:
  290. details['local_ip'] = addrs[netifaces.AF_INET][0]['addr']
  291. if netifaces.AF_LINK in addrs:
  292. details['mac_address'] = addrs[netifaces.AF_LINK][0]['addr'].upper().replace('-', ':')
  293. except Exception as e:
  294. print(f" Ошибка получения сетевых деталей: {e}")
  295. return details
  296. def get_system_info():
  297. """Собирает имя хоста и внешний IP."""
  298. info = {"hostname": None, "external_ip": None}
  299. try:
  300. info["hostname"] = socket.gethostname()
  301. except Exception as e:
  302. print(f" Ошибка получения hostname: {e}")
  303. try:
  304. # Пробуем несколько сервисов для получения внешнего IP
  305. services = [
  306. 'https://api.ipify.org?format=json',
  307. 'https://ifconfig.me/all.json',
  308. 'http://ip-api.com/json/'
  309. ]
  310. for service in services:
  311. try:
  312. response = requests.get(service, timeout=5, verify=False)
  313. response.raise_for_status()
  314. data = response.json()
  315. if 'ip' in data:
  316. info["external_ip"] = data['ip']
  317. break
  318. elif 'query' in data: # ip-api.com format
  319. info["external_ip"] = data['query']
  320. break
  321. except:
  322. continue
  323. except Exception as e:
  324. print(f" Ошибка получения внешнего IP: {e}")
  325. return info
  326. # --- Основной запуск ---
  327. if __name__ == "__main__":
  328. data = {}
  329. target_host = 'ya.ru'
  330. output_filename = "network_info_report.txt"
  331. print("="*60)
  332. print(" ПРОГРАММА ДЛЯ АНАЛИЗА СЕТЕВОГО ПОДКЛЮЧЕНИЯ")
  333. print("="*60)
  334. # Сбор данных
  335. print("\n--- 1. Сбор базовой информации (IP, MAC, Hostname) ---")
  336. system_info = get_system_info()
  337. data.update(system_info)
  338. print(f" Hostname: {system_info.get('hostname', 'N/A')}")
  339. print(f" Внешний IP: {system_info.get('external_ip', 'N/A')}")
  340. local_info = get_local_net_details()
  341. data.update(local_info)
  342. print(f" Локальный IP: {local_info.get('local_ip', 'N/A')}")
  343. print(f" MAC-адрес: {local_info.get('mac_address', 'N/A')}")
  344. print(f" Интерфейс: {local_info.get('interface_name', 'N/A')}")
  345. print(f" Шлюз: {local_info.get('gateway_ip', 'N/A')}")
  346. io_data = get_network_io_total()
  347. if io_data:
  348. data.update(io_data)
  349. print(f" Отправлено данных: {get_size(io_data.get('total_sent'))}")
  350. print(f" Получено данных: {get_size(io_data.get('total_recv'))}")
  351. print("Базовые данные собраны. ✅")
  352. # Пинги
  353. if data.get('gateway_ip'):
  354. print(f"\n--- 2. Проверка пинга до шлюза ({data['gateway_ip']}) ---")
  355. ping_gw_data = get_ping_and_loss(data['gateway_ip'], count=10)
  356. if ping_gw_data:
  357. data["ping_gateway_ms"] = ping_gw_data["avg_ping_ms"]
  358. data["loss_gateway_percent"] = ping_gw_data["packet_loss_percent"]
  359. print(f" Средний пинг: {ping_gw_data['avg_ping_ms']:.2f} мс")
  360. print(f" Потеря пакетов: {ping_gw_data['packet_loss_percent']:.2f}%")
  361. print("Проверка завершена. 📶")
  362. print(f"\n--- 3. Проверка пинга до {target_host} ---")
  363. ping_ext_data = get_ping_and_loss(target=target_host, count=10)
  364. if ping_ext_data:
  365. data["ping_ya_ru_ms"] = ping_ext_data["avg_ping_ms"]
  366. data["loss_ya_ru_percent"] = ping_ext_data["packet_loss_percent"]
  367. print(f" Средний пинг: {ping_ext_data['avg_ping_ms']:.2f} мс")
  368. print(f" Потеря пакетов: {ping_ext_data['packet_loss_percent']:.2f}%")
  369. print("Проверка завершена. 🎯")
  370. # Speedtest через прямое скачивание
  371. print("\n--- 4. Проверка скорости сети (прямое скачивание) ---")
  372. print("Тестирование скорости загрузки с российских серверов...")
  373. print("⚠ Тест займет около 10 секунд для точного измерения...")
  374. # Тестируем скорость в течение 10 секунд для точности
  375. speed_data = download_speed_test(test_duration=10)
  376. if speed_data:
  377. data.update(speed_data)
  378. print(f"\n ИТОГ скорости: {speed_data['download_speed_mbps']:.2f} Мбит/с")
  379. print("Тестирование скорости завершено. 🚀")
  380. else:
  381. print("Тестирование скорости не выполнено (все серверы недоступны).")
  382. # Форматирование и вывод отчета
  383. report_content = format_report(data, target_host)
  384. print("\n" + "="*60)
  385. print(" ОТЧЕТ")
  386. print("="*60)
  387. print(report_content)
  388. try:
  389. with open(output_filename, 'w', encoding='utf-8') as f:
  390. f.write(report_content)
  391. print(f"\n✅ Отчет успешно сохранен в файле: {output_filename}")
  392. print(f"📂 Путь: {os.path.abspath(output_filename)}")
  393. except Exception as e:
  394. print(f"\n❌ Ошибка при записи отчета в файл: {e}")
  395. print("\n" + "="*60)
  396. print(" ТЕСТИРОВАНИЕ ЗАВЕРШЕНО")
  397. print("="*60)