• 爬虫 — App 爬虫(二)


    一、Appium介绍

    类似于 selenium,找包比较困难,加密参数比较难解的时候使用。

    所需环境

    • node.js

    • Java 的 SDK

    • 安卓的 SDK

    • Appium 应用程序

    • 模拟器

    二、node.js 安装

    node.js 下载官网

    安装步骤

    1、点击 Next;

    在这里插入图片描述

    2、选中勾选框后,点击 Next;

    在这里插入图片描述

    3、选中安装路径后,点击 Next;

    在这里插入图片描述

    4、点击 Next;

    在这里插入图片描述

    5、点击 Next;

    在这里插入图片描述

    6、点击 Install;

    在这里插入图片描述

    7、点击 Finish;

    在这里插入图片描述

    8、安装完成。

    9、验证安装。

    按 win + R,输入 cmd 后,按回车。

    在这里插入图片描述

    在终端窗口输入以下命令:

    node -v 显示安装的 node.js 版本

    npm -v 显示安装的 npm 版本

    在这里插入图片描述

    三、Java 的 SDK 安装以及配置

    点击进入官网下载

    点击进入百度网盘下载,版本:jdk-8u211-windows-x64

    1、安装步骤

    1、点击“下一步”;

    在这里插入图片描述

    2、更改安装路径后,点击“确定”;

    在这里插入图片描述

    3、点击“下一步”;

    在这里插入图片描述

    4、更改安装目录后,点击“下一步”;

    在这里插入图片描述

    5、点击“关闭”;

    在这里插入图片描述

    2、配置环境变量

    1、在桌面上“此电脑”图标上右击,选择“属性”,选择“高级系统设置”;

    2、选择“高级”,点击“环境变量”;

    在这里插入图片描述

    3、找到系统变量,点击“新建”;

    在这里插入图片描述

    4、填入变量名和变量值,变量值为安装路径,点击“确定”;

    变量名输入:JAVA_HOME

    变量值输入:E:\Install\Java\jdk1.8.0_211

    在这里插入图片描述

    5、还需要新建一个变量值,点击“新建”;

    在这里插入图片描述

    6、填入变量名和变量值,点击“确定”;

    变量名输入:CLASS_PATH

    变量值输入:.;%JAVA_HOME%\lib;%JAVA_HOME%\lib\tools.jar

    在这里插入图片描述

    7、选中“Path”,点击“编辑”;

    在这里插入图片描述

    8、点击“新建”,添加一个路径:%JAVA_HOME%\bin 后,点击“确定”;

    在这里插入图片描述

    9、验证是否安装成功,打开终端,输入 java -version,出现对应的版本号就可以了。

    在这里插入图片描述

    四、安卓环境的配置

    点击进入下载地址

    下载后解压到任意目录下

    1、配置环境变量

    1、在桌面上“此电脑”图标上右击,选择“属性”,选择“高级系统设置”;

    2、选择“高级”,点击“环境变量”;

    在这里插入图片描述

    3、找到系统变量,点击“新建”;

    在这里插入图片描述

    4、填入变量名和变量值,变量值为安装路径,点击“确定”;

    变量名输入:ANDROID_HOME

    变量值输入:E:\Install\androidsdk

    在这里插入图片描述

    5、选中“Path”,点击“编辑”;

    在这里插入图片描述

    6、点击“新建”,编辑系统环境的 Path 后,点击“确定”;

    %ANDROID_HOME%\platform-tools

    %ANDROID_HOME%\tools

    在这里插入图片描述

    7、验证是否配置成功,打开终端,输入adb。

    在这里插入图片描述

    adb:安卓调试桥

    Android 环境和开发环境之间桥梁

    可以让用户在电脑上对手机进行全面的操作

    五、Appium 安装

    点击进入下载地址

    1、安装

    1、按需求选择后,点击“安装”;

    在这里插入图片描述

    2、点击“完成”;

    在这里插入图片描述

    2、打开 APP

    方法一:使用 Appium 的内置驱动打开 APP

    方法二:使用 Python 代码打开 APP

    • 在终端查看 selenium 版本

      命令:pip show selenium

    • 版本低于 4.1.1 的需要升级一下(需要先把 Python 升级到 3.7 以上版本)

      命令:pip install selenium==4.1.1

    • 安装 Appium 第三方库

      命令:pip install appium-python-client

      如果报以下错误

      WARNING: You are using pip version 20.1.1; however, version 23.1.2 is available.
      You should consider upgrading via the ‘e:\install\python37\python.exe -m pip install --upgrade pip’ command.

      可在终端输入命令:python.exe -m pip install --upgrade pip

    3、使用

    1、启动模拟器,新开一个模拟器(专门用来采用 Appium 来爬取数据);

    2、进去模拟器后,进入“工具”,进入“设置”,进入“关于平板电脑”,不停的点击版本号,直到出现开发者选项,打开 usb 调试;

    3、重启模拟器 ;

    4、双击打开安装好的 Appium,输入本地 IP 地址 127.0.0.1 后,点击“Start Server v1.15.1”;

    在这里插入图片描述

    5、验证 Appium 是否可以操作模拟器;

    命令:adb devices -l

    在这里插入图片描述

    如果报以下错误

    adb server version (36) doesn’t match this client (41); killing…

    原因:由于 SDK 里 adb 和夜神模拟器的 adb 版本不匹配导致

    解决方法:

    1、找到 androidsdk 文件夹所在目录下的 platform-tools 文件夹下的 adb.exe,复制到桌面,重命名为 nox_adb.exe

    2、找到夜神模拟器安装文件夹所在的目录下的 bin 文件夹下的 nox_adb.exe,重命名为 nox_adb_old.exe

    3、把桌面上的 nox_adb.exe 拷贝到夜神模拟器的 bin 文件夹下

    4、重启模拟器

    6、在模拟器里打开需要获取包名和界面名的页面;

    在终端输入命令:

    adb shell dumpsys window windows | findstr mFocusedApp

    输出结果:

    mFocusedApp=AppWindowToken{c618cec token=Token{577693eActivityRecord{3fe15f9 u0 com.android.browser/.BrowserActivity t7}}}

    包名:com.android.browser

    界面名:.BrowserActivity

    7、运行代码;

    from appium import webdriver  # 导入 appium 的 webdriver 库,用于自动化测试移动应用程序
    
    # 创建一个字典用于存储配置参数
    caps = dict()
    # 配置连接参数
    # 设置系统为 Android
    caps['platformName'] = 'Android'
    # 设置平台版本为 7.1.2(模拟器-关于平板-版本号)
    caps['platformVersion'] = '7.1.2'
    # 设置设备名称为 Android(可以换)
    caps['deviceName'] = 'Android'
    # 设置应用程序的包名
    caps['appPackage'] = 'com.android.browser'
    # 设置应用程序的界面名
    caps['appActivity'] = '.BrowserActivity'
    # 有需要输入中文,需要设置为 True
    caps['unicodeKeyboard'] = True
    # 重置键盘设置,恢复原来的输入法
    caps['resetKeyboard'] = True
    # 禁用应用程序的重置,不需要重置 APP 状态,就设置为 True
    caps['noReset'] = True
    # 设置新命令的超时时间为 6000 毫秒
    caps['newCommandTimeout'] = 6000
    # 设置自动化引擎为 UiAutomator2
    caps['automationName'] = 'UiAutomator2'
    
    # 创建 Appium WebDriver 实例,连接到 Appium 服务器,加载驱动
    driver = webdriver.Remote('http://127.0.0.1:4723/wd/hub', caps)
    # 打开网址
    driver.get('https://www.baidu.com/')
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    六、Appium 使用

    1、定位数据(方法一,不常用)

    1、Appium 先停止服务并且完全退出;

    2、找到 androidsdk 文件夹,点击 tools 文件夹,点击 bin 文件夹,双击 uiautomatorviewer.bat 文件;

    3、点击图标;

    在这里插入图片描述

    4、找到需要定位的数据。

    在这里插入图片描述

    2、定位数据(方法二,常用)

    1、打开 Appium,输入本地 IP 地址 127.0.0.1 后,点击“Start Server v1.15.1”;

    在这里插入图片描述

    2、点击图标;

    在这里插入图片描述

    3、按照代码添加参数;

    # 配置连接参数
    # 设置系统为 Android
    caps['platformName'] = 'Android'
    # 设置平台版本为 7.1.2(模拟器-关于平板-版本号)
    caps['platformVersion'] = '7.1.2'
    # 设置设备名称为 Android(可以换)
    caps['deviceName'] = 'Android'
    # 设置应用程序的包名
    caps['appPackage'] = 'com.android.browser'
    # 设置应用程序的界面名
    caps['appActivity'] = '.BrowserActivity'
    # 有需要输入中文,需要设置为 True
    caps['unicodeKeyboard'] = True
    # 重置键盘设置,恢复原来的输入法
    caps['resetKeyboard'] = True
    # 禁用应用程序的重置,不需要重置 APP 状态,就设置为 True
    caps['noReset'] = True
    # 设置新命令的超时时间为 6000 毫秒
    caps['newCommandTimeout'] = 6000
    # 设置自动化引擎为 UiAutomator2
    caps['automationName'] = 'UiAutomator2'
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    3、练习

    需求:打开浏览器,地址栏输入 www.douban.com 后按回车

    分析:

    1、打开浏览器

    2、鼠标点击地址栏

    3、输入网址

    4、回车

    代码实现

    from appium import webdriver  # 导入 appium 的 webdriver 库,用于自动化测试移动应用程序
    from appium.webdriver.extensions.android.nativekey import AndroidKey  # 导入 AndroidKey 模块,用于模拟 Android 设备的按键操作
    from selenium.webdriver.common.by import By  # 导入 By 模块,用于定位元素
    
    # 创建一个字典用于存储配置参数
    caps = dict()
    # 配置连接参数
    # 设置系统为 Android
    caps['platformName'] = 'Android'
    # 设置平台版本为 7.1.2(模拟器-关于平板-版本号)
    caps['platformVersion'] = '7.1.2'
    # 设置设备名称为 Android(可以换)
    caps['deviceName'] = 'Android'
    # 设置应用程序的包名--浏览器
    caps['appPackage'] = 'com.android.browser'
    # 设置应用程序的界面名
    caps['appActivity'] = '.BrowserActivity'
    # 有需要输入中文,需要设置为 True
    caps['unicodeKeyboard'] = True
    # 重置键盘设置,恢复原来的输入法
    caps['resetKeyboard'] = True
    # 禁用应用程序的重置,不需要重置 APP 状态,就设置为 True
    caps['noReset'] = True
    # 设置新命令的超时时间为 6000 毫秒
    caps['newCommandTimeout'] = 6000
    # 设置自动化引擎为 UiAutomator2
    caps['automationName'] = 'UiAutomator2'
    
    # 创建 Appium WebDriver 实例,连接到 Appium 服务器,加载驱动
    driver = webdriver.Remote('http://127.0.0.1:4723/wd/hub', caps)
    # 定位输入框元素
    input_tag = driver.find_element(By.ID, 'com.android.browser:id/url')
    # 进行点击操作
    input_tag.click()
    # 在输入框中输入指定的网址
    input_tag.send_keys('www.douban.com')
    # 模拟按下 ENTER 键
    driver.press_keycode(AndroidKey.ENTER)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    4、界面滑动

    分为:

    从一个元素滑动到另外一个元素

    从一个位置滑动到另外一个位置

    需求:进入“设置”界面,从“WLAN”滑动到“声音”

    分析:

    1、在模拟器里打开“设置”界面;

    2、获取“设置”界面的包名和界面名;

    在终端输入命令:

    adb shell dumpsys window windows | findstr mFocusedApp

    输出结果:

    mFocusedApp=AppWindowToken{b9a8e16 token=Token{2ed7d8 ActivityRecord{a2e16bb u0 com.android.settings/.Settings t13}}}

    包名:com.android.settings

    界面名:.Settings

    from appium import webdriver  # 导入 appium 的 webdriver 库,用于自动化测试移动应用程序
    
    # 创建一个字典用于存储配置参数
    caps = dict()
    # 配置连接参数
    # 设置系统为 Android
    caps['platformName'] = 'Android'
    # 设置平台版本为 7.1.1(模拟器-关于平板-版本号)
    caps['platformVersion'] = '7.1.1'
    # 设置设备名称为 Android(可以换)
    caps['deviceName'] = 'Android'
    # 设置应用程序的包名--设置
    caps['appPackage'] = 'com.android.settings'
    # 设置应用程序的界面名
    caps['appActivity'] = '.Settings'
    # 有需要输入中文,需要设置为 True
    caps['unicodeKeyboard'] = True
    # 重置键盘设置,恢复原来的输入法
    caps['resetKeyboard'] = True
    # 禁用应用程序的重置,不需要重置 APP 状态,就设置为 True
    caps['noReset'] = True
    # 设置新命令的超时时间为 6000 毫秒
    caps['newCommandTimeout'] = 6000
    # 设置自动化引擎为 UiAutomator2
    caps['automationName'] = 'UiAutomator2'
    
    # 创建 Appium WebDriver 实例,连接到 Appium 服务器,加载驱动
    driver = webdriver.Remote('http://127.0.0.1:4723/wd/hub', caps)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    3、在 Appium 里输入配置参数,保存好后,运行;

    4、定位数据“WLAN”和“声音”的位置,然后滑动;

    from appium import webdriver  # 导入 appium 的 webdriver 库,用于自动化测试移动应用程序
    from selenium.webdriver.common.by import By  # 导入 By 模块,用于定位元素
    
    # 创建一个字典用于存储配置参数
    caps = dict()
    # 配置连接参数
    # 设置系统为 Android
    caps['platformName'] = 'Android'
    # 设置平台版本为 7.1.1(模拟器-关于平板-版本号)
    caps['platformVersion'] = '7.1.1'
    # 设置设备名称为 Android(可以换)
    caps['deviceName'] = 'Android'
    # 设置应用程序的包名--设置
    caps['appPackage'] = 'com.android.settings'
    # 设置应用程序的界面名
    caps['appActivity'] = '.Settings'
    # 有需要输入中文,需要设置为 True
    caps['unicodeKeyboard'] = True
    # 重置键盘设置,恢复原来的输入法
    caps['resetKeyboard'] = True
    # 禁用应用程序的重置,不需要重置 APP 状态,就设置为 True
    caps['noReset'] = True
    # 设置新命令的超时时间为 6000 毫秒
    caps['newCommandTimeout'] = 6000
    # 设置自动化引擎为 UiAutomator2
    caps['automationName'] = 'UiAutomator2'
    
    # 创建 Appium WebDriver 实例,连接到 Appium 服务器,加载驱动
    driver = webdriver.Remote('http://127.0.0.1:4723/wd/hub', caps)
    # 定位元素--WLAN
    WLAN = driver.find_element(By.XPATH, '//*[@text="WLAN"]')
    # 定位元素--声音
    sy = driver.find_element(By.XPATH, '//*[@text="声音"]')
    # 滑动
    # 从一个元素滑动到另外一个元素
    # 手的操作是往上,内容是往下加载
    driver.drag_and_drop(sy, WLAN)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    注意:

    如果要滑动到的位置不在第一页里,直接滑动会报错

    需要滑动到第一页的最后的位置,等下一页的内容加载出来,才能再滑动

    七、案例

    目标 APP:笔趣阁

    需求:爬取排行榜的标题及简介

    分析

    1、打开笔趣阁 APP

    2、点击榜单

    3、点击热搜榜

    4、获取第一页后,滑动,获取第二页数据,滑动,直到获取50条数据

    5、多次滑动,可以用循环

    6、不通过直接获取包名和界面名来打开笔趣阁,可以直接通过定位 APP 位置

    代码实现

    import json  # 导入 json 模块,用于处理 JSON 格式的数据
    import time  # 导入 time 模块,用于添加延时等待
    from appium import webdriver  # 导入 appium 的 webdriver 库,用于自动化测试移动应用程序
    from selenium.webdriver.common.by import By  # 导入 By 模块,用于定位元素
    
    # 创建一个字典用于存储配置参数
    caps = dict()
    # 配置连接参数
    # 设置系统为 Android
    caps['platformName'] = 'Android'
    # 设置平台版本为 7.1.1(模拟器-关于平板-版本号)
    caps['platformVersion'] = '7.1.1'
    # 设置设备名称为 Android(可以换)
    caps['deviceName'] = 'Android'
    # 有需要输入中文,需要设置为 True
    caps['unicodeKeyboard'] = True
    # 重置键盘设置,恢复原来的输入法
    caps['resetKeyboard'] = True
    # 禁用应用程序的重置,不需要重置 APP 状态,就设置为 True
    caps['noReset'] = True
    # 设置新命令的超时时间为 6000 毫秒
    caps['newCommandTimeout'] = 6000
    # 设置自动化引擎为 UiAutomator2
    caps['automationName'] = 'UiAutomator2'
    
    # 创建 Appium WebDriver 实例,连接到 Appium 服务器,加载驱动
    driver = webdriver.Remote('http://127.0.0.1:4723/wd/hub', caps)
    # 定位笔趣阁 App,并点击
    driver.find_element(By.XPATH, '//android.widget.TextView[@content-desc="笔趣阁"]').click()
    # 等待3秒
    time.sleep(3)
    # 点击榜单
    driver.find_element(By.XPATH, '/hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.TabHost/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.LinearLayout/android.view.ViewGroup/androidx.recyclerview.widget.RecyclerView/android.widget.LinearLayout[1]/android.widget.LinearLayout/android.widget.LinearLayout[2]/android.widget.ImageView').click()
    # 等待2秒
    time.sleep(2)
    # 点击热搜榜
    driver.find_element(By.ID, 'com.bqg.ddnoverl:id/tvAiRkName').click()
    # 创建一个空集合,用于存储数据项,自动去重
    data = set()
    # 获取屏幕的尺寸
    window_size = driver.get_window_size()
    # 高跟宽
    height, width = window_size.get('height'), window_size.get('width')
    while True:
        # 等待3秒
        time.sleep(3)
        # 获取多个榜单元素
        contents = driver.find_elements(By.XPATH, '/hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.LinearLayout/android.view.ViewGroup/androidx.recyclerview.widget.RecyclerView/android.widget.RelativeLayout/android.widget.RelativeLayout/android.widget.LinearLayout')
        # 打印榜单元素数量
        print(len(contents))
        # 循环获取数据
        for content in contents:
            try:
                # 创建一个空字典,用于存储每个内容项的信息
                item = {}
                # 标题
                item['title'] = content.find_element(By.ID, 'com.bqg.ddnoverl:id/tvClTitle').text
                # 简介
                item['content'] = content.find_element(By.ID, 'com.bqg.ddnoverl:id/tvClDesc').text
                # 打印数据
                print(item)
                # 将数据转换为 JSON 格式并添加到集合中
                # 集合里面的添加是不能直接添加字典的,需要转换类型
                data.add(json.dumps(item, ensure_ascii=False))
            except:
                # 处理数据异常情况
                print('数据有误')
        if len(data) < 50:
            # 在应用中进行滑动操作,从屏幕的上部中间位置向下滑动到屏幕的下部中间位置,持续时间为1000毫秒
            driver.swipe(width * 0.5, height * 0.7, width * 0.5, height * 0.2, 1000)
            # 打印提示
            print("滑动成功")
        else:
            # 数据达到50个,跳出循环
            break
    # 打印最终的数据集合
    print(data)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77

    记录学习过程,欢迎讨论交流,尊重原创,转载请注明出处~

  • 相关阅读:
    效率为王,居家办公必备的5款小工具
    androdi知识笔记
    web网站 固定的邀请码字符 能被爬虫爬取吗?动态改变邀请码的字符是不是可以避免爬虫爬取或数据泄露
    [CSS入门到进阶] 外国前端开发者说的 Intrinsic Ratios in css 是什么意思?
    深入理解机器学习——类别不平衡学习(Imbalanced Learning):样本采样技术-[基础知识]
    Redis集群
    自从看了谷歌大神拼S强撸的Spring源码笔记,我从渣渣练成了钢铁
    短时间内防止多次点击
    ​统信UOS丨开机无法进入系统丨进阶操作
    面试题:在 Java 中 new 一个对象的流程是怎样的?彻底被问懵了。。
  • 原文地址:https://blog.csdn.net/muyuhen/article/details/132829007