В данной статье речь пойдет о парсинге. Не о том, когда получаются данные веб-сайта. Этот парсинг, в более правильном варианте, все же называется scrapping. А о том, который подразумевает под собой парсинг данных. В данном случае текстовых. Ну и немного о получении данных о сетевых адаптерах, установленных в системе.
Почему я решил написать данную статью? Дело в том, что не так давно я столкнулся с тем, что многие новички, в частности присутствующие, здесь, на форуме, не умеют парсить текстовые данные. Самый первый способ, с помощью которого они пытаются вытащить данные из километровой портянки, это использование регулярных выражений. И да, я не спорю, если уметь пользоваться регулярными выражениями, найти можно что угодно. Да и получить тот же самый e-mail или веб-адрес гораздо легче. Но иногда использование регулярных выражений попросту излишне. Давайте рассмотрим, как можно распарсить вывод команды «ipconfig /all», с помощью которой можно получить данные обо всех сетевых адаптерах, установленных в системе, а также их параметрах.
Не сказать, что данный вывод парсить одно удовольствие. Дело в том, что нам нужно предусмотреть один небольшой нюанс, а именно, исключить привязку к какому-либо естественному языку. Ведь вывод данной команды, а в частности название параметров, переведено на тот язык, который используется в системе. А потому привязаться к выводу на конкретном языке можно, но нежелательно, потому, что в будущем вам может понадобиться использовать тот же скрипт на другой системе и естественно, ничего не получиться без изменения самого скрипта.
Давайте посмотрим на сам вывод. Ниже представлен скриншот командной строки.
Это виртуальная машина. Я намеренно добавил в нее несколько сетевых адаптеров, для того чтобы немного усложнить парсинг. На первый взгляд зацепиться за какой-либо элемент в виде повторяющегося паттерна здесь не особо представляется возможным. Самое простое, что мы можем сделать в данном случае, это разделить вывод на строки с помощью split("\r\n").
Для начала импортируем в код необходимые библиотеки. В нашем случае, так как сторонними библиотеками не «из коробки» мы пользоваться не будем, блок импорта будет выглядеть следующим образом:
Получение текста с маркерами для последующего разбиения на блоки и строки в них
Давайте создадим функцию, которую назовем all_adapters(). И теперь напишем код, который будет выполнять команду и делить вывод на строки.
Как видите, код продолжается дальше, так как на этом итерация не закончена. После того, как мы получим вывод команды в переменную out, создадим текстовую переменную text, в которую будем складывать полученные и обработанные строки. Так как нам не за что особо зацепиться, чтобы разбить полученные строки на блоки относящиеся к одному адаптеру, мы добавим в формируемый текст свои маркеры, по которым уже и будем выполнять разбиение.
Для начала проверим, не является ли строка после разбиения пустой. Если да, итерируемся по списку дальше. Если строка не пуста, проверяем, не содержит ли она в себе текст к которому можно привязаться, так как, думаю, что вывод этого текста на любом языке будет одинаковым – «Ethernet». Если данный текст присутствует в строке, добавляем к переменной text «~», а также содержимое текущей строки, у которой предварительно обрежем пустые значения, если они есть в начале и конце с помощью strip(). Ну и во всех остальных случаях к переменной text добавляем значение этой переменной, «||», который будет служить разделителем между строками и текущее содержимое строки списка.
Таким образом, мы получили текстовую переменную text, в которой содержаться как символы, по которым мы можем разбить данный текст на блоки, так и символы, по которым мы можем разбить текст в блоках на строки.
Разбиение текста на блоки и строки. Получение данных и формирование словаря из значений
Дальше будем работать с переменной текст, содержащей нужные нам параметры. Для начала создадим цикл, в котором будем итерироваться по тексту разбитому на блоки с помощью добавленного в текст маркера «~».
Создадим еще один цикл, в котором будем итерироваться уже внутри блока, который разобьем на словарь с помощью маркера «||». Так как не все элементы в полученном списке являются параметрами, нужно забрать из списка названия сетевых адаптеров, которые добавим в словарь и, уже в них, будем складывать параметры, получаемые из блока.
Проверяем, содержит ли текущий итерируемый элемент списка значение «Ethernet». Если да, создаем в общем словаре раздел с названием адаптера. Объявляем переменную keys и в нее присваиваем значение только что созданного словаря. Это необходимо для того, чтобы складывать получаемые далее параметры куда нужно. Вот код, где мы делаем проверку.
Если мы не присвоим значение только что созданного словаря в переменную, значение network_adapters[item.replace(":", "")] будем всегда меняться, так как item будет содержать в себе, хоть и в текущем блоке другое значение. Ну и с помощью continue переходим к следующей итерации.
Теперь нужно проверить, не содержит ли в себе параметр пустого значения. Делим элемент списка по « :» и забираем второй элемент. Если он пустой, то переходим к следующей итерации.
Так как не все сетевые адаптеры активны, а зачастую только один из них, это если брать в расчет не серверную машину, у неактивных адаптеров нет ip-адреса. А вот у активных он есть. Но, так как мы не можем привязаться к конкретному языку, чтобы выполнить проверку по названию параметра, нужно проверить, есть ли он. Более того, значение здесь выдается в не особо удобном для последующего использования виде: 10.0.2.15(Основной). То же самое и с IPv6 адресом. И вот этот вот основной нужно убрать, да еще и проверить, является ли данное значение адресом вообще. Для этого будем использовать функции IPv4Address, IPv6Address библиотеки ipaddress.
Получаем значение элемента. Делим его по « :». Забираем второй элемент, который дополнительно делим по открывающей скобке. И загоняем в функцию IPv4Address. Если элемент не является ipv4 адресом, функция выбросит исключение. Если нет, добавляем ключ и значение в словарь. То же самое проделываем и с адресом ipv6.
Для чего такие сложности? Дело в том, что некоторые значения могут иметь в своих названиях скобки. А значит просто так, не проверив адрес это или нет, мы их разделить не можем. А если разделим без проверки, получим только часть названия. Для примера, название сетевого адаптера: Intel(R) PRO/1000 MT Desktop Adapter #4.
Ну и после проверки ipv6 адреса, если он вызовет исключение, добавляем остальные значения, которые не относятся к адресам в словарь.
В общем-то, словарь на данном этапе уже будет готов. Но, на всякий случай, мало ли что пойдет не так, чтобы не потерять уже полученные данные, сохраним их в папку скрипта в json, после чего вернем словарь из функции.
Получение локального ipv4-адреса
Что ж, хорошо. Параметры адаптеров, которые есть в системе, мы получили. Но, мы до сих пор не знаем, какой из адаптеров является основным, то есть, используемым по умолчанию. Нужно получить какое-то уникальное значение, по которому можно определить, да, вот это вот и есть нужный адаптер, и забрать его значения. Одним из таких значений является локальный ip-адрес, который и будет принадлежать сетевому адаптеру, который используется по умолчанию. Для получения локального ipv4 адреса используем функцию со SO. Она достаточно хорошо делает свое дело.
Получение сетевого адаптера используемого в системе по умолчанию и его параметров
Теперь, когда у нас есть словарь с параметрами сетевых адаптеров и локальный ipv4 адрес, мы можем получить сетевой адаптер по умолчанию. Создадим для этого отдельную функцию, в которую передадим полученный из предыдущей функции словарь, default_network(network_adapters: dict, loc_ip: str), также в эту же функцию мы передадим полученный ipv4 адрес.
Создадим словарь, в который будем помещать значения из словаря со всеми адаптерами по одному. То есть, запускаем цикл и итерируемся по ключам словаря. После того, как мы составим словарь из значений одного из ключей, мы будем итерироваться по созданному словарю для проверки, есть ли в нем искомый ipv4 адрес. И если есть, возвращаем уже готовый словарь с параметрами адаптера из функции. Если же нет, продолжаем итерацию.
Запуск функций созданных ранее
Ну и напоследок создадим функцию main(), в которой будем запускать созданные ранее функции, а также проверять полученные значения словаря. Если словарь с сетевым адаптером по умолчанию пустой, а такое может быть в случае отсутствия интернета, выводим на печать общий словарь. Если же все в порядке, выводим на печать значения обоих словарей.
А это полученные json.
А на этом, пожалуй, все.
Надеюсь, что с поставленной задачей, а именно показать как парсить вывод команд операционной системы, я справился. Получение параметров сетевых адаптеров, это уже второстепенная задача.
Спасибо за внимание. Надеюсь, информация будет вам полезна
Почему я решил написать данную статью? Дело в том, что не так давно я столкнулся с тем, что многие новички, в частности присутствующие, здесь, на форуме, не умеют парсить текстовые данные. Самый первый способ, с помощью которого они пытаются вытащить данные из километровой портянки, это использование регулярных выражений. И да, я не спорю, если уметь пользоваться регулярными выражениями, найти можно что угодно. Да и получить тот же самый e-mail или веб-адрес гораздо легче. Но иногда использование регулярных выражений попросту излишне. Давайте рассмотрим, как можно распарсить вывод команды «ipconfig /all», с помощью которой можно получить данные обо всех сетевых адаптерах, установленных в системе, а также их параметрах.
Не сказать, что данный вывод парсить одно удовольствие. Дело в том, что нам нужно предусмотреть один небольшой нюанс, а именно, исключить привязку к какому-либо естественному языку. Ведь вывод данной команды, а в частности название параметров, переведено на тот язык, который используется в системе. А потому привязаться к выводу на конкретном языке можно, но нежелательно, потому, что в будущем вам может понадобиться использовать тот же скрипт на другой системе и естественно, ничего не получиться без изменения самого скрипта.
Давайте посмотрим на сам вывод. Ниже представлен скриншот командной строки.
Это виртуальная машина. Я намеренно добавил в нее несколько сетевых адаптеров, для того чтобы немного усложнить парсинг. На первый взгляд зацепиться за какой-либо элемент в виде повторяющегося паттерна здесь не особо представляется возможным. Самое простое, что мы можем сделать в данном случае, это разделить вывод на строки с помощью split("\r\n").
Для начала импортируем в код необходимые библиотеки. В нашем случае, так как сторонними библиотеками не «из коробки» мы пользоваться не будем, блок импорта будет выглядеть следующим образом:
Python:
import json
import subprocess
from ipaddress import IPv4Address, IPv6Address
from pathlib import Path
from socket import socket, AF_INET, SOCK_DGRAM
Получение текста с маркерами для последующего разбиения на блоки и строки в них
Давайте создадим функцию, которую назовем all_adapters(). И теперь напишем код, который будет выполнять команду и делить вывод на строки.
Python:
def all_adapters() -> dict:
network_adapters = dict()
out = subprocess.check_output("ipconfig /all", shell=True).decode("cp866")
text = ""
for item in out.split("\r\n"):
Как видите, код продолжается дальше, так как на этом итерация не закончена. После того, как мы получим вывод команды в переменную out, создадим текстовую переменную text, в которую будем складывать полученные и обработанные строки. Так как нам не за что особо зацепиться, чтобы разбить полученные строки на блоки относящиеся к одному адаптеру, мы добавим в формируемый текст свои маркеры, по которым уже и будем выполнять разбиение.
Для начала проверим, не является ли строка после разбиения пустой. Если да, итерируемся по списку дальше. Если строка не пуста, проверяем, не содержит ли она в себе текст к которому можно привязаться, так как, думаю, что вывод этого текста на любом языке будет одинаковым – «Ethernet». Если данный текст присутствует в строке, добавляем к переменной text «~», а также содержимое текущей строки, у которой предварительно обрежем пустые значения, если они есть в начале и конце с помощью strip(). Ну и во всех остальных случаях к переменной text добавляем значение этой переменной, «||», который будет служить разделителем между строками и текущее содержимое строки списка.
Python:
for item in out.split("\r\n"):
if item == "":
continue
elif "Ethernet" in item:
text = f"{text.strip()}~{item.strip()}"
else:
text = f"{text.strip()}||{item.strip()}"
Таким образом, мы получили текстовую переменную text, в которой содержаться как символы, по которым мы можем разбить данный текст на блоки, так и символы, по которым мы можем разбить текст в блоках на строки.
Разбиение текста на блоки и строки. Получение данных и формирование словаря из значений
Дальше будем работать с переменной текст, содержащей нужные нам параметры. Для начала создадим цикл, в котором будем итерироваться по тексту разбитому на блоки с помощью добавленного в текст маркера «~».
Создадим еще один цикл, в котором будем итерироваться уже внутри блока, который разобьем на словарь с помощью маркера «||». Так как не все элементы в полученном списке являются параметрами, нужно забрать из списка названия сетевых адаптеров, которые добавим в словарь и, уже в них, будем складывать параметры, получаемые из блока.
Проверяем, содержит ли текущий итерируемый элемент списка значение «Ethernet». Если да, создаем в общем словаре раздел с названием адаптера. Объявляем переменную keys и в нее присваиваем значение только что созданного словаря. Это необходимо для того, чтобы складывать получаемые далее параметры куда нужно. Вот код, где мы делаем проверку.
Python:
if "Ethernet" in item:
network_adapters[item.replace(":", "")] = dict()
keys = network_adapters[item.replace(":", "")]
continue
Если мы не присвоим значение только что созданного словаря в переменную, значение network_adapters[item.replace(":", "")] будем всегда меняться, так как item будет содержать в себе, хоть и в текущем блоке другое значение. Ну и с помощью continue переходим к следующей итерации.
Теперь нужно проверить, не содержит ли в себе параметр пустого значения. Делим элемент списка по « :» и забираем второй элемент. Если он пустой, то переходим к следующей итерации.
Python:
try:
if item.split(" :")[1].strip() == "":
continue
except IndexError:
continue
Так как не все сетевые адаптеры активны, а зачастую только один из них, это если брать в расчет не серверную машину, у неактивных адаптеров нет ip-адреса. А вот у активных он есть. Но, так как мы не можем привязаться к конкретному языку, чтобы выполнить проверку по названию параметра, нужно проверить, есть ли он. Более того, значение здесь выдается в не особо удобном для последующего использования виде: 10.0.2.15(Основной). То же самое и с IPv6 адресом. И вот этот вот основной нужно убрать, да еще и проверить, является ли данное значение адресом вообще. Для этого будем использовать функции IPv4Address, IPv6Address библиотеки ipaddress.
Получаем значение элемента. Делим его по « :». Забираем второй элемент, который дополнительно делим по открывающей скобке. И загоняем в функцию IPv4Address. Если элемент не является ipv4 адресом, функция выбросит исключение. Если нет, добавляем ключ и значение в словарь. То же самое проделываем и с адресом ipv6.
Для чего такие сложности? Дело в том, что некоторые значения могут иметь в своих названиях скобки. А значит просто так, не проверив адрес это или нет, мы их разделить не можем. А если разделим без проверки, получим только часть названия. Для примера, название сетевого адаптера: Intel(R) PRO/1000 MT Desktop Adapter #4.
Ну и после проверки ipv6 адреса, если он вызовет исключение, добавляем остальные значения, которые не относятся к адресам в словарь.
Python:
try:
IPv4Address(item.split(" :")[1].strip().split("(")[0])
keys.update({item.split(" :")[0].replace(".", "").strip(): item.split(" :")[1].strip().split("(")[0]})
continue
except Exception:
pass
try:
IPv6Address(item.split(" :")[1].strip().split("(")[0])
keys.update({item.split(" :")[0].replace(".", "").strip(): item.split(" :")[1].strip().split("(")[0]})
continue
except Exception:
keys.update({item.split(" :")[0].replace(".", "").strip(): item.split(" :")[1].strip()})
Python:
for tx in text.split("~")[1:]:
for item in tx.split("||"):
if "Ethernet" in item:
network_adapters[item.replace(":", "")] = dict()
keys = network_adapters[item.replace(":", "")]
continue
try:
if item.split(" :")[1].strip() == "":
continue
except IndexError:
continue
try:
IPv4Address(item.split(" :")[1].strip().split("(")[0])
keys.update({item.split(" :")[0].replace(".", "").strip(): item.split(" :")[1].strip().split("(")[0]})
continue
except Exception:
pass
try:
IPv6Address(item.split(" :")[1].strip().split("(")[0])
keys.update({item.split(" :")[0].replace(".", "").strip(): item.split(" :")[1].strip().split("(")[0]})
continue
except Exception:
keys.update({item.split(" :")[0].replace(".", "").strip(): item.split(" :")[1].strip()})
В общем-то, словарь на данном этапе уже будет готов. Но, на всякий случай, мало ли что пойдет не так, чтобы не потерять уже полученные данные, сохраним их в папку скрипта в json, после чего вернем словарь из функции.
Python:
with open(Path.cwd() / 'ethernet_adapters.json', 'w', encoding='utf-8') as js:
json.dump(network_adapters, js, indent=4, ensure_ascii=False)
return network_adapters
Python:
def all_adapters():
"""
Парсинг вывода команды ipconfig /all.
Выполняем команду. Для того чтобы разделить вывод на блоки,
в каждом из которых будет один адаптер, приводим строку к нужному
виду, указав в качестве разделителя "~". Также на будущее делим все
остальные строки с помощью "||".
Затем итерируемся по созданному нами текстовому блоку. Делим его по
разделителям для начала на блоки, в которых содержаться данные об
одном адаптере. Затем, в каждом блоке делим содержимое на список из
строк по "||". Затем итерируемся по полученному списку, забираем
название адаптера. Создаем в словаре раздел с адаптером. Итерируемся
дальше, пропускаем пустые строки, проверяем адреса ipv4 и ipv6, для
того, чтобы убрать у них приставку (в русском варианте: Основной).
Делим элементы списка и добавляем в словарь полученные значения.
Затем записываем полученные данные в json для лучшей сохранности и
возвращаем полученный словарь из функции.
:return: словарь со всеми адаптерами в системе.
"""
network_adapters = dict()
out = subprocess.check_output("ipconfig /all", shell=True).decode("cp866")
text = ""
for item in out.split("\r\n"):
if item == "":
continue
elif "Ethernet" in item:
text = f"{text.strip()}~{item.strip()}"
else:
text = f"{text.strip()}||{item.strip()}"
for tx in text.split("~")[1:]:
for item in tx.split("||"):
if "Ethernet" in item:
network_adapters[item.replace(":", "")] = dict()
keys = network_adapters[item.replace(":", "")]
continue
try:
if item.split(" :")[1].strip() == "":
continue
except IndexError:
continue
try:
IPv4Address(item.split(" :")[1].strip().split("(")[0])
keys.update({item.split(" :")[0].replace(".", "").strip(): item.split(" :")[1].strip().split("(")[0]})
continue
except Exception:
pass
try:
IPv6Address(item.split(" :")[1].strip().split("(")[0])
keys.update({item.split(" :")[0].replace(".", "").strip(): item.split(" :")[1].strip().split("(")[0]})
continue
except Exception:
keys.update({item.split(" :")[0].replace(".", "").strip(): item.split(" :")[1].strip()})
with open(Path.cwd() / 'ethernet_adapters.json', 'w', encoding='utf-8') as js:
json.dump(network_adapters, js, indent=4, ensure_ascii=False)
return network_adapters
Получение локального ipv4-адреса
Что ж, хорошо. Параметры адаптеров, которые есть в системе, мы получили. Но, мы до сих пор не знаем, какой из адаптеров является основным, то есть, используемым по умолчанию. Нужно получить какое-то уникальное значение, по которому можно определить, да, вот это вот и есть нужный адаптер, и забрать его значения. Одним из таких значений является локальный ip-адрес, который и будет принадлежать сетевому адаптеру, который используется по умолчанию. Для получения локального ipv4 адреса используем функцию со SO. Она достаточно хорошо делает свое дело.
Python:
def local_ipv4() -> str:
"""
Получаем локальный IP-адрес с помощью установки
соединения на адрес 10.255.255.255. В ответ получаем
имя сокета, которое и является адресом.
:return: возвращает локальный IP-адрес или адрес локальной петли
в случае возникновения исключения.
"""
ip = None
st = socket(AF_INET, SOCK_DGRAM)
try:
st.connect(('10.255.255.255', 1))
ip = st.getsockname()[0]
except Exception:
ip = '127.0.0.1'
finally:
st.close()
return ip
Получение сетевого адаптера используемого в системе по умолчанию и его параметров
Теперь, когда у нас есть словарь с параметрами сетевых адаптеров и локальный ipv4 адрес, мы можем получить сетевой адаптер по умолчанию. Создадим для этого отдельную функцию, в которую передадим полученный из предыдущей функции словарь, default_network(network_adapters: dict, loc_ip: str), также в эту же функцию мы передадим полученный ipv4 адрес.
Создадим словарь, в который будем помещать значения из словаря со всеми адаптерами по одному. То есть, запускаем цикл и итерируемся по ключам словаря. После того, как мы составим словарь из значений одного из ключей, мы будем итерироваться по созданному словарю для проверки, есть ли в нем искомый ipv4 адрес. И если есть, возвращаем уже готовый словарь с параметрами адаптера из функции. Если же нет, продолжаем итерацию.
Python:
def default_network(network_adapters: dict, loc_ip: str) -> dict:
"""
Получаем сетевой адаптер используемый по-умолчанию.
Итерируемся по ранее составленному словарю, составляем промежуточный
словарь, итерируемся по нему и проверяем, есть ли в нем значение,
которое соответствует ipv4-адресу по-умолчанию. Если да, возвращаем
словарь из функции. Если нет, обнуляем словарь и двигаемся дальше.
:param network_adapters: словарь со всеми сетевыми адаптерами в системе.
:param loc_ip: локальный ipv4 адрес.
:return: словарь с сетевым адаптером по-умолчанию.
"""
default_adapter = dict()
for network in network_adapters:
default_adapter[network] = dict()
for adapter in network_adapters[network]:
default_adapter[network].update({adapter: network_adapters[network][adapter]})
for loc in default_adapter[network]:
if loc_ip == default_adapter[network][loc]:
with open(Path.cwd() / 'ethernet_default.json', 'w', encoding='utf-8') as js:
json.dump(default_adapter, js, indent=4, ensure_ascii=False)
return default_adapter
default_adapter.clear()
Запуск функций созданных ранее
Ну и напоследок создадим функцию main(), в которой будем запускать созданные ранее функции, а также проверять полученные значения словаря. Если словарь с сетевым адаптером по умолчанию пустой, а такое может быть в случае отсутствия интернета, выводим на печать общий словарь. Если же все в порядке, выводим на печать значения обоих словарей.
Python:
def main():
adapters = all_adapters()
ipv4 = local_ipv4()
default = default_network(adapters, ipv4)
if default is None:
if adapters is not None:
print(adapters)
else:
print(adapters)
print(default)
if __name__ == "__main__":
main()
Python:
"""
Скрипт для получения данных о сетевых адаптерах
используемых в системе, а также их параметров, которые
доступны при выводе команды "ipconfig /all".
"""
import json
import subprocess
from ipaddress import IPv4Address, IPv6Address
from pathlib import Path
from socket import socket, AF_INET, SOCK_DGRAM
def all_adapters():
"""
Парсинг вывода команды ipconfig /all.
Выполняем команду. Для того чтобы разделить вывод на блоки,
в каждом из которых будет один адаптер, приводим строку к нужному
виду, указав в качестве разделителя "~". Также на будущее делим все
остальные строки с помощью "||".
Затем итерируемся по созданному нами текстовому блоку. Делим его по
разделителям для начала на блоки, в которых содержаться данные об
одном адаптере. Затем, в каждом блоке делим содержимое на список из
строк по "||". Затем итерируемся по полученному списку, забираем
название адаптера. Создаем в словаре раздел с адаптером. Итерируемся
дальше, пропускаем пустые строки, проверяем адреса ipv4 и ipv6, для
того, чтобы убрать у них приставку (в русском варианте: Основной).
Делим элементы списка и добавляем в словарь полученные значения.
Затем записываем полученные данные в json для лучшей сохранности и
возвращаем полученный словарь из функции.
:return: словарь со всеми адаптерами в системе.
"""
network_adapters = dict()
out = subprocess.check_output("ipconfig /all", shell=True).decode("cp866")
text = ""
for item in out.split("\r\n"):
if item == "":
continue
elif "Ethernet" in item:
text = f"{text.strip()}~{item.strip()}"
else:
text = f"{text.strip()}||{item.strip()}"
for tx in text.split("~")[1:]:
for item in tx.split("||"):
if "Ethernet" in item:
network_adapters[item.replace(":", "")] = dict()
keys = network_adapters[item.replace(":", "")]
continue
try:
if item.split(" :")[1].strip() == "":
continue
except IndexError:
continue
try:
IPv4Address(item.split(" :")[1].strip().split("(")[0])
keys.update({item.split(" :")[0].replace(".", "").strip(): item.split(" :")[1].strip().split("(")[0]})
continue
except Exception:
pass
try:
IPv6Address(item.split(" :")[1].strip().split("(")[0])
keys.update({item.split(" :")[0].replace(".", "").strip(): item.split(" :")[1].strip().split("(")[0]})
continue
except Exception:
keys.update({item.split(" :")[0].replace(".", "").strip(): item.split(" :")[1].strip()})
with open(Path.cwd() / 'ethernet_adapters.json', 'w', encoding='utf-8') as js:
json.dump(network_adapters, js, indent=4, ensure_ascii=False)
return network_adapters
def local_ipv4() -> str:
"""
Получаем локальный IP-адрес с помощью установки
соединения на адрес 10.255.255.255. В ответ получаем
имя сокета, которое и является адресом.
:return: возвращает локальный IP-адрес или адрес локальной петли
в случае возникновения исключения.
"""
ip = None
st = socket(AF_INET, SOCK_DGRAM)
try:
st.connect(('10.255.255.255', 1))
ip = st.getsockname()[0]
except Exception:
ip = '127.0.0.1'
finally:
st.close()
return ip
def default_network(network_adapters: dict, loc_ip: str) -> dict:
"""
Получаем сетевой адаптер используемый по-умолчанию.
Итерируемся по ранее составленному словарю, составляем промежуточный
словарь, итерируемся по нему и проверяем, есть ли в нем значение,
которое соответствует ipv4-адресу по-умолчанию. Если да, возвращаем
словарь из функции. Если нет, обнуляем словарь и двигаемся дальше.
:param network_adapters: словарь со всеми сетевыми адаптерами в системе.
:param loc_ip: локальный ipv4 адрес.
:return: словарь с сетевым адаптером по-умолчанию.
"""
default_adapter = dict()
for network in network_adapters:
default_adapter[network] = dict()
for adapter in network_adapters[network]:
default_adapter[network].update({adapter: network_adapters[network][adapter]})
for loc in default_adapter[network]:
if loc_ip == default_adapter[network][loc]:
with open(Path.cwd() / 'ethernet_default.json', 'w', encoding='utf-8') as js:
json.dump(default_adapter, js, indent=4, ensure_ascii=False)
return default_adapter
default_adapter.clear()
def main():
adapters = all_adapters()
ipv4 = local_ipv4()
default = default_network(adapters, ipv4)
if default is None:
if adapters is not None:
print(adapters)
else:
print(adapters)
print(default)
if __name__ == "__main__":
main()
А это полученные json.
А на этом, пожалуй, все.
Надеюсь, что с поставленной задачей, а именно показать как парсить вывод команд операционной системы, я справился. Получение параметров сетевых адаптеров, это уже второстепенная задача.
Спасибо за внимание. Надеюсь, информация будет вам полезна