1
0

network_info.py 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365
  1. import tkinter as tk
  2. from tkinter import messagebox, ttk
  3. import sqlite3
  4. import socket
  5. import requests
  6. import uuid
  7. import speedtest
  8. import psutil
  9. import netifaces
  10. from pythonping import ping as python_ping
  11. import time
  12. import os
  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. # Добавляем метку времени начала отчета
  30. timestamp = time.strftime("%Y-%m-%d %H:%M:%S")
  31. report_lines = []
  32. report_lines.append("="*50)
  33. report_lines.append(" СВОДНАЯ ИНФОРМАЦИЯ О СЕТИ")
  34. report_lines.append("="*50)
  35. report_lines.append(f"Дата и время отчета: {timestamp}")
  36. report_lines.append("-" * 30)
  37. # Блок 1: Системная информация
  38. report_lines.append("🖥️ Система:")
  39. report_lines.append(f" Имя компьютера: {data.get('hostname', 'N/A')}")
  40. report_lines.append(f" Сетевой адаптер: {data.get('interface_name', 'N/A')}")
  41. report_lines.append(f" MAC-адрес: {data.get('mac_address', 'N/A')}")
  42. report_lines.append("-" * 30)
  43. # Блок 2: IP-адреса и шлюз
  44. report_lines.append(f"🌐 IP-адреса:")
  45. report_lines.append(f" Внутренний IP: {data.get('local_ip', 'N/A')}")
  46. report_lines.append(f" IP шлюза (роутера): {data.get('gateway_ip', 'N/A')}")
  47. report_lines.append(f" Внешний IP: {data.get('external_ip', 'N/A')}")
  48. report_lines.append("-" * 30)
  49. # Блок 3: Объем данных
  50. report_lines.append(f"📊 Общий объем данных (с момента загрузки ОС):")
  51. report_lines.append(f" Отправлено: {get_size(data.get('total_sent'))}")
  52. report_lines.append(f" Получено: {get_size(data.get('total_recv'))}")
  53. report_lines.append("-" * 30)
  54. # Блок 4: Пинг
  55. report_lines.append(f"⏱️ Пинг и потеря пакетов:")
  56. # Пинг до шлюза
  57. report_lines.append(f" - До шлюза ({data.get('gateway_ip', 'N/A')}):")
  58. ping_gw = data.get('ping_gateway_ms')
  59. loss_gw = data.get('loss_gateway_percent')
  60. if ping_gw is not None:
  61. report_lines.append(f" Средний пинг: {ping_gw:.2f} мс")
  62. report_lines.append(f" Потеря пакетов: {loss_gw:.2f}%")
  63. else:
  64. report_lines.append(" Не удалось проверить.")
  65. # Пинг до ya.ru
  66. report_lines.append(f" - До {target_host}:")
  67. ping_ext = data.get('ping_ya_ru_ms')
  68. loss_ext = data.get('loss_ya_ru_percent')
  69. if ping_ext is not None:
  70. report_lines.append(f" Средний пинг: {ping_ext:.2f} мс")
  71. report_lines.append(f" Потеря пакетов: {loss_ext:.2f}%")
  72. else:
  73. report_lines.append(" Не удалось проверить (проверьте подключение к Интернету).")
  74. report_lines.append("-" * 30)
  75. # Блок 5: Скорость
  76. report_lines.append(f"📶 Скорость Интернета (Speedtest):")
  77. dl_speed = data.get('download_speed_mbps')
  78. ul_speed = data.get('upload_speed_mbps')
  79. if dl_speed is not None:
  80. report_lines.append(f" Скорость загрузки: {dl_speed:.2f} Мбит/с")
  81. report_lines.append(f" Скорость выгрузки: {ul_speed:.2f} Мбит/с")
  82. report_lines.append(f" Сервер: {data.get('server_name')} ({data.get('server_location')})")
  83. report_lines.append(f" Задержка до сервера: {data.get('server_latency'):.2f} мс")
  84. else:
  85. report_lines.append(" Тестирование скорости не было выполнено или завершилось ошибкой.")
  86. report_lines.append("="*50)
  87. return "\n".join(report_lines)
  88. # *** Функции для измерений ***
  89. def get_network_io_total():
  90. """Получает общий объем отправленных и полученных данных."""
  91. try:
  92. net_io = psutil.net_io_counters()
  93. return {"total_sent": net_io.bytes_sent, "total_recv": net_io.bytes_recv}
  94. except Exception:
  95. return None
  96. def get_network_speed():
  97. """Измеряет скорость загрузки, выгрузки и получает данные о сервере Speedtest."""
  98. try:
  99. st = speedtest.Speedtest()
  100. st.get_best_server()
  101. server = st.best
  102. download_speed = st.download() / 10**6
  103. upload_speed = st.upload() / 10**6
  104. return {
  105. "download_speed_mbps": download_speed, "upload_speed_mbps": upload_speed,
  106. "server_name": server['host'], "server_location": f"{server['country']} ({server['name']})",
  107. "server_latency": server['latency']
  108. }
  109. except Exception:
  110. return None
  111. def get_ping_and_loss(target, count=4):
  112. """Измеряет средний пинг и процент потери пакетов."""
  113. try:
  114. result = python_ping(target, count=count, timeout=2)
  115. return {"avg_ping_ms": result.rtt_avg_ms, "packet_loss_percent": result.packet_loss}
  116. except Exception:
  117. return None
  118. def get_local_net_details():
  119. """Получает локальный IP, MAC-адрес, имя активного интерфейса и IP шлюза."""
  120. details = {"local_ip": None, "mac_address": None, "interface_name": None, "gateway_ip": None}
  121. try:
  122. gws = netifaces.gateways()
  123. default_route = gws.get('default', {}).get(netifaces.AF_INET)
  124. if default_route:
  125. details['gateway_ip'] = default_route[0]
  126. active_interface = default_route[1]
  127. details['interface_name'] = active_interface
  128. addrs = netifaces.ifaddresses(active_interface)
  129. if netifaces.AF_INET in addrs:
  130. details['local_ip'] = addrs[netifaces.AF_INET][0]['addr']
  131. if netifaces.AF_LINK in addrs:
  132. details['mac_address'] = addrs[netifaces.AF_LINK][0]['addr'].upper().replace('-', ':')
  133. except Exception:
  134. pass
  135. return details
  136. def get_system_info():
  137. """Собирает имя хоста и внешний IP."""
  138. info = {"hostname": None, "external_ip": None}
  139. try:
  140. info["hostname"] = socket.gethostname()
  141. except:
  142. pass
  143. try:
  144. response = requests.get('https://api.ipify.org?format=json', timeout=5)
  145. response.raise_for_status()
  146. info["external_ip"] = response.json().get('ip')
  147. except:
  148. pass
  149. return info
  150. # *** Функции для взаимодействия с базой данных ***
  151. def create_database_and_table(db_file):
  152. """
  153. Создает базу данных и таблицу NetworkInfo, если они отсутствуют.
  154. """
  155. conn = sqlite3.connect(db_file)
  156. cursor = conn.cursor()
  157. # Создание таблицы NetworkInfo
  158. cursor.execute('''
  159. CREATE TABLE IF NOT EXISTS NetworkInfo (
  160. id INTEGER PRIMARY KEY AUTOINCREMENT,
  161. hostname TEXT,
  162. mac_address TEXT,
  163. local_ip TEXT,
  164. gateway_ip TEXT,
  165. external_ip TEXT,
  166. total_sent TEXT,
  167. total_recv TEXT,
  168. ping_gateway_ms REAL,
  169. loss_gateway_percent REAL,
  170. ping_ya_ru_ms REAL,
  171. loss_ya_ru_percent REAL,
  172. download_speed_mbps REAL,
  173. upload_speed_mbps REAL,
  174. server_name TEXT,
  175. server_location TEXT,
  176. server_latency REAL,
  177. created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
  178. )
  179. ''')
  180. conn.commit()
  181. conn.close()
  182. def save_to_db(db_file, data):
  183. """
  184. Сохраняет данные в базу данных.
  185. """
  186. conn = sqlite3.connect(db_file)
  187. cursor = conn.cursor()
  188. # Заполняем поля из data
  189. sql_insert_query = '''
  190. INSERT INTO NetworkInfo (
  191. hostname, mac_address, local_ip, gateway_ip, external_ip, total_sent, total_recv,
  192. ping_gateway_ms, loss_gateway_percent, ping_ya_ru_ms, loss_ya_ru_percent,
  193. download_speed_mbps, upload_speed_mbps, server_name, server_location, server_latency
  194. ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
  195. '''
  196. values = [
  197. data.get('hostname'), data.get('mac_address'), data.get('local_ip'),
  198. data.get('gateway_ip'), data.get('external_ip'), data.get('total_sent'),
  199. data.get('total_recv'), data.get('ping_gateway_ms'), data.get('loss_gateway_percent'),
  200. data.get('ping_ya_ru_ms'), data.get('loss_ya_ru_percent'), data.get('download_speed_mbps'),
  201. data.get('upload_speed_mbps'), data.get('server_name'), data.get('server_location'),
  202. data.get('server_latency')
  203. ]
  204. cursor.execute(sql_insert_query, values)
  205. conn.commit()
  206. conn.close()
  207. def view_database(db_file):
  208. """
  209. Возвращает список всех записей из базы данных.
  210. """
  211. conn = sqlite3.connect(db_file)
  212. cursor = conn.cursor()
  213. # Извлекаем все строки из таблицы
  214. cursor.execute("SELECT * FROM NetworkInfo ORDER BY created_at ASC;")
  215. rows = cursor.fetchall()
  216. conn.close()
  217. return rows
  218. # *** Графический интерфейс ***
  219. class App(tk.Tk):
  220. def __init__(self):
  221. super().__init__()
  222. self.title("Мониторинг сети")
  223. self.geometry("800x600") # Окно размером 800х600 пикселей
  224. self.create_widgets()
  225. self.db_file = 'network_reports.db'
  226. create_database_and_table(self.db_file)
  227. def create_widgets(self):
  228. frame_buttons = ttk.Frame(self)
  229. frame_buttons.pack(pady=(10, 10))
  230. btn_collect = ttk.Button(frame_buttons, text="Запустить мониторинг", command=self.collect_data)
  231. btn_view = ttk.Button(frame_buttons, text="Просмотреть отчёты", command=self.view_reports)
  232. btn_exit = ttk.Button(frame_buttons, text="Выход", command=self.quit)
  233. btn_collect.grid(row=0, column=0, padx=10)
  234. btn_view.grid(row=0, column=1, padx=10)
  235. btn_exit.grid(row=0, column=2, padx=10)
  236. # Таблица для просмотра результатов мониторинга
  237. columns = ("id", "hostname", "mac_address", "local_ip", "gateway_ip", "external_ip",
  238. "total_sent", "total_recv", "ping_gateway_ms", "loss_gateway_percent",
  239. "ping_ya_ru_ms", "loss_ya_ru_percent", "download_speed_mbps", "upload_speed_mbps",
  240. "server_name", "server_location", "server_latency", "created_at")
  241. self.tree = ttk.Treeview(self, columns=columns, show="headings")
  242. self.tree.pack(fill=tk.BOTH, expand=True)
  243. for col in columns:
  244. self.tree.heading(col, text=col.capitalize(), anchor=tk.W)
  245. self.tree.column(col, width=100, stretch=False)
  246. def collect_data(self):
  247. """
  248. Собирает всю необходимую информацию и сохраняет её в базу данных.
  249. """
  250. data = {}
  251. target_host = 'ya.ru'
  252. output_filename = "network_info_report.txt"
  253. # Сбор данных
  254. print("--- 1. Сбор базовой информации (IP, MAC, Hostname) ---")
  255. data.update(get_system_info())
  256. data.update(get_local_net_details())
  257. io_data = get_network_io_total()
  258. if io_data:
  259. data.update(io_data)
  260. print("Базовые данные собраны. ✅")
  261. # Пинги
  262. if data.get('gateway_ip'):
  263. print(f"\n--- 2. Проверка пинга до шлюза ({data['gateway_ip']}) ---")
  264. ping_gw_data = get_ping_and_loss(data['gateway_ip'])
  265. if ping_gw_data:
  266. data["ping_gateway_ms"] = ping_gw_data["avg_ping_ms"]
  267. data["loss_gateway_percent"] = ping_gw_data["packet_loss_percent"]
  268. print("Проверка завершена. 📶")
  269. print(f"\n--- 3. Проверка пинга до {target_host} ---")
  270. ping_ext_data = get_ping_and_loss(target=target_host)
  271. if ping_ext_data:
  272. data["ping_ya_ru_ms"] = ping_ext_data["avg_ping_ms"]
  273. data["loss_ya_ru_percent"] = ping_ext_data["packet_loss_percent"]
  274. print("Проверка завершена. 🎯")
  275. # Speedtest
  276. print("\n--- 4. Проверка скорости сети (Speedtest) ---")
  277. speed_data = get_network_speed()
  278. if speed_data:
  279. data.update(speed_data)
  280. print("Тестирование скорости завершено. 🚀")
  281. else:
  282. print("Тестирование скорости не выполнено (проверьте интернет-соединение).")
  283. # Форматирование и вывод отчета
  284. report_content = format_report(data, target_host)
  285. print(report_content)
  286. try:
  287. with open(output_filename, 'w', encoding='utf-8') as f:
  288. f.write(report_content)
  289. print(f"\n✅ Отчет успешно сохранен в файле: {output_filename} в папке {os.getcwd()}")
  290. except Exception as e:
  291. print(f"\n❌ Ошибка при записи отчета в файл: {e}")
  292. # Сохраняем данные в базу данных
  293. save_to_db(self.db_file, data)
  294. messagebox.showinfo("Готово", "Данные успешно собраны и сохранены!")
  295. def view_reports(self):
  296. """
  297. Загружает и показывает данные из базы данных в таблице.
  298. """
  299. rows = view_database(self.db_file)
  300. self.tree.delete(*self.tree.get_children())
  301. for row in rows:
  302. self.tree.insert("", tk.END, values=row)
  303. if __name__ == "__main__":
  304. app = App()
  305. app.mainloop()