本文使用开发环境:windows11、python 3.11.4、PyCharm 2023.2
subprocess模块
Python的subprocess模块提供了一种在Python中调用外部命令的方法。 它允许您在Python程序中启动新进程,连接到它们的输入/输出/错误管道,并等待它们完成。 subprocess.check_output(args, *, stdin=None, stderr=None, shell=False, universal_newlines=False) 参数说明: args: 是一个字符串或者字符串列表,表示要执行的命令及其参数。默认应该是一个字符串序列,如[‘df’, ‘-Th’]或(‘df’, ‘-Th’),也可以是一个字符串,如’df -Th’,但是此时需要把shell参数的值置为True。 shell: 如果为True,则将args作为一个shell命令执行。默认为False 可以使用'python代码来执行linux的命令 universal_newlines: 该参数影响的是'输入与输出'的'数据格式',如果universal_newlines=True,则其值应该是一个字符串。 1) 它的值'默认为False',此时stdout和stderr的输出是'字节'序列 2) 当该参数的值设置为'True'时,stdout和stderr的输出是"字符串" check_output()函数默认就会返回命令执行结果,所以不用设置stdout的值,如果我们希望在结果中捕获错误信息,可以执行stderr=subprocess.STDOUT。
for循环高级语法
for 语句后面跟上一个 if 判断语句,用于过滤掉那些不满足条件的结果项。 [表达式 for 变量 in 列表 if 条件] [out_exp_res for out_exp in input_list if condition] out_exp_res:列表生成元素表达式,可以是有返回值的函数。 for out_exp in input_list:迭代 input_list 将 out_exp 传入到 out_exp_res 表达式中。 if condition:条件语句,可以过滤列表中不符合条件的值。 split() 方法通过指定分隔符对字符串进行切片,该方法将字符串分割成子字符串并返回一个由这些子字符串组成的列表。 如果第二个参数 num 有指定值,则分割为 num+1 个子字符串。 split()方法特别适用于根据特定的分隔符将字符串拆分成多个部分。 strip() 方法用于移除字符串头尾指定的字符(默认为空格或换行符)或字符序列。 注意:该方法只能删除开头或是结尾的字符,不能删除中间部分的字符。 str.strip([chars]);
with open as f 用法
Python 中的 with 语句用于异常处理,封装了 try…except…finally 编码范式,提高了易用性。 要写入特定编码的文本文件,请给open()函数传入encoding参数,将字符串自动转换成指定编码 遇到有些编码不规范的文件,可能会遇到UnicodeDecodeError,因为在文本文件中可能夹杂了一些非法编码的字符。 遇到这种情况,open()函数还接收一个errors参数,表示如果遇到编码错误后如何处理? 最简单的方式是直接忽略 “with”是一个保留字,open函数用来打开文件, as f 指定文件的别名,“f”可以根据需要更改。 参考: https://wenku.baidu.com/view/d0a4eebb132de2bd960590c69ec3d5bbfd0adab8.html? w 打开一个文件只用于写入。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。 使用netsh wlan show profile命令可以显示已连接的和先前连接过的Wi-Fi网络的配置文件信息。 该命令的name参数指定了要显示的Wi-Fi网络的名称。 参数key=clear时,netsh wlan show profile命令会显示关键内容,包括Wi-Fi密码,而不是隐藏为星号或其他掩码形式。 这个命令的原理是,Windows操作系统将Wi-Fi网络的配置文件存储在系统中的一个数据库中。 netsh wlan show profile命令实际上是在访问这个数据库,并将相关信息以文本形式显示出来,其中包括了Wi-Fi密码。
具体代码如下
"""
Python的subprocess模块提供了一种在Python中调用外部命令的方法。
它允许您在Python程序中启动新进程,连接到它们的输入/输出/错误管道,并等待它们完成。
subprocess.check_output(args, *, stdin=None, stderr=None, shell=False, universal_newlines=False)
参数说明
args: 是一个字符串或者字符串列表,表示要执行的命令及其参数。
默认应该是一个字符串序列,如[‘df’, ‘-Th’]或(‘df’, ‘-Th’),也可以是一个字符串,如’df -Th’,但是此时需要把shell参数的值置为True。
shell: 如果为True,则将args作为一个shell命令执行。默认为False 可以使用'python代码来执行linux的命令
universal_newlines: 该参数影响的是'输入与输出'的'数据格式',如果universal_newlines=True,则其值应该是一个字符串。
1) 它的值'默认为False',此时stdout和stderr的输出是'字节'序列
2) 当该参数的值设置为'True'时,stdout和stderr的输出是"字符串"
check_output()函数默认就会返回命令执行结果,所以不用设置stdout的值,如果我们希望在结果中捕获错误信息,可以执行stderr=subprocess.STDOUT。
# 执行netsh命令获取wifi密码 运行外部命令并获取输出
# subprocess.check_output() 在python3的输出为bytes而非string,在实际使用过程中得增加一个解码过程decode(),不然会有问题
# decode中不带参数,默认是以utf-8解码
# 返回的其实是一个编码后的比特值,实际的编码格式取决于调用的命令,因此python3将解码过程交给应用层,也就是我们使用的人来做啦。
"""
import subprocess
# 获取配置文件的函数
def getProfiles(args):
"""
shell为true,代表执行一条
subprocess.check_output() 在python3的输出为bytes而非string,在实际使用过程中得增加一个解码过程decode(),不然会有问题
"""
# 执行指定的命令,并将结果以字符串形式返回
result = subprocess.check_output(args, shell=True).decode('GB2312')
"""
解析结果获取wifi配置文件名称
str.splitlines([keepends]) keepends是可选,代表在输出结果里是否保留换行符('\r', '\r\n', \n')
默认为 False,不包含换行符; 如果为 True,则保留换行符
"""
lines = result.splitlines(keepends=False) # 一行一行的截取字符串
"""
for line in lines:
if "所有用户配置文件 :" in line:
print(line.split(':')[1].strip()) # strip去除首尾空格
高级语法
for 语句后面跟上一个 if 判断语句,用于过滤掉那些不满足条件的结果项。
[表达式 for 变量 in 列表 if 条件]
[out_exp_res for out_exp in input_list if condition]
out_exp_res:列表生成元素表达式,可以是有返回值的函数。
for out_exp in input_list:迭代 input_list 将 out_exp 传入到 out_exp_res 表达式中。
if condition:条件语句,可以过滤列表中不符合条件的值。
split() 方法通过指定分隔符对字符串进行切片,该方法将字符串分割成子字符串并返回一个由这些子字符串组成的列表。
如果第二个参数 num 有指定值,则分割为 num+1 个子字符串。
split()方法特别适用于根据特定的分隔符将字符串拆分成多个部分。
strip() 方法用于移除字符串头尾指定的字符(默认为空格或换行符)或字符序列。
注意:该方法只能删除开头或是结尾的字符,不能删除中间部分的字符。
str.strip([chars]);
"""
# 获取配置文件
# profiles = [line.split(":")[1].strip() for line in lines if "所有用户配置文件 :" in line]
return [line.split(":")[1].strip() for line in lines if "所有用户配置文件 :" in line]
def getWifiPassword(args):
"""
Python 中的 with 语句用于异常处理,封装了 try…except…finally 编码范式,提高了易用性。
要写入特定编码的文本文件,请给open()函数传入encoding参数,将字符串自动转换成指定编码
遇到有些编码不规范的文件,可能会遇到UnicodeDecodeError,因为在文本文件中可能夹杂了一些非法编码的字符。
遇到这种情况,open()函数还接收一个errors参数,表示如果遇到编码错误后如何处理? 最简单的方式是直接忽略
with open as f 用法
“with”是一个保留字,open函数用来打开文件, as f 指定文件的别名,“f”可以根据需要更改。
参考: https://wenku.baidu.com/view/d0a4eebb132de2bd960590c69ec3d5bbfd0adab8.html?
w 打开一个文件只用于写入。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。
使用netsh wlan show profile命令可以显示已连接的和先前连接过的Wi-Fi网络的配置文件信息。
该命令的name参数指定了要显示的Wi-Fi网络的名称。
参数key=clear时,netsh wlan show profile命令会显示关键内容,包括Wi-Fi密码,而不是隐藏为星号或其他掩码形式。
这个命令的原理是,Windows操作系统将Wi-Fi网络的配置文件存储在系统中的一个数据库中。
netsh wlan show profile命令实际上是在访问这个数据库,并将相关信息以文本形式显示出来,其中包括了Wi-Fi密码。
"""
# 查询每个wifi配置文件的密码并保存到文件
with open('WIFI.csv', 'w', encoding='utf-8', errors='ignore') as f:
for profile in getProfiles(args):
try:
# f'' 格式化字符串 类似于前端模板字符串。 instruction: 指令
instruction = f'netsh wlan show profiles name = "{profile}" key=clear'
# 获取每个配置文件里面的内容 编码不对可能匹配不到
profile_comment = subprocess.check_output(instruction, shell=True).decode(encoding='GB2312',
errors='ignore')
comments_lines = profile_comment.splitlines() # 获取每一行的内容
# 遍历每一行的内容,并放在password变量中,如果字符"关键内容"在password变量中,则将password以“:”号分割截取下标为1的字符串
password = [password.split(':')[1].strip() for password in comments_lines if "关键内容" in password][0]
# 配置文件里面,部分SSID 名称 本身就存在乱码,所以用username打印出来依旧会乱码
# username = [username.split(':')[1].strip() for username in comments_lines if "SSID 名称" in username][0]
# 写入文件
f.write(f'{profile}密码为:【{password}】 \n')
print(f'{profile}密码为:【{password}】')
except:
print(f'无法获取{profile}的密码')
# 入口函数
if __name__ == '__main__':
command = 'netsh wlan show profiles'
getWifiPassword(command) # 调用函数
print('用户密码已保存在WIFI.csv文件中')