• Python网络爬虫——Appuim+夜神模拟器爬取得到APP课程数据


    一、背景介绍

    随着生产力和经济社会的发展,温饱问题基本解决,人们开始追求更高层次的精神文明,开始愿意为知识和内容付费。从2016年开始,内容付费渐渐成为时尚。 罗辑思维创始人罗振宇全力打造“得到APP”就是这样一款优质的可以听音频、学通识课程、看电子书、看直播、记笔记的知识付费平台,得到汇聚罗振宇、薛兆丰、梁宁、万维钢、吴军、香帅、宁向东等各个领域的专家学者的精品课程,致力于服务所有终身学习者。

    也许你会感到奇怪,得到就是这样一款只有APP而没有网页版的产品,所以传统的网页爬取对于爬取得到数据只能是望洋兴叹了。本文用于爬取得到APP的课程数据,包括课程名称、作者、单价、学习人数等数据,可作为一个爬取APP数据的demo进行分享。

    二、APP爬取思路和方案选择

    2.1 思路一

    通过抓包软件对APP进行抓包分析, 这种方式可以看到 App 在运行过程中发生的所有请求和响应。得知接口之后可以通过设置合适的请求头和各种参数来发送HTTP或者HTTPS请求接口,接口返回的数据就是想要数据了。

    这种方式一旦实现,基本上算是一劳永逸的,除非接口和返回数据定义发生变化。但是如果一些动态参数设置不对,访问接口则不能得到任何数据,换句话说,只要无法破解参数,这条路就是死路一条。

    2.2 思路二

    通过自动化测试工具模拟手工操作APP进行数据的爬取。通过向自动化测试工具(例如Appium)发送操作指令,驱动设备完成点击、输入、滑动等各种操作,分析页面数据完成数据爬取。

    这种方式相比于方式一而言,并不会受限于请求头和动态参数,只要是人工可以操作的,自动化测试工具都可以帮助我们进行完成,而所有的APP的所有功能所有页面用户都可以进行操作,意味着APP内所有的数据都可以拿到。

    2.3 方案选择

    本人在尝试使用方式一的过程中,抓包分析接口之后发现有些动态参数无法搞定,故放弃该方式。采用方式二进行爬取。

    三、准备工作

    3.1 Python环境的搭建

    下载Python安装包:官方下载地址

    安装:注意勾选“Add Python 3.8 to PATH”

    3.2 Android SDK安装和环境变量配置

    下载Android Studio进行安装Android SDK:下载地址

    默认安装或者选择路径进行安装即可

    环境变量的配置:

    变量名称:ANDROID_HOME
    变量值:SDK安装路径
    在Path变量下面添加:%ANDROID_SDK_HOME%platform-tools
    在Path变量下面添加:%ANDROID_SDK_HOME%	ools
    

    3.3 夜神模拟器安装和得到APP安装

    夜神模拟器下载:夜神模拟器

    夜神模拟器安装:默认安装即可。

    得到APP下载:得到APP下载

    将下载的apk安装包拖动到夜神模拟器中进行安装。

    3.4 Appium安装

    Appium下载地址: Appium下载

    安装:默认安装到C盘即可。

    配置环境变量:

    变量名称:APPIUM_HOME
    变量值:Appium安装路径(eg:C:Program FilesAppium)
    在Path变量下面添加:%APPIUM_HOME%
    

    四、爬取核心

    4.1 Appium启动APP

    使用Appium启动APP时需要配置参数:platformName、deviceName、appPackage、appActivity。配置完成之后Appium会自动查找手机上面的包名和入口类,然后将其启动。

    platformName:平台名称,本文使用的是安卓平台,填写Android。
    deviceName:设备名称。
    appPackage:APP程序包。
    appActivity:程序入口。
    
    • 获取appPackage和appActivity的方法:

    最简单有效的方法为使用命令行获取。使用Appium客户端连接到APP,将APP打开到需要获取appActivity的页面,执行下面命令:

    adb shell
    dumpsys activity | grep mFocusedActivity
    

    1572162644737.png

    代码如下:

     def __init__(self):
     print("init")
     self.desired_caps = {
     "platformName": "Android",
     "deviceName": "127.0.0.1:62001",
     'platformVersion': '5.1',
     "appPackage": "com.luojilab.player",
     "appActivity": "com.luojilab.business.HomeTabActivity",  # 主页
     "noReset": True
     }
     self.driver = webdriver.Remote(DRIVER_SERVER, self.desired_caps)
     self.wait = WebDriverWait(self.driver, TIMEOUT)
    

    这段代码的作用是使用Appium启动得到APP并进入主页。如图:

    Image [2].png

    4.2 点击“课程”按钮进入课程页

    本文目的是爬取课程的数据,所以需要点击课程进入课程页。人的操作是这样的的,首先在课程页面找到课程按钮,然后点击。程序的操作也是一样的:首先要定位到“课程”这个按钮,然后进行点击。

    使用Appium定位元素

    1572162113820.png

    点击选中左边“课程”按钮,可以看到这个元素的源代码,通过xpath定位:

    course = self.driver.find_element_by_xpath("//android.widget.TextView[@text='课程']") # 课程

    Appium可以进行点击的操作。点击课程按钮的代码如下:course.click()

    4.3 定义课程数据类

    课程页面如图所示:

    Image [3].png

    从课程页面可以看到,一门课程展现出来的数据有:课程名称、课程摘要、作者姓名和头衔、单价以及销量。

    从面向对象的思想来说,课程就是一个对象,这个对象有如下属性:课程名称、课程摘要、作者姓名和头衔、单价以及销量。用代码表示就是这样的:

    class CourseData(object):
     def __init__(self, course_name, summary, lecturer_name_and_title, price, subscribe_num):
     super().__init__()
     self.course_name = course_name
     self.summary = summary
     self.lecturer_name_and_title = lecturer_name_and_title
     self.price = price
     self.subscribe_num = subscribe_num
    

    4.4 获取所有课程数据

    通过Appium分析页面的源代码,可以很容易解析得到课程的各种数据。

    1572163652655.png

    代码如下:

    course_names = temp.find_element_by_id('com.luojilab.player:id/column_name') #课程名称
    summaries = temp.find_element_by_id('com.luojilab.player:id/summary') # 摘要
    lecturer_name_and_titles = temp.find_element_by_id(
    'com.luojilab.player:id/tv_name_and_title') # 讲师
    prices = temp.find_element_by_id('com.luojilab.player:id/price') #价格
    subscribe_nums = temp.find_element_by_id('com.luojilab.player:id/tv_subscribe_num') # 价格
    

    当获取完一屏的数据,需要向上滑动继续获取数据。

    Appium滑动API说明:

    方法:swipe(int start x,int start y,int end x,int y,duration) 
    参数说明:
    int start x:开始滑动的x坐标;
    int start y:开始滑动的y坐标 ;
    int end x:结束点x坐标;
    int end y:结束点y坐标; 
    duration:滑动时间。
    

    本文是从屏幕下部滑动到屏幕上部,滑动时间为2000ms。具体代码为:

    self.driver.swipe(FLICK_START_X, FLICK_START_Y, FLICK_START_X,
     FLICK_START_Y + FLICK_DISTANCE,
     2000)
    

    当无法滑动的时候,数据就获取完成了。

    4.5 课程数据写入Excel

    数据获取完成之后需要进行存储。Python中有专门操作Excel的库:openpyxl。本文使用openpyxl将爬取到的数据写入Excel进行保存。核心代码如下:

    # 定义数据输出的Excel
    try:
     wb = openpyxl.load_workbook(PATH)
    except:
     wb = openpyxl.Workbook()
    # wb = openpyxl.Workbook()
    sheet_name = time.strftime("%F")
    sheet = wb.create_sheet(sheet_name)
    row = ["学院", "课程名称", "课程摘要", "主讲人", "单价", "销量", "销售金额"]
    sheet.append(row)
    ...
    wb.save(PATH)
    

    五、总结

    本文使用Appium和夜神模拟器在Windows平台上面实现得到课程数据的爬取。这里给出GitHub代码供大家学习,程序适用于最新版得到APP的课程数据爬取,如遇到APP版本升级等特殊情况,程序也需要进行升级维护。

    GitHub地址

  • 相关阅读:
    Ext.grid.column.Column主要配置项及示例
    Ext.grid.Panel主要配置及示例
    EF Code First关系规则及配置
    ExtJS4系列目录
    EF Code First数据库连接配置
    ASP.NET MVC系列:ASP.NET MVC简介
    Ext JS下载及配置
    Ext.container.Viewport
    Ext.tab.Panel页签
    ASP.NET MVC系列:Controller/Action
  • 原文地址:https://www.cnblogs.com/sgh1023/p/11748072.html
Copyright © 2020-2023  润新知