python+appium爬取微信运动数据,并分析好友的日常步数情况
python+appium爬取微信运动数据,并分析好友的日常步数情况
声明:仅供技术交流,请勿用于非法用途,如有其它非法用途造成损失,和本博客无关
目录
- python+appium爬取微信运动数据,并分析好友的日常步数情况
- 前言
- 一、准备
- 二、爬取数据
- 思维导图(爬取逻辑)
- 第一步:连接手机
- 第二步:元素定位
- 第三步:编写代码
- 三、数据分析
- 第一步、数据预处理
- 第二步、数据探索性分析
- 第三步、数据可视化
- 第四步、结论
- 写在最后
前言
- 微信运动只能看到前30天的数据,超过的会过期而拿不到,我也是现在才知道的。本来还想拿多一点数据的哈哈。(不信你去试试)
- 本次爬取使用的是
appium
,因为是完全模拟人的操作,所以耗时由您好友数量决定。(我200左右的微信好友,其中130+个人开启了微信运动,耗时半个钟,基本上一分钟拿到一天的数据) - 最好先给您的好友都备注好,并且名字最好不要超过8个字好像,因为超过之后会显示不全,最后那几个字会省略为点点点,强迫症看着就很烦你懂的
废话不多说,直接开始
一、准备
appium
:一个类似于selenium
的自动化工具,很多操作也很相像。(这个安装网上有很多教程,亲测确实是很麻烦,不过安装好之后简直是一劳永逸呀)Appium-python-Client
:这个是python
第三方库,通过它写python代码来操作appium
的,直接用pip
命令安装即可jupyter notebook
:这次推荐使用这个编译器。(后面的数据分析会用到,很友好,很完美,相信你也会爱上她的hiahiahia~)- 一部手机:这个没有的话,用安卓模拟器应该也行。推荐直接上真机就好了
二、爬取数据
思维导图(爬取逻辑)
第一步:连接手机
我这里连接了我自己的真机,安卓模拟器我没装不清楚具体细节请谅解。用USB将电脑和手机连上后,首先要打开手机的USB调试,大致都在:设置——>开发者选项——>开启USB调试
appium
的教程网上也都能找得到,也不难,基本上会selenium
的都能一下子学会appium
。而appium
会依赖Android
环境,那么这里给出两个要用到的adb
命令:
- 查看包名和界面名(package&activity)
linux
/mac
adb shell dumpsys window windows | grep mFocusedApp
windows
adb shell dumpsys window windows | findstr mFocusedApp
- 获取当前电脑已经连接的设备和对应的设备名
adb devices
然后在cmd中输入上述命令获取手机的设备名、再者进入微信,输入命令获取包名和界面名。(好像不同手机不同版本的包名和界面名会有所差异)
第二步:元素定位
我这里用的查找元素定位工具是安装Android SDK
自带的uiautomatorviewer
工具。具体在你安装的Android SDK
目录下:tools目录——>uiautomatorviewer.bat
元素主要是通过resource-id
标签来定位,用到的主要是xpath
语句,具体定位内容请看代码。
好像不同手机不同版本的resource-id
也会有所差异,所以尽量不要复制代码直接运行哈,自己动手丰衣足食。
第三步:编写代码
运行代码前的准备:自己先打开微信,然后进入消息的页面,并把微信运动置顶,这样是为了减少不必要的操作。
ps:详情讲解请看代码和代码注释
from appium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from appium.webdriver.common.touch_action import TouchAction
import parsel #解析页面
import datetime
import timedef crawl(desired_caps,date_out):driver = webdriver.Remote('http://127.0.0.1:4723/wd/hub', desired_caps)wait=WebDriverWait(driver,20,4) #设置显示等待,即在20秒的时间内,每隔4秒找一次元素,这个按需更改TouchAction(driver).tap(element=wait.until(lambda x : x.find_element_by_xpath('//*[@text="微信运动"]'))).perform()data={} #存储每个排行榜的信息num=0 #给日期计数sj=int(time.time()) #记录开始爬取数据开始的时间while True:start_time=int(time.time()) #记录本次爬取开始的时间up_el=driver.find_elements_by_id('com.tencent.mm:id/ai')[0] #捕获上一个排行榜时间的元素low_el=driver.find_elements_by_id('com.tencent.mm:id/ai')[1] #捕获当前排行榜时间的元素if num != 0:driver.drag_and_drop(up_el,low_el) #拖动上一个元素的位置到当前元素的位置date=(datetime.datetime.now()-datetime.timedelta(days=1+num)).strftime("%Y-%m-%d")name_list=[] #存储姓名run_count_list=[] #存储步数like_list=[] #存储点赞数flag=1 #因为自己总是会出现在第一位,所以第一次滑要排除自己if date_out not in low_el.text:now=driver.find_elements_by_id('com.tencent.mm:id/atb')[2]TouchAction(driver).tap(element=now).perform() #点击进入当前排行榜while True:if driver.find_elements_by_xpath('//*[@text="邀请朋友"]') == []: #判断是否到底端了driver.swipe(480,1500,480,700,duration=2000) #这个也按你们实际情况来更改坐标吧,只要第一次滑完的时候要看到第一名的信息response=parsel.Selector(driver.page_source)if flag == 1:people=response.xpath('//*[@resource-id="com.tencent.mm:id/om"]')[1:] #第一次排除自己else:people=response.xpath('//*[@resource-id="com.tencent.mm:id/om"]')for eachone in people:flag=0name=eachone.xpath('.//*[@resource-id="com.tencent.mm:id/brk"]/@text').get() #注意这里用的是@text,而不是/text,之前我在这里都快绝望了,一直拿不到text的内容,最后给蒙出来了哈哈run_count=eachone.xpath('.//*[@resource-id="com.tencent.mm:id/bq8"]/@text').get()like=eachone.xpath('.//*[@resource-id="com.tencent.mm:id/bpy"]/@text').get()if (name not in name_list)and(name is not None):temp=[] #存储步数和点赞数name_list.append(name)temp.append(run_count)temp.append(like)run_count_list.append(temp)item=dict(zip(name_list,run_count_list))data.update({date:item})else:breakprint(f'{date},有{len(name_list)}个好友开启了他们的微信运动。本轮耗时:{int(time.time())-start_time}秒')num+=1driver.back() #返回else:print(f'再往后消息已过期。总耗时:{int(time.time())-sj}秒')breakdriver.quit() #退出return datadef save_data(data):json_str = json.dumps(data, indent=4,ensure_ascii=False)with open('data.json', 'w', encoding='utf-8') as f:f.write(json_str)def main(desired_caps,date_out):# 爬取数据data=crawl(desired_caps,date_out)# 保存数据save_data(data)if __name__ == '__main__':desired_caps={'platformName': 'Android', #操作系统'deviceName': '3c91eced', #设备名'platformVersion': '6.0.1', #版本号'appPackage': 'com.tencent.mm', #包名'appActivity': 'com.tencent.mm.ui.LauncherUI' #界面名}main(desired_caps,date_out='12月12日') #我的是12月12日之前的都已过期,你们按实际时间来更改这个日期就行
运行完之后呢,会在当前目录下生成一个data.json
的文件,这就是爬下来的全部数据啦
输出如下:
2020-01-10,有135个好友开启了他们的微信运动。本轮耗时:59秒
2020-01-09,有135个好友开启了他们的微信运动。本轮耗时:61秒
2020-01-08,有135个好友开启了他们的微信运动。本轮耗时:62秒
2020-01-07,有134个好友开启了他们的微信运动。本轮耗时:61秒
2020-01-06,有134个好友开启了他们的微信运动。本轮耗时:62秒
2020-01-05,有132个好友开启了他们的微信运动。本轮耗时:60秒
2020-01-04,有133个好友开启了他们的微信运动。本轮耗时:60秒
2020-01-03,有133个好友开启了他们的微信运动。本轮耗时:60秒
2020-01-02,有132个好友开启了他们的微信运动。本轮耗时:60秒
2020-01-01,有134个好友开启了他们的微信运动。本轮耗时:62秒
2019-12-31,有134个好友开启了他们的微信运动。本轮耗时:62秒
2019-12-30,有133个好友开启了他们的微信运动。本轮耗时:59秒
2019-12-29,有134个好友开启了他们的微信运动。本轮耗时:60秒
2019-12-28,有135个好友开启了他们的微信运动。本轮耗时:62秒
2019-12-27,有135个好友开启了他们的微信运动。本轮耗时:62秒
2019-12-26,有134个好友开启了他们的微信运动。本轮耗时:61秒
2019-12-25,有135个好友开启了他们的微信运动。本轮耗时:62秒
2019-12-24,有135个好友开启了他们的微信运动。本轮耗时:61秒
2019-12-23,有134个好友开启了他们的微信运动。本轮耗时:62秒
2019-12-22,有135个好友开启了他们的微信运动。本轮耗时:63秒
2019-12-21,有136个好友开启了他们的微信运动。本轮耗时:77秒
2019-12-20,有133个好友开启了他们的微信运动。本轮耗时:68秒
2019-12-19,有134个好友开启了他们的微信运动。本轮耗时:64秒
2019-12-18,有134个好友开启了他们的微信运动。本轮耗时:64秒
2019-12-17,有133个好友开启了他们的微信运动。本轮耗时:63秒
2019-12-16,有133个好友开启了他们的微信运动。本轮耗时:61秒
2019-12-15,有133个好友开启了他们的微信运动。本轮耗时:62秒
2019-12-14,有134个好友开启了他们的微信运动。本轮耗时:63秒
2019-12-13,有135个好友开启了他们的微信运动。本轮耗时:63秒
再往后消息已过期。总耗时:1819秒
三、数据分析
首先先加载刚刚爬取到的数据和导入所需要的库,以及设定一些默认的配置
import pandas as pd
import random
import json
import os
import matplotlib.pyplot as plt #画图工具
%matplotlib inline
plt.rcParams['font.sans-serif'] = ['SimHei'] #黑体(显示中文)
plt.rcParams['font.size'] = 20 #字体大小
#加载json数据
with open('data.json','r',encoding='utf-8') as f:data=json.load(f)
第一步、数据预处理
预处理主要是剔除异常值、空值、重复值等等,可是我觉得在这里,我并不想剔除这些数据,因为可以从这里看出哪些人什么时候开启了微信运动,什么时候关闭了它,还有空值的话也可能是因为他没有打开过微信甚至可能根本没有上过网玩过手机都有可能。还有一种可能是找出他/她哪一天屏蔽了你的微信运动哈哈。
所以我这里就不做数据处理了,直接全部套用就ok
第二步、数据探索性分析
ps:考虑到隐私的问题,以下的图片均已打码
- 康康第一名和倒数第一名都有谁
one=[]
for i in list(data.keys()):print('{},第一名:{}'.format(i,list(data[i].keys())[0]))one.append(list(data[i].keys())[0])
df=pd.DataFrame([one]).T
df.columns=['第一名']
df.index=list(data.keys())
print('获得第一名的次数:')
print(df['第一名'].value_counts())
daoshu_one=[]
for i in list(data.keys()):print('{},倒数第一名:{}'.format(i,list(data[i].keys())[-1]))daoshu_one.append(list(data[i].keys())[-1])
df['倒数第一名']=daoshu_one
print('获得倒数第一名的次数:')
print(df['倒数第一名'].value_counts())
输出如下:
- 康康前十名和倒数前十名都有谁
ten=[]
all_ten=[]
for i in list(data.keys()):print('{},前十名:{}'.format(i,list(data[i].keys())[:10]))ten.append(list(data[i].keys())[:10])all_ten+=list(data[i].keys())[:10]
df['前十名']=ten
df_ten=pd.DataFrame([all_ten]).T
df_ten.columns=['前十名的次数']
print('获得前十名的次数:')
print(df_ten['前十名的次数'].value_counts())
daoshu_ten=[]
all_daoshu_ten=[]
for i in list(data.keys()):print('{},倒数前十名:{}'.format(i,list(data[i].keys())[-10:]))daoshu_ten.append(list(data[i].keys())[-10:])all_daoshu_ten+=list(data[i].keys())[-10:]
df['倒数前十名']=daoshu_ten
df_daoshu_ten=pd.DataFrame([all_daoshu_ten]).T
df_daoshu_ten.columns=['倒数前十名的次数']
print('获得倒数前十名的次数:')
print(df_daoshu_ten['倒数前十名的次数'].value_counts())
ps:由于边幅有限,这个就不上传输出了,跟第一名和倒数第一名的输出差不多,有兴趣自己运行看看吧
第三步、数据可视化
- 先可视化前面两个
下面这个函数的用处是将柱状图中的每根柱子标上对应的数值,后面很多操作都用到这个函数,所以我把它单独拿了出来
def autolabel(rects):for rect in rects:height = rect.get_height()plt.annotate('{}'.format(height),xy=(rect.get_x() + rect.get_width() / 2, height),xytext=(0,3), # 3 points vertical offsettextcoords="offset points",ha='center', va='bottom')
name=df['第一名'].value_counts().index
one_count=df['第一名'].value_counts().values
plt.figure(figsize=(18,8))
a=plt.bar(name,one_count,label='次数')
plt.ylabel('次数/次')
plt.tick_params(axis='x', rotation=30)
plt.title('第一名的次数')
autolabel(a)
plt.legend()
plt.tight_layout()
plt.savefig('第一名的次数.jpg')
plt.show()
name=df['倒数第一名'].value_counts().index
daoshu_one_count=df['倒数第一名'].value_counts().values
plt.figure(figsize=(18,8))
a=plt.bar(name,daoshu_one_count,color='red',label='次数')
plt.ylabel('次数/次')
plt.tick_params(axis='x', rotation=30)
plt.title('倒数第一名的次数')
autolabel(a)
plt.legend()
plt.tight_layout()
plt.savefig('倒数第一名的次数.jpg')
plt.show()
name=df_ten['前十名的次数'].value_counts().index[:20]
ten_count=df_ten['前十名的次数'].value_counts().values[:20]
plt.figure(figsize=(18,8))
a=plt.bar(name,ten_count,label='次数')
plt.ylabel('次数/次')
plt.tick_params(axis='x', rotation=30)
plt.title('前十名的次数(中的前20名)')
autolabel(a)
plt.legend()
plt.tight_layout()
plt.savefig('前十名的次数(中的前20名).jpg')
plt.show()
name=df_daoshu_ten['倒数前十名的次数'].value_counts().index[:20]
daoshu_ten_count=df_daoshu_ten['倒数前十名的次数'].value_counts().values[:20]
plt.figure(figsize=(18,8))
a=plt.bar(name,daoshu_ten_count,color='red',label='次数')
plt.ylabel('次数/次')
plt.tick_params(axis='x', rotation=30)
plt.title('倒数前十名的次数(中的前20名)')
autolabel(a)
plt.legend()
plt.tight_layout()
plt.savefig('倒数前十名的次数(中的前20名).jpg')
plt.show()
输出如下:
- 个人步数趋势可视化
def everyone_plot(name):run_count_list=[] #存储步数like_list=[] # 存储点赞数for i in list(data.keys())[::-1]:if data[i].get(name) is not None:run_count=int(data[i].get(name)[0])run_count_list.append(run_count)like_list.append(int(data[i].get(name)[1]))else:run_count_list.append(0)like_list.append(0)plt.figure(figsize=(18,8))plt.plot(list(data.keys())[::-1],run_count_list,label='步数',linewidth=2,color='blue',marker='o',markerfacecolor='red',markersize=8)plt.tick_params(axis='x', rotation=70)plt.ylabel('步数/步')plt.title(f'{name}的个人运动趋势')low=-1000 if min(run_count_list) < 1000 else 250high=max(run_count_list)+max(run_count_list)/2plt.ylim(low,high)plt.grid(True)for x,y in zip(list(data.keys())[::-1],run_count_list):plt.text(x, y, y, ha='center', va='bottom', fontsize=18)for i,(x,y) in enumerate(zip(list(data.keys())[::-1],run_count_list)):if like_list[i] != 0:plt.text(x, low,f'{like_list[i]}赞', ha='center', va='bottom', fontsize=18)plt.legend()plt.tight_layout() #铺满整个画布plt.savefig(f'./personal/{name}.jpg')plt.show()if __name__ == '__main__':if not os.path.exists('./personal'):os.makedirs('./personal')all_name=[] #存储这些数据里面出现过的所有人的姓名for i in list(data.keys()):all_name+=list(data[i].keys())all_name=list(set(all_name)) #集合去重法for i in range(len(all_name)):eachone=random.choice(all_name)all_name.remove(eachone)everyone_plot(eachone)
这里保存和输出了所有人的这30天以来的运动趋势情况,图片有点多,就不一一列出来了,下面就随便展示一个吧
- 比较两个或多个人的运动趋势
def compare_plot(names,flag=True): #flag判断是否需要标上数值plt.figure(figsize=(18,8))for name in names: #通过循环画出传进来的每个人的运动趋势run_count_list=[]like_list=[]for i in list(data.keys())[::-1]:if data[i].get(name) is not None:run_count=int(data[i].get(name)[0])run_count_list.append(run_count)like_list.append(int(data[i].get(name)[1]))else:run_count_list.append(0)like_list.append(0)plt.plot(list(data.keys())[::-1],run_count_list,label=name,linewidth=2,marker='o',markersize=6)if flag:for x,y in zip(list(data.keys())[::-1],run_count_list):plt.text(x, y, y, ha='center', va='bottom', fontsize=18)plt.tick_params(axis='x', rotation=70)plt.ylabel('步数/步')plt.title(f'{len(names)}个人之间的比较')plt.grid(True)plt.legend()plt.tight_layout()plt.savefig(f'{len(names)}个人之间的比较.jpg')plt.show()if __name__ == '__main__':compare_plot(['好友A名字','好友B名字'],flag=True)
下面我也随机找两个好友进行比较了一下,输出如下:
第四步、结论
通过观察第一名和倒数第一名、前十名和倒数前十名,并且看到了谁占的次数最多,大致可以猜出这些好友每天的运动即行走状况,是几万步在外面兜兜转转很忙呢,还是寥寥几百步甚至几十步宅在家里面呢,看得一清二楚。(排除那些用工具来刷步数的情况,大致还是很准确的了)
还能看到点赞的数量,这个点赞我觉得就是看你的好友的好友是不是时常关注这个微信运动了,因为我觉得很少会去在意别人吧并且还给他/她点赞,这样的行为我之前点赞过几次之后就没有再点过了,没必要,主要还是懒哈啊哈。
再者通过观察每个人的运动趋势,也能清楚地知道好友们这30天里面的运动情况的。是毫无波动地持续一个月的几千步呢,还是会有那么一两天突然增高呢,再或者是跌宕起伏地像人生一样呢,又或者走着走着步数变成了零呢(可能关闭了微信运动这个功能了)等等等等
可能我分析地还不够全面,不够细致,那就先这样吧
写在最后
为什么会去爬取微信运动信息并分析好友的运动情况呢?
一个原因:在很早之前,我就有过这个想法了,就想分析微信运动里好友们的运动情况,看看他们每一天是怎么过的,这其实是一件很好玩的事情嘻嘻。(我要我觉得,不要你觉得)
另一个原因:本来是想学appium
的,因为想在手机上开发一些自动化的任务,比如日常签到啊,爬数据啊,刷xx啊等等(你懂的),并且还可以配合一些抓包工具来完成一些别人爬不到的数据哈哈(只存在于手机中的那些数据)。可是呢,不知道为啥,我只能拿到与微信相关的页面数据,其他的应用都不能拿到,拿不到页面数据那就别想爬虫了呀。我也百度找了很久,什么重装环境啦,Android API版本更换啦,我都试过了,还是不行。(学appium
还真的是从入门到放弃呢),所以就在我下定决心快要卸载所有和appium
相关的东西的时候,我忍住了,内心想法是既然都入门了,不搞一下就放弃了?于是乎就有了这一篇文章。
ps:其实我也有爬取过朋友圈动态里面的数据的,只是因为拿不到图片和视频,只能拿文字,我就想没有图片和视频那还爬什么呢,这些才是精华所在呀。(只是我个人看法,你们有兴趣也可以自己去尝试一番),对了,如果有Android大佬,可以帮我看下只能获取到微信页面数据,这是出了什么问题吗?万分感谢!
python+appium爬取微信运动数据,并分析好友的日常步数情况相关推荐
- Python爬虫爬取微信朋友圈的方法,感兴趣的朋友可以了解下
前言 本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 小雨 | 作者 python教程 | 来源 接下来,我们将实现微信朋友圈的 ...
- Python爬虫爬取微信朋友圈
更多编程教程请到:菜鸟教程 https://www.piaodoo.com/ 友情链接: 高州阳光论坛https://www.hnthzk.com/ 人人影视http://www.op-kg.com/ ...
- python为啥爬取数据会有重复_利用Python来爬取“吃鸡”数据,为什么别人能吃鸡?...
原标题:利用Python来爬取"吃鸡"数据,为什么别人能吃鸡? 首先,神装镇楼 背景 最近老板爱上了吃鸡(手游:全军出击),经常拉着我们开黑,只能放弃午休的时间,陪老板在沙漠里奔波 ...
- python爬虫爬取微信公众号小程序信息
python爬虫爬取微信公众号小程序信息 爬取内容 某汽车维修信息提供的维修店名称,地点以及电话(手机)号码 爬取步骤 啥也别管,先抓包看看,在这里,博主使用的抓包软件是charles 抓包:将网络传 ...
- 用Python实现爬取微信头像
如何用python实现爬取微信头像 python里面有个itchat包,用这个可以实现 1.先下载 itchat pip install itchat 2.创建一个py文件 import itchat ...
- 从入门到入土:Python实现爬取刷新微博推荐和最新好友微博|cookie调用|模拟登录
写在前面: 此博客仅用于记录个人学习进度,学识浅薄,若有错误观点欢迎评论区指出.欢迎各位前来交流.(部分材料来源网络,若有侵权,立即删除) Python实现爬取刷新微博推荐和最新好友微博|cookie ...
- 简单使用resquests爬取雪球网数据,分析股票走势
简单使用resquests爬取雪球网数据,分析股票走势 import requests import pymongo import json # 数据库初始化 client = pymongo.Mon ...
- python,爬取微信好友数据,看他一天天在干嘛
前段时间发现了一个好玩的东西,一个python的第三方库itchat,它的功能很强大.只要你扫一下它所生成的二维码即可模拟登陆你的微信号,然后可以实现自动回复,爬取微信列表好友信息等功能.基于这个第三 ...
- python爬取微信聊天记录数据_[使用案例]python如何爬取微信好友信息?(上)
Python3如何爬取微信好友基本信息,并且进行数据清洗?下面跟着IP海带来的教程,我们一起看看具体的操作要怎么实现. 1.登录获取好友基础信息: 好友的获取方法为get_friends,将会返回完整 ...
最新文章
- 平年闰年c语言源代码,C语言平年闰年问题
- Spring AOP增强(Advice)
- tab与list配合使用
- Xcode 新项目删除 storyboard 文件
- 如何假装自己读懂了《时间简史》
- centos7源码安装mysql报错_CentOS7 下源码安装MySQL数据库 8.0.11
- Intel 64/x86_64/IA-32/x86处理器指令集 - CPUID (2) - 起源
- python函数定义语句可执行_python学习笔记-定义函数
- 2020年我对大前端的认知,前端开发有哪些变化
- 机器学习基础(二十三)—— 概念、定义
- Python-Matplotlib可视化(4)——添加注释让统计图通俗易懂
- 高中计算机网络技术专业的自我鉴定,计算机网络技术专业的自我鉴定(精选5篇)...
- c语言程序的生命周期(编写、预处理、编译、汇编、链接、执行)
- Ubuntu18.04安装网络调试助手 NetAssist
- eclipse汉化-设置语言包
- 软件测试-黑盒测试:正交实验设计法
- XTUOJ-1281-Cute String
- 在线作图工具:ProcessOn,流程图-思维导图-原型图-UML图等
- python身份证号码校验
- PostScript 打印机打印内存不足错误消息