Python小工具,利用脚本快速获取本机全部已知WiFi密码
  • 分类:开发随笔
  • 发表:2019-06-07
  • 围观(230)
  • 评论(0)

端午回了次外婆家,端午佳节嘛总是要回去看看。天天在宿舍宅着容易被人说死宅是不是?刚好有个小表弟要高考,让他也感受一下来自小表哥的关心。回去给他加加油,想法很不错叻,说走就走啊。

貌似小表弟并不需要我的打气,心态好得很叻,去他学校的时候还在打篮球呢。这样一来感觉问题就不大了不是。但是晚上的时候问题还是来了。虽然在这边住了这么多次但是WiFi密码我还是没记住,手机刷机了密码全没了。没有WiFi这谁顶得住啊?这肯定难不倒学技术的我不是?WiFi万能钥匙不一样用鸭?貌似不能用,好险我带了电脑回来。电脑连过家里的WiFi,我记得可以查看已经连接的WiFi密码的哦。遇到问题就要解决对吧,爱学习的我立马从床上跳起来了👏👏👏......

问题解决

查看连接过的WiFi密码倒是没什么难度诶,一条cmd命令就解决了:Netsh wlan show profile name=【需要查看的WiFiSSID】key=clear。讲命令行参数替换成想要查看的WiFi的SSID就可以在输出信息看到密码了,方便的很叻,问题解决叻不是?可以回床上开心游戏叻。如果是这样就太水了吧。既然到了这里不如写个小脚本一键提取所有已知的WiFi密码,到时候用起来岂不是美滋滋?

本机保存的WiFi密码

代码实现

原理很简单,只需要简单的操作cmd命令就可以实现我们需要的功能。作为Python小脚本,最好只使用原生支持库完成,因为安装第三方库实在是很麻烦。小工具是一个系列哦,后面也会遵守这个原则的。

我个人理解这个工具更像一个小爬虫,只不过数据源从Web变成了本机,原理都是一样的。不需要构造requests请求,相比起来简单很多,我更倾向理解为API的调用,嘿嘿嘿😀。

爬取“网页”Ⅰ:Netsh wlan show profile(获取所有配置)
爬取“网页”Ⅱ:Netsh wlan show profile name=【需要查看的WiFiSSID】key=clear(获取详细配置)
支持库:os

os.popen可以实现Python对cmd的操作,返回的是file类型的对象,我们可以很简单的获取到控制台打印的数据。是不是和requests的请求有点异曲同工之妙。取到的数据我们读取到之后用简单的文本处理或者正则表达式把我们想要的数据提取出来就可以了,我这里用的是split欸嘿😝,你要问我为什么不用正则,我只能说正则我真的不是很会,hiahia🤙

具体代码不表啦,因为很简单,后面会贴出详细代码,这里说说我遇到的一个问题嘞。由于WiFi名称可能存在中文,但后返回结果在Python中转码GBK的时候就可能出现乱码,这个问题一度让我怀疑人生。看看具体代码:

temp = os.ponen("Netsh wlan show profile name=\"{}\" key=clear")
temp.read() # 这里转码异常就会抛出异常

问题的原因经过我半天的排查总算找出来叻。因为read()方法执行之后会对控制台返回的bytes数据转为GBK,但是返回数据有乱码所以转码就会报错。平时遇到这种问题我们可以在decode()方法内添加“ignore”参数防止这种报错,对于现在的情况read()方法显然不可以加忽略参数。我的解决方法是捕获异常,然后在异常信息内获取源数据,重新decode()并添加“ignore”参数,想想我真是个小机灵鬼哟。

try:
    temp = os.popen(cmd)
    info = temp.read()
    temp.close()
except Exception as e:
    info = e.args[1].decode("gbk", "ignore")

转码总是很烦,错误总让人抓狂,耐下心来分析其实都不难。这个技巧可以用在所有decode()上面。反正我在Python上遇到的转码问题不下上十次。找机会确实要把编码问题好好研究研究。

执行效果

总结

学习总是生活的小事做起啊,有时候这些小工具是很能提高生产力的。不得不说Python的强大啊,用起来真的是超级舒服不是么?虽然作为动态语言有的时候联想会有点问题,但是这不是有Pycharm么?作为开发者来说有Jetbrains这样的公司我真的会做梦傻笑,嘿嘿嘿。

风继续吹,呼~~~呼~~呼~


import os

class WifiPwd():
    all_settings_cmd = "Netsh wlan show profile"
    single_password = "Netsh wlan show profile name=\"{}\" key=clear"

    @classmethod
    def get_all_pwd(cls):
        names = cls.__get_all_settings()
        for name in names:
            cmd = cls.single_password.format(name)
            try:
                temp = os.popen(cmd)
                info = temp.read()
                temp.close()
            except Exception as e:
                info = e.args[1].decode("gbk", "ignore")
            result = cls.__parse_password(info)
            print("SSID : {result[ssid]} --- Password : {result[password]}".format(result=result))

    @classmethod
    def __get_all_settings(cls):
        settings = os.popen(cls.all_settings_cmd)
        temp = settings.read().split("用户配置文件\n-------------\n")[1].strip()
        names = []
        for setting in temp.split("\n"):
            names.append(setting.split(" : ")[1])
        settings.close()
        return names

    @classmethod
    def __parse_password(cls, info):
        name = ""
        password = ""
        for line in info.split("\n"):
            if "名称                   :" in line:
                name = line.split(":")[1].strip()
                continue

            if "关键内容" in line:
                password = line.split(":")[1].strip()
        return {"ssid": name, "password": password or "没找到密码"}


if __name__ == '__main__':
    print("本小工具由Weiney开发")
    print("Blog:www.weiney.com")
    print("-" * 24)
    WifiPwd.get_all_pwd()
    print("-" * 24)
    input("所有本地WiFi密码获取完成,按回车键退出")

共有 0 条评论

Top