【Python】分析和宝宝最近的消息和邮件
一、成果
这是我自己搭建的一个网站 猫九的头像很可爱啊的个人博客,会不定期更新自己学到的新知识,欢迎大家访问!
1.1为什么会有这篇文章
上上次和宝宝吵架的时候,宝宝说丢失了一部分聊天记录找不回了,就一直在想怎么样才能恢复和宝宝的聊天记录。之后又碰巧学了用Appium来做手机自动化测试,就爬取了和宝宝近几天的聊天记录来做文本分析,同时也分析了和宝宝来往的邮件,用可视化的图表展示我们有多喜欢对方。
1.2成果
和宝宝在过去六个月的信件往来数量:
收到宝宝的邮件中的词频统计和词云图:
给宝宝写的邮件中的词频统计和词云图:
和宝宝最近聊天记录的文本分析:
二、Appium库获取微信聊天记录
2.1环境准备
windows版本 | Windows 10 |
---|---|
Appium客户端 | Appium-Python-Client 2.1.4 |
Android SDK 版本 | Android 11.0® |
Appium版本 | Appium v1.15.1 |
Python 版本 | Python 3.10.4 |
手机版本 | Android 10 |
请先打开手机USB调试功能,并用USB连接手机和电脑。
2.2.重要步骤代码解释
2.2.1命令行下查看电脑连接的设备
adb devices
若出现下列信息证明连接成功
List of devices attachedNPYDU19301006477 device
2.2.2获取APP Package和启动Activity
手机打开至微信界面,命令行输入下面命令获取APP Package和启动Activity:
adb shell dumpsys activity recents | find "intent={"
如图所示:
2.2.3设置desired_caps参数
desired_caps = { 'platformName': 'Android', # 被测手机是安卓 'platformVersion': '10', # 手机安卓版本 'deviceName': 'xxx', # 设备名,安卓手机可以随意填写 'appPackage': 'com.tencent.mm', # 启动APP Package名称 'appActivity': '.ui.LauncherUI', # 启动Activity名称 'unicodeKeyboard': False, # 使用自带输入法,输入中文时填True 'resetKeyboard': True, # 执行完程序恢复原来输入法 'noReset': True, # 不要重置App 'newCommandTimeout': 6000, 'automationName': 'UiAutomator2'}
2.2.4启动检查器会话
启动Appium,启动检查器会话:
选择自定义服务器->编辑JSON Representation->启动会话
JSON Representation的内容(其实就是前面设置的desired_caps参数,只不过Python和Json的语法格式不一样)如下:
{ "platformName": "Android", "platformVersion": "10", "deviceName": "xxx", "appPackage": "com.tencent.mm", "appActivity": ".ui.LauncherUI", "unicodeKeyboard": false, "resetKeyboard": true, "noReset": true, "newCommandTimeout": 6000, "automationName": "UiAutomator2"}
启动会话后,可以看到如下界面:
2.2.5定位元素
以定位中的一个元素为例:
driver.find_element(By.ID, 'fhz').click()
2.2.6设置滑动参数,获取聊天消息
由于webdriver对象只能选择当前页面的所有微信聊天消息,所以需要不断滑动窗口来更新页面,进而获取所有的微信聊天消息。首先获取当前屏幕的宽和高:
x = driver.get_window_size()['width'] # 获取屏幕的高y = driver.get_window_size()['height'] # 获取屏幕的宽
设置一定次数的循环来滑动窗口获取消息:
for i in range(1000): driver.swipe(9/ 10 * x, 1 / 4 * y, 9 / 10* x, 5 / 6 * y, 600) # 从屏幕的右上方滑动到右下方 msgs = driver.find_elements(By.ID, 'b4b') #定位到微信消息 for msg in msgs: file.write(msg.text + '\n') #将每一条消息的文本内容写入文件file
2.3完整代码
from appium import webdriverfrom selenium.webdriver.common.by import Bydesired_caps = { 'platformName': 'Android', # 被测手机是安卓 'platformVersion': '10', # 手机安卓版本 'deviceName': 'xxx', # 设备名,安卓手机可以随意填写 'appPackage': 'com.tencent.mm', # 启动APP Package名称 'appActivity': '.ui.LauncherUI', # 启动Activity名称 'unicodeKeyboard': False, # 使用自带输入法,输入中文时填True 'resetKeyboard': True, # 执行完程序恢复原来输入法 'noReset': True, # 不要重置App 'newCommandTimeout': 6000, 'automationName': 'UiAutomator2',}file = open("聊天记录3.txt", "a") #创建文本文档,保存聊天记录driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)driver.implicitly_wait(20) # 设置隐式等待时间driver.find_element(By.ID, 'fhz').click() x = driver.get_window_size()['width'] # 获取屏幕的高y = driver.get_window_size()['height'] # 获取屏幕的宽for i in range(1000): driver.swipe(9/ 10 * x, 1 / 4 * y, 9 / 10* x, 5 / 6 * y, 600) # 从屏幕的右上方滑动到右下方 msgs = driver.find_elements(By.ID, 'b4b') #定位到微信消息 for msg in msgs: file.write(msg.text + '\n') #将每一条消息的文本内容写入文件file
2.4Tips
- 由于滑动窗口的swipe()函数相当于点击效果,所以不能从屏幕的最右上方一直滑动到右下方,否则会触发手机通知栏,也不能从屏幕中间进行滑动,会误触消息。
- 经过观察可知获取的消息有一些消息是重复的,所以文本要经过去重。
- 此教程虽然介绍利用appium获取安卓手机微信消息,但对Harmony OS系统也可能适用。笔者的手机为华为Nova4,不久前更新鸿蒙系统,仍然可以进行自动化测试。
- Phone的自动化测试工具和Android不同,请自行学习。
三、jieba库分词,制作词频柱状图
3.1重要代码注释
为了避免matplotlib显示中文时产生乱码,需要先对字体进行设置:
plt.rcParams['font.family'] = ['sans-serif']plt.rcParams['font.sans-serif'] = ['SimHei']
jieba加载用户停用词典,用户停用词典可以使分词更精确:
jieba.load_userdict("dic.txt")
使用jieba.cut()函数进行分词:
for line in open(path): line.strip('\n') seg_list = jieba.cut(line, cut_all=False) cut_words += (" ".join(seg_list))all_words = cut_words.split()
统计词频:
c = Counter() #创建计数器for item in all_words: if len(item) > 1 and item != '\r\n': c[item] += 1
绘制高频词水平柱状图:
x = []y = []for key, value in c.items(): if value > 60: #数组中添加词频数大于60的词 x.append(key) y.append(value) barcolor = ['#FEFEFE', '#F3DFA4', '#E1C58C', '#C9A469', '#F9F3DD', '#FBFBF9', '#A4653E', '#882815', '#FEFEFB','#FCFFFB'] #指定生成柱状图的颜色plt.figure()plt.barh(x, y, color=barcolor) #绘制水平柱状图plt.show()
3.2完整代码
from collections import Counterimport jieba.analysefrom matplotlib import pyplot as pltplt.rcParams['font.family'] = ['sans-serif']plt.rcParams['font.sans-serif'] = ['SimHei']jieba.load_userdict("dic.txt")path = "文本去重.txt"cut_words = ""for line in open(path): line.strip('\n') seg_list = jieba.cut(line, cut_all=False) cut_words += (" ".join(seg_list))all_words = cut_words.split()c = Counter()for item in all_words: if len(item) > 1 and item != '\r\n': c[item] += 1 x = []y = []for key, value in c.items(): if value > 60: x.append(key) y.append(value) barcolor = ['#FEFEFE', '#F3DFA4', '#E1C58C', '#C9A469', '#F9F3DD', '#FBFBF9', '#A4653E', '#882815', '#FEFEFB','#FCFFFB']plt.figure()plt.barh(x, y, color=barcolor)plt.show()
四、Wordcloud库制作词云图
4.1重要代码解释
4.1.1 安装python库
wordcloud库用来生成词云
pip install wordcloudpip install imageio
imageio库用来指定词云背景图,这里指定词云图的形状为一秩可爱的猫。
pic_path = "pic/cat4.jpg"mask_image = imread(pic_path)
4.1.2 设置停用词
停用词在词云图中不进行显示。
stopwords = {"Doge", "recalled", "message", "Facepalm", "Shrunken", "Hurt", "的", "是", "就", "我", "呀", "你", "吧", "了"}
4.1.3 生成词云
font_Path属性值必须指定为中文字体,否则词云图会出现中文乱码。
color_func为生成词云图的颜色,可以通过ImageColorGenerator()函数来获取。
cloud = wordcloud.WordCloud(width=1000, height=700, font_path=fontPath, stopwords=stopwords, mask=mask_image,background_color='#748ca4', scale=2, min_font_size=3, color_func=image_colors)cloud.generate(" ".join(jieba.lcut(text)))cloud.to_file("baobao.png")
4.2 完整代码
import wordcloudfrom imageio import imreadfrom matplotlib import pyplot as pltfrom wordcloud import ImageColorGeneratorplt.rcParams['font.family'] = ['sans-serif']plt.rcParams['font.sans-serif'] = ['SimHei']path = "文本去重.txt"color = "pic/maskme.jpg"colormap = imread(color)image_colors = ImageColorGenerator(colormap) # 从图片提取颜色stopwords = {"Doge", "recalled", "message", "Facepalm", "Shrunken", "Hurt", "的", "是", "就", "我", "呀", "你", "吧", "了"}fontPath = "C:\\Windows\\Fonts\\simhei.ttf"pic_path = "pic/cat4.jpg"mask_image = imread(pic_path)text = open(path).read().strip('\n')cloud = wordcloud.WordCloud(width=1000, height=700, font_path=fontPath, stopwords=stopwords, mask=mask_image,background_color='#748ca4', scale=2, min_font_size=3, color_func=image_colors)cloud.generate(" ".join(jieba.lcut(text)))cloud.to_file("baobao2.png")#显示词云图plt.imshow(cloud)plt.axis("off")plt.show()
写在最后:用宝宝的话说我们是在用正经的工具做着不正经的事情,哈哈哈,怎么可能呢,想你才是最正经的事情呀!
你学会了吗?