上一次写过类似于这样的文章,但那个文章用了很少用的wmi库,且随着本地网卡的数量越多运行速度就越慢,今天采取了另一个办法,读取ipconfig的输出值,首先的办法还是通过socket发包获取本机生产IP,然后通过正则表达式找ipconfig中输出的所有IP地址格式的字符串。我们知道ipconfig的输出是有顺序的,不管是多少个网卡,多少个IP,IP下面就是掩码,紧接着是网关地址,具体就不多解释了。
这个版本的主要优势在于直接提取ipconfig /all对应网卡输出的结果,准确率有保障,关键的是速度非常的快。
#-*- encoding=utf-8 -*-
#
import socket
import re
import os
import ipaddress
pt = r'\d+\.\d+\.\d+\.\d+'
# 首选得到生产IP地址,这个地址绝对不会有错
ip = [(s.connect(('8.8.8.8', 53)), s.getsockname()[0], s.close()) for s in [socket.socket(socket.AF_INET, socket.SOCK_DGRAM)]][0][1]
RT = dict(IP=ip)
# 每一个网卡输出的信息都是有2个回车符,因此以2个回车符进行分割,存在ip地址的那整段字符文本其取出来
data = os.popen('ipconfig /all').read().strip().lower().split('\n\n')
for i in range(len(data)):
if ip in data[i]:
data = data[i-1]+ '\n' + data[i]
break
# 得到所有的IP地址列表,并从生产IP地址开始截取到最后,抛弃生产IP出现之前的所有IP
IPS = re.findall(pt,data)
IPS = IPS[IPS.index(ip):]
# 得到本地连接的名字
RT['NAME'] = data.split('\n')[0].split()[1][:-1]
# 掩码一定是紧接着生产IP地址出现的后面一个以255开头的地址
RT['MASK'] = [ i for i in IPS if i.startswith('255.')][0]
# 最后一个dns字符出现的位置以后的文本截取到的IP地址为DNS地址
RT['DNS'] = re.findall(pt, data[data.rfind(' dns '):])
# 第一个DNS地址前面的那个IP如果不是以255开头的,也不等于生产IP,且在生产IP/掩码范围内,那一定是网关地址
if RT['DNS']:
GATE = IPS[IPS.index(RT['DNS'][0]) - 1]
if not GATE.startswith('255.') and not GATE==ip and ipaddress.ip_address(GATE) in ipaddress.ip_network(f'{ip}/{RT["MASK"]}', strict=False):
RT['GATE'] = GATE
else:
# 也许配了DNS地址,但没有配网关,此时网关为空
RT['GATE'] = ''
else:
# 如果没有获取到DNS地址,判断最后一个IP是不是网关,判断的手法也是一样的
GATE = IPS[-1]
if not GATE.startswith('255.') and not GATE==ip and ipaddress.ip_address(GATE) in ipaddress.ip_network(f'{ip}/{RT["MASK"]}', strict=False):
RT['GATE'] = GATE
else:
# 如果判断不是网关,那么这个机器,没有配置DNS,也没有配置网关
RT['GATE'] = ''
# 现在寻找mac地址
RT['MAC'] = re.findall(r'..-..-..-..-..-..', data)[0]
print(RT)
















