我要爬爬虫(15)用appium爬取手机QQ音乐歌名

我想爬一下QQ音乐的我喜欢的歌单里的VIP歌曲的歌名,想知道哪些歌曲是vip歌曲,获取一个歌名清单。
分别试了网页版和windows版以及官方PC版,可是网页版的歌单显示不全,只显示前几十首歌,之前还是显示完全的,应该是最近一段时间变更的;而windows商店里自带的版本不显示VIP歌曲。
本来打算用Charles来监听qq音乐PC版的,可是监听到的请求,其中的歌曲数据经过了加密,获取不到,我还是会得太少了。。。
所以就打算用appium,类似于移动端的selenium,对于移动端的页面进行操作。

安装Appium

首先在电脑中安装Android sdk。
将Android sdk的路径保存为Android_Home写进环境变量,sdk文件夹下的tools和platform-tools写入path里。
本机是要安装jdk的,一开始不知道一运行就闪退。。。同样把jdk的路径也写入环境变量。
最后将手机与电脑连接,安装Appium,手机上自动安装Appium Settings和Unlock。

连接手机

打开Appium,出现的是日志界面,
日志界面
点击右上角的放大镜,进入Automatic Server.
在Automatic Server中设定Desired Capabilities,分别是
platformName(操作系统名),
deviceName(设备名),
appPackage和appActivity,这两个是具体某个app的信息,noReset(启动app时不要清除app里的原有的数据,设为True)
其中deviceName可以在手机设置中查看,也可以连接电脑后在cmd中通过命令来查看

adb devices -l

可能出现报错的情况
报错
重启电脑或者确认手机开发者模式是否开启。

List of devices attached

而appPackage和appActivity可以在开启某个app后通过命令来查看。

adb.exe shell dumpsys window |findstr mCurrent

连接手机
上图即为打开手机qq音乐的连接配置。
配置完毕后,点击 Start Session连接。
手机会自动打开qq音乐,app source中也可以看到出现qq音乐的操作界面。
qq音乐主界面
如果手机设置密码,那么手机会停在锁屏界面,app source亦然。
如果VIP刚刚过期,还可能有vip的弹窗广告。。。这些都会影响操作。

代码逻辑设计

根据qq音乐的UI特点,打开app后的操作步骤应为
1 点击 我的
2 点击 喜欢
3 获得当前界面下所有的vip歌曲的歌名,作者,专辑。
4 向下滑动手机屏幕。
5 重复3,4,直至滑动至歌单底部。

需要pythonAppium-Python-Client模块中的webdriver类建立连接对象。
selenium模块的一些方法可以模拟appium软件中的操作。
定义连接时,分别定义webdriver对象的server和attrs。server为http://localhost:4723/wd/hub,localhost就是连接本地,4723为appium的服务端口号,wd即为webdriver的缩写,hub 是指主(中心) 节点,在selenium 分布式里中心节点。所以/wd/hub可以理解为appium的规定地址。attrs即为刚才Appium软件中Desired Capabilities那些选项。

self.attrs = {
            "platformName": "Android",
            "deviceName": "DUK_AL20",
            "appPackage": "com.tencent.qqmusic",
            "appActivity": "com.tencent.qqmusic.activity.AppStarterActivity",
            "noReset": "True"
        }
        self.server = 'http://localhost:4723/wd/hub'
        self.driver = webdriver.Remote(self.server,self.attrs)

建立连接后即可打开手机qq音乐,进入其主界面。

1,2点击

首先需要定位 我的 按钮,已知其accessibility id=我的,所以可以通过find_element_by_accessibility_id来定位按钮。然后使用click()方法点击即可。
我的按钮
然后界面跳转到 我的 界面,以同样的方法点击 喜欢 即可。由于界面刷新有延迟,可以使用WebDriverWait()方法等待2s再点击。
喜欢按钮

3 获取歌曲信息

进入我喜欢的歌单后,需要定位每一首歌,并判断其是否为vip歌曲。
每一首歌曲
可以定位到歌曲的歌名和歌曲信息,均可以通过元素的text值获取到文本信息。通过定位vip元素,如果能找到该元素则为vip歌曲,反之则不是。
歌曲元素
使用find_elements_by_id定位到当前界面的所有歌曲,然后遍历每一首歌,同样使用find_element_by_id定位每首歌的vip元素,如果定位到则获取歌名和歌曲信息,反之则捕获异常并跳过这首歌。将捕获到的信息写入文本文件中。
值得注意的是,为了反爬虫的需要,qq音乐中的元素名称有时候会变化,比如歌曲的resource_id并不一定是com.tencent.qqmusic:id/aqi,所以代码运行前需要检查一下元素名。

4 滑动

当前屏幕中的vip歌曲获取完毕后,下滑屏幕获取新的歌曲。这里用到webdriver的swipe()方法,在方法中分别设定滑动轨迹起始点和终点的座标即可。例如

swipe(start_x=1256, start_y=1931, end_x=1388, end_y=780, duration=1500)

start_x,start_y,end_x,end_y分别对应滑动轨迹起始点和终点的横纵座标。
duration为滑动时间,这决定滑动的速度。
元素的bounds值为元素的左上角和右下角的座标,可以参照它设定始终点的座标。
定位元素
由于触屏手机滑动是有惯性设定的,手指离开屏幕后,屏幕依然会遵循原来的轨迹继续滑行一段距离,之前手指滑动的越快,手指离开后屏幕继续滑动的越远。所以这里滑动时间duration可以适当设置长一点,让滑动速度慢一些,避免屏幕继续向下滑动,导致错过一些歌曲。为此,滑动的终点座标也应该设定适当在下面一些。
在这里插入图片描述
如图,end点不要设定的太高,滑动距离短一点,给惯性一点缓冲距离。

5 滑动次数

简单来说,就是设定滑动几下。歌单的总歌曲数是知道的,大约900首,一个屏幕最多显示7首,所以设计滑动大约130下即可。

总结

最终获取到VIP的歌单,所有VIP歌曲的名字。
获取到歌单
最终结果不是特别理想,
1 速度比较慢,定位屏幕中的7首歌的元素本身就很慢,而且为了保证数据完全刷新出来,在很多操作之间需要设计等待,这也会耽搁一些时间。
2 由于怕漏掉一些歌曲,所以滑动的比较谨慎,滑动距离设计的比较小,这也导致歌曲被重复获取(上一个屏幕底部获取到,又在下一个屏幕顶部获取到),后面还得做去重处理。
不过目的还是达到了,确实获取到了vip歌单,而且没有漏掉的歌曲。

参考

appium自动化爬虫
Android查看appPackage和Activity的多种方法
"http://127.0.0.1:4723/wd/hub"的解释

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章