我想爬一下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,出现的是日志界面,

python 爬取酷狗音乐vip歌曲 如何爬取vip音乐_Server


点击右上角的放大镜,进入Automatic Server.

在Automatic Server中设定Desired Capabilities,分别是

platformName(操作系统名),

deviceName(设备名),

appPackage和appActivity,这两个是具体某个app的信息,noReset(启动app时不要清除app里的原有的数据,设为True)

其中deviceName可以在手机设置中查看,也可以连接电脑后在cmd中通过命令来查看

adb devices -l

可能出现报错的情况

python 爬取酷狗音乐vip歌曲 如何爬取vip音乐_spider_02


重启电脑或者确认手机开发者模式是否开启。

List of devices attached

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

adb.exe shell dumpsys window |findstr mCurrent

python 爬取酷狗音乐vip歌曲 如何爬取vip音乐_python 爬取酷狗音乐vip歌曲_03


上图即为打开手机qq音乐的连接配置。

配置完毕后,点击 Start Session连接。

手机会自动打开qq音乐,app source中也可以看到出现qq音乐的操作界面。

python 爬取酷狗音乐vip歌曲 如何爬取vip音乐_Android_04


如果手机设置密码,那么手机会停在锁屏界面,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()方法点击即可。

python 爬取酷狗音乐vip歌曲 如何爬取vip音乐_Server_05


然后界面跳转到 我的 界面,以同样的方法点击 喜欢 即可。由于界面刷新有延迟,可以使用WebDriverWait()方法等待2s再点击。

python 爬取酷狗音乐vip歌曲 如何爬取vip音乐_Server_06

3 获取歌曲信息

进入我喜欢的歌单后,需要定位每一首歌,并判断其是否为vip歌曲。

python 爬取酷狗音乐vip歌曲 如何爬取vip音乐_python 爬取酷狗音乐vip歌曲_07


可以定位到歌曲的歌名和歌曲信息,均可以通过元素的text值获取到文本信息。通过定位vip元素,如果能找到该元素则为vip歌曲,反之则不是。

python 爬取酷狗音乐vip歌曲 如何爬取vip音乐_spider_08


使用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值为元素的左上角和右下角的坐标,可以参照它设定始终点的坐标。

python 爬取酷狗音乐vip歌曲 如何爬取vip音乐_Server_09


由于触屏手机滑动是有惯性设定的,手指离开屏幕后,屏幕依然会遵循原来的轨迹继续滑行一段距离,之前手指滑动的越快,手指离开后屏幕继续滑动的越远。所以这里滑动时间duration可以适当设置长一点,让滑动速度慢一些,避免屏幕继续向下滑动,导致错过一些歌曲。为此,滑动的终点坐标也应该设定适当在下面一些。

python 爬取酷狗音乐vip歌曲 如何爬取vip音乐_Android_10


如图,end点不要设定的太高,滑动距离短一点,给惯性一点缓冲距离。

5 滑动次数

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

总结

最终获取到VIP的歌单,所有VIP歌曲的名字。

python 爬取酷狗音乐vip歌曲 如何爬取vip音乐_python 爬取酷狗音乐vip歌曲_11


最终结果不是特别理想,

1 速度比较慢,定位屏幕中的7首歌的元素本身就很慢,而且为了保证数据完全刷新出来,在很多操作之间需要设计等待,这也会耽搁一些时间。

2 由于怕漏掉一些歌曲,所以滑动的比较谨慎,滑动距离设计的比较小,这也导致歌曲被重复获取(上一个屏幕底部获取到,又在下一个屏幕顶部获取到),后面还得做去重处理。

不过目的还是达到了,确实获取到了vip歌单,而且没有漏掉的歌曲。

参考

appium自动化爬虫