美文网首页工具的使用
使用Appium爬取淘宝App数据

使用Appium爬取淘宝App数据

作者: DebugWorld | 来源:发表于2019-03-26 12:13 被阅读474次

    0x01、介绍说明

    1、简介

    图片 Appium是一个自动化测试开源工具。通过WebDriver协议驱动IOS、Android、Windows Phone平台上的原生应用、混合应用和web应用。

    2、Appium工作原理

    Appium选择了Client/Server的设计模式,Server可以在OSX、Windows以及Linux系统上运行,Client支持Ruby、Python、Java、PHP、C#、JavaScript等语言的实现。

    当我在MAC平台上,通过Python(python-client )编写了一个appium自动化脚本并执行,请求会首先到 appium.dum (MAC下的appium-Server),appium-Server通过解析,驱动iOS设备来执行appium自动化脚本。或者,我在Windows平台上,通过Java( java-client )编写了一个appium自动化脚本并执行,请求会首先到 appiumForWindow.zip(Window下的appium-Server),appium-Server通过解析,驱动Android虚拟机或真机来执行appium脚本。所以,你会看到appium的强大之处就在于此。

    0x02、环境配置

    本教程以MacBook Pro通过Python程序控制Android系统的淘宝App为例,因为Appium依赖Android SDK,Android SDK需要Java环境,所以所需环境如下:

    • Java
    • Android SDK
    • Appium
    • Python

    1、 Java安装

    # 在终端输入以下命令
    java -version
    
    # 命令反馈信息,说明安装成功
    java version "1.8.0_202"
    Java(TM) SE Runtime Environment (build 1.8.0_202-b08)
    Java HotSpot(TM) 64-Bit Server VM (build 25.202-b08, mixed mode)
    
    • 配置环境:
    # 打开.bash_profile文件
    vim ~/.bash_profile
    
    # 配置环境变量(路径需要更改为自己的Java安装路径),保存并退出
    export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_202.jdk/Contents/Home
    export CLASS_PATH=$JAVA_HOME/lib
    export PATH=$PATH:$JAVA_HOME/bin
    
    # 配置生效
    source ~/.bash_profile
    

    2、Android SDK 安装

    • 下载:下载地址
    • 解压:进入目录android-sdk-macoxs --> tool, 双击android文件来启动Android SDK Manager
    • Android SDK Manager:
      • SDK Path: 安装路径
      • 只需要安装Android SDK Tolls 、Android SDK Platform-tools和Android SDK Build-tools(默认会选中Android 9的模拟系统,如果下载了Android的模拟系统,只有无尽等待)
      • 点击 install
    图片
    • 配置环境
    # 打开.bash_profile
    vim ~/.bash_profile
    
    # 输入自己的路径,保存并退出
    export ANDROID_HOME=/Users/xxxxxxx/Documents/Android/android-sdk-macosx
    export PATH=$PATH:$ANDROID_HOME/tools:$ANDROID_HOME/platform-tools
    
    # 使配置生效
    vim ~/.bash_profile
    
    # 输入命令,查看是否成功
    adb --version
    # 出现-bash: adb: command not found错误,常见原因有两种
    # 1. 环境变量配置出错
    # 2. 重启电脑(至于为什么需要重启,母鸡啊)
    

    3、Appium 安装

    # 先安装brew, 如果已经安装过了请跳过
    /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
    brew update
    
    # 再安装npm:
    brew install npm
    
    # 安装cnpm:淘宝NPM镜像
    npm install -g cnpm --registry=https://registry.npm.taobao.org
    
    # 用cnpm安装appium
    cnpm install -g appium
    
    # 检测是否成功
    appium
    
    # 安装appium-doctor, 该软件能够检测appium正常运行所需要的环境是否都有
    npm install appium-doctor -g
    
    # 然后检测是环境配置好,如果出错重启电脑
    appium-doctor 
    
    • 根据appium-doctor反馈结果安装所需环境
    # Xcode是控制ios的,暂时不用问
    
    # Carthage was NOT founf! 解决办法
    brew install carthage
    
    图片

    4、Python3安装

    图片
    图片
    • 安装:按照步骤安装就行
    • python2和python3共存
    # mac 输入python命令默认是python2.7,通过以下命令查看不同python版本所在的目录
    which python
    which python2
    which python3
    
    # 创建软链接,python2和python3共存
    # python2.7的软连接设置为python2
    ln -s /usr/bin/python2.7 /usr/bin/python2
    
    # 删除原有的python的软连接
    rm /usr/bin/python
    # 把python3的软连接设置为python
    ln -s /usr/local/bin/python3 /usr/bin/python
    

    0x03、建立连接

    pc端和移动端的连接有两种方式USB连接和无线连接

    1、 USB连接

    • 打开开发者模式和USB调试:允许USB安装、USB调试等权限
    • 打开pc终端
    # 查看手机设备信息
    adb devices 
    
    # 命令反馈信息,出现设备id号说明连接成功
    * daemon not running; starting now at tcp:5037
    * daemon started successfully
    xxxxxxx unauthorized
    

    2、无线连接

    • 在USB连接下,输入 adb tcpip 5555
    # 端口号是任意的,只要不被占用就行
    adb tcpip 5555
    
    # 命令反馈信息
    restarting in TCP mode port: 5555
    
    • 查看手机设备局域网ip
    # 查看手机设备的局域网ip
    adb shell ip -f inet addr show wlan0 
    
    # 命令反馈信息,其中192.168.1.5就是内网ip,或者在手机端的wifi设置查看
    * 22: wlan0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP qlen 1000
    
        inet 192.168.1.5/24 brd 192.168.1.255 scope global wlan0
    
           valid_lft forever preferred_lft forever
    
    • 无线连接
    # ip需要改为你手机设置的ip
    adb connect 192.168.1.5
    
    # 命令反馈信息,说明连接成功,就可以不需要USB数据线连接了,但是pc端和移动端需要在同一个局域网下
    connected to 192.168.1.5:5555
    
    • 验证
    # 断掉USB连接,输入以下命令
    adb devices
    
    # 命令反馈信息,此时手机的设备号就变成192.168.1.5:5555了
    List of devices attached
    192.168.1.5:5555    device
    

    3、 SDK 命令

    adb kill-server          # 断开连接
    adb install path_to_apk  # 通过命令安装app
    

    更多命令:官方教程

    0x04、控制程序

    1、运行appium

    # 启动命令。4444 端口号(可以随意设置,官方建议>=4444)、192.168.1.5:5555:获取到的手机设备号,在python程序里会用到。当程序python运行之后,该命令会打印操作日志
    appium -a 127.0.0.1 -p 4444 -U 192.168.1.5:5555
    

    2、程序

    • 所需python库
    pip install Appium-Python-Client
    pip install selenium
    
    • 定位元素
    # 打开终端输入UIAutomatorviewer,就可以查看定位元素了
    UIAutomatorviewer
    
    图片
    • 爬取淘宝app
    import time
    from appium import webdriver
    from appium.webdriver.common import mobileby
    from appium.webdriver.webdriver import WebDriver
    from selenium.webdriver.support.wait import WebDriverWait
    from selenium.webdriver.support import expected_conditions as EC
    
    
    desired_capabilities = {
            'platformName': 'Android',                          # 系统
            'deviceName': 'xxxxxxxx',                           # 移动设备号
            'platformVersion': '6.0.1',                         # 系统版本
            'appPackage': 'com.taobao.taobao',                  # 操作的app
            'appActivity': 'com.taobao.tao.welcome.Welcome',    # 打开淘宝app首页
            'unicodeKeyboard': True,
            'resetKeyboard': True,
            'dontStopAppOnReset': True,
            'autoGrantPermissions': True,
            'noReset': True,
            'automationName': 'uiautomator2',
            'newCommandTimeout': '36000',                       # 超时时间
            'systemPort': '8202',                               # 端口号,操作不用设备使用不同端口号
            'udid': 'xxxxxxxx',                                 # 移动设备号
            'command_executor': 'http://127.0.0.1:4444/wd/hub'  # 和启动命令保持一致
    }
    
    
    class AppiumDemo(object):
        def __init__(self):
            self.driver = webdriver.Remote(command_executor=desired_capabilities['command_executor'],
                                           desired_capabilities=desired_capabilities)
            self.by = mobileby.MobileBy()
    
            # 点击搜索框
            self.wait_find_element(by_type=self.by.ID, value='com.taobao.taobao:id/home_searchedit').click()
            # 点击店铺搜索
            self.wait_find_element(by_type=self.by.XPATH, value='//android.widget.TextView[@text="店铺"]').click()
    
        def wait_find_element(self, by_type: str, value: str, driver: WebDriver = None):
            """
            获取单个元素, 显式等待
            :param driver: 驱动对象
            :param by_type: 查找元素的操作
            :param value: 查找元素的方法
            :return:
            """
            driver = driver or self.driver
            if not driver:
                return driver
            try:
                WebDriverWait(driver, 10).until(EC.visibility_of_element_located(locator=(by_type, value)))
                return driver.find_element(by_type, value)
            except:
                # self.logger.warning(traceback.format_exc())
                return False
    
        def wait_find_elements(self, by_type: str, value: str, driver: WebDriver = None):
            """
            获取多个元素, 显式等待
            :param driver:
            :param by_type:
            :param value:
            :return:
            """
            driver = driver or self.driver
            if not driver:
                return driver
            try:
                WebDriverWait(driver, 10).until(EC.presence_of_all_elements_located(locator=(by_type, value)))
                return driver.find_elements(by_type, value)
            except:
                return False
    
        def get_size(self, driver: WebDriver = None):
            """
            获取屏幕大小
            :param driver:
            :return:
            """
            driver = driver or self.driver
            if not driver:
                return driver
    
            x = driver.get_window_size()['width']
            y = driver.get_window_size()['height']
            return [x, y]
    
        def swipe_up(self, driver: WebDriver = None, _time: int = 1000):
            """
            向上滑动
            :param driver:
            :param _time:
            :return:
            """
            driver = driver or self.driver
            if not driver:
                return driver
            try:
                size = self.get_size(driver)
                x1 = int(size[0] * 0.5)  # 起始x坐标
                y1 = int(size[1] * 0.80)  # 起始y坐标
                y2 = int(size[1] * 0.30)  # 终点y坐标
                driver.swipe(x1, y1, x1, y2, _time)
                return True
            except:
                return False
    
        def execute(self, seed):
            self.wait_find_element(by_type=self.by.ID, value='com.taobao.taobao:id/searchEdit').clear().send_keys(seed['keyword'])
            self.wait_find_element(by_type=self.by.ID, value='com.taobao.taobao:id/searchbtn').click()
            self.wait_find_element(by_type=self.by.XPATH, value='//android.widget.TextView[@text="销量优先"]').click()
            shop_list = self.wait_find_elements(by_type=self.by.ID, value='com.taobao.taobao:id/shopTitle')
            for shop_info in shop_list:
                shop_info.click()
                # 点击全部宝贝
                self.wait_find_element(by_type=self.by.XPATH, value='//android.widget.FrameLayout'
                                                                    '[@content-desc="全部宝贝"]').click()
    
                for i in range(3):
                    # 获取这一屏的数据
                    item_list = self.wait_find_elements(by_type=self.by.ID, value="com.taobao.taobao:id/title")
                    for item_info in item_list:
                        print(item_info.text)
                    self.swipe_up()                 # 向上滑动
                    time.sleep(0.5)                 # 一定要延时
                self.driver.back()                  # 返回上一级
            self.driver.back()
    
    
    def main():
        seed = {
            'keyword': 'Python 书'
        }
        spider = AppiumDemo()
        while True:
            spider.execute(seed=seed)
    
    
    if __name__ == '__main__':
        main()
    

    程序第一次运行的时候,会在手机安装3个app,一定要同意安装,只有Appium Settings在桌面有图标

    • Appium Settings
    • io.appium.uiautomator2.server
    • io.appium.uiautomator2.server.test

    0x05、参考

    Android SDK官方教程
    Appium官方教程
    Appium新手入门

    相关文章

      网友评论

        本文标题:使用Appium爬取淘宝App数据

        本文链接:https://www.haomeiwen.com/subject/xllgvqtx.html