使用mitmproxy + appium + python 全自动抓取公众号文章

【转载请注明出处】:https://blog.csdn.net/huahao1989/article/details/106180223

1. 先使用mitmproxy代理抓微信公众号历史文章列表

实现思路:

在电脑上安装 mitmproxy代理,手机和电脑连同一wifi,手机配置当前电脑为代理服务器,然后手动查看公众号历史文章列表,这样电脑上就可以获得列表,然后再根据列表中的详情url拿到公众号文章详情。

1.1 安装mitmproxy

需要先安装Python 3.6 (或更高版本)和 pip3.6 ,之后执行以下命令安装

sudo pip3.6 install -U pip
sudo pip3.6 install mitmproxy
1.2 准备代理脚本wechat_proxy.py

更多的例子可以参考官网simple

# -*- coding: utf-8 -*-
# @Time    : 2019/7/11
# @Author  : zl

from mitmproxy import http
from mitmproxy import ctx
from urllib import parse
import json


def response(flow: http.HTTPFlow):
    try:
        info = ctx.log.info
        req = flow.request
        resp = flow.response
        url = req.url
        purl = parse.urlparse(url)
        param_dict = parse.parse_qs(purl.query)
        host = purl.hostname
        path = purl.path

        if host == 'mp.weixin.qq.com' and path == '/mp/profile_ext':
            action = param_dict['action'][0]
            if action in ['home', 'getmsg']:
                msg = {}
                msg['url'] = url
                msg['action'] = action
                msg['req_header'] = dict(req.headers)
                msg['resp_header'] = dict(resp.headers)
                if action == 'getmsg':
                    msg['resp_body'] = json.loads(resp.content)
                info('msg : %s----' % msg)

    except Exception as e:
        ctx.log.error('wechatproxy error, %s' % e)

执行下面的脚本启动:

mitmdump -p 8888 -s ${script_home}/wechat_proxy.py

手机浏览器访问http://mitm.it/安装证书并启用,然后配置手机代理,翻阅公众号文章列表既可以看到消息日志,文章详情的抓取这里不再介绍

mitmproxy其他的用法可以参考官方文档

2. 使用appium实现自动化

2.1 前提

2.1.1 安装JDK 并设置环境变量

1. 到Java官网下载相应的JDK并安装
2. 设置环境变量
   - 添加JAVA_HOME 
   - 在PATH变量末尾追加 ;%JAVA_HOME%/bin;
   - 添加CLASSPATH,设置值为%JAVA_HOME%\lib;%JAVA_HOME%\lib\tools.jar

2.1.2 安装Android SDK 并设置环境变量
注意:安装Android SDK需要并更新你的SDK repository

1.  到[Android 官网](http://developer.android.com/sdk/index.html#Other)下载并安装SDK
2.  设置环境变量
    - 添加`ANDROID_HOME`
    - 在`path`环境变量值末尾追加:`;%ANDROID_HOME%\tools;%ANDROID_HOME%\platform-tools;`

2.1.3 安装Nodejs

#先安装一个node版本管理软件 
brew install n 
#或者
curl -L https://git.io/n-install | bash
#安装node8.6
sudo n 8.6.0
#后面安装的时候有可能没权限
sudo chown -R $(whoami):admin /usr/local/**

注:不要安装太高版本,否则后面安装某些依赖会不兼容。

2.2 安装appium

安装appium有两种方式:

  • 使用 npm (Node js 的管理与分发工具) 安装Appium
  • 使用Appium官方安装包安装

下面只介绍npm安装方式,如果要装desktop,直接去官网下载最新版安装即可。

将npm的下载地址更改为淘宝的NPM镜像源

npm config set registry=https://registry.npm.taobao.org
npm config get registry

确认镜像源替换成功之后执行下面命令安装Appium

npm install -g appium
2.3 安装其他依赖

2.3.1 安装opencv4nodejs
如果已经安装openCV,则需要在安装opencv4nodejs之前设置

export OPENCV4NODEJS_DISABLE_AUTOBUILD=1
export OPENCV_INCLUDE_DIR=/usr/local/include/opencv4
export OPENCV_LIB_DIR=/usr/local/lib
export OPENCV_BIN_DIR=/usr/local/bin

npm安装

npm install -g opencv4nodejs

2.3.2 安装idevicelocation

brew install libzip libplist openssl libimobiledevice
git clone https://github.com/JonGabilondoAngulo/idevicelocation.git
cd idevicelocation
make
sudo make install
  • 遇到问题

    checking for libimobiledevice-1.0 >= 1.2.1... no
    configure: error: Package requirements (libimobiledevice-1.0 >= 1.2.1) were not met:
    Package 'openssl', required by 'libimobiledevice-1.0', not found
    

    解决方法

    ln -s /usr/local/Cellar/openssl/${YOUR_OPENSSL_VERSION}/lib/pkgconfig/* /usr/local/lib/pkgconfig/
    

2.3.3 安装idb 及 idb_companion

brew tap facebook/fb
brew install idb-companion
brew tap cartr/qt4
brew tap-pin cartr/qt4
brew install cartr/qt4/qt@4
pip3.6 install fb-idb
brew install cmake usbmuxd libimobiledevice

执行

$ idb list-targets
...
iPhone X | 569C0F94-5D53-40D2-AF8F-F4AA5BAA7D5E | Shutdown | simulator | iOS 12.2 | x86_64 | No Companion Connected
iPhone Xs | 2A1C6A5A-0C67-46FD-B3F5-3CB42FFB38B5 | Shutdown | simulator | iOS 12.2 | x86_64 | No Companion Connected
iPhone Xs Max | D3CF178F-EF61-4CD3-BB3B-F5ECAD246310 | Shutdown | simulator | iOS 12.2 | x86_64 | No Companion Connected
iPhone Xʀ | 74064851-4B98-473A-8110-225202BB86F6 | Shutdown | simulator | iOS 12.2 | x86_64 | No Companion Connected
...
  • 遇到问题1

    Error: An unexpected error occurred during the `brew link` step
    The formula built, but is not symlinked into /usr/local
    Permission denied @ dir_s_mkdir - /usr/local/Frameworks
    Error: Permission denied @ dir_s_mkdir - /usr/local/Frameworks
    

    解决

    sudo chown -R $(whoami):admin /usr/local/**
    sudo mkdir /usr/local/Frameworks
    sudo chown $(whoami):admin /usr/local/Frameworks
    
  • 遇到问题2
    执行idb命令报错

    TypeError: __init__() got an unexpected keyword argument 'serialized_options'
    

    解决

    pip3.6  install -U protobuf
    

2.3.4 安装bundletool

cd ${ANDROID_HOME}
mkdir bundle-tools
wget https://github.com/google/bundletool/releases/download/0.10.1/bundletool-all-0.10.1.jar
mv bundletool-all-0.10.1.jar bundletool.jar
sudo chmod 755 bundletool.jar
sudo chown $(whoami):admin bundletool.jar

2.3.5 安装剩余依赖

npm install -g ffmpeg
npm install -g mjpeg-consumer
brew tap wix/brew
brew install applesimutils
brew install ios-deploy
brew install ios-webkit-debug-proxy
brew cask install osxfuse
brew install ifuse --HEAD 
brew install carthage
brew install fbsimctl --HEAD
gem install xcpretty
2.4 验证安装

通过appium-doctor的命令来检查当前appium安装是否完善,当前的JDK、SDK等环境是否配置正确。

npm install -g appium-doctor
appium-doctor

2.5 运行测试demo准备
2.5.1 下载appium源码。
git clone https://github.com/appium/appium.git
2.5.2 启动appium 服务
appium
2.5.3 安装客户端驱动程序

cd到${code_dir}/appium/sample-code/python目录下,运行下面命令就可以运行示例了,appium本身支持多种语言的客户端,我这里语言选择的是python

npm install -g appium-uiautomator2-driver
npm install -g webdriverio
npm install -g app-inspector
pip3.6 install -r requirements.txt
pip3.6 install -U facebook-wda
2.6 在模拟器和真机上运行测试脚本
2.6.1 用Android 模拟器进行测试
py.test test/test_android_selectors.py 

报错

E  WebDriverException: Message: An unknown server-side error occurred while processing the command. Original error: Unable to find an active device or emulator with OS 8.0. The following are available: emulator-5554 (9)

这里已经提示的很清楚了,就是没有找到Android 8.0版本的设备或者模拟器,发现了可用的设备,Android平台版本是9,设备版本是emulator-5554,根据提示修改helpers.py的默认版本或者设置环境变量,

ANDROID_BASE_CAPS = {
    'app': os.path.abspath('../apps/ApiDemos-debug.apk'),
    'automationName': 'UIAutomator2',
    'platformName': 'Android',
    'platformVersion': os.getenv('ANDROID_PLATFORM_VERSION') or '9',
    'deviceName': os.getenv('ANDROID_DEVICE_VERSION') or 'emulator-5554',
}

或者

export ANDROID_PLATFORM_VERSION=9
export ANDROID_DEVICE_VERSION=emulator-5554

注释掉helpers.py中上报到saucelabs的调用

 def fin():
            # report_to_sauce(driver.session_id)

也可以去https://saucelabs.com注册账号,然后设置环境变量

export SAUCE_LABS=
export SAUCE_USERNAME=
export SAUCE_ACCESS_KEY=

然后再执行测试脚本
使用mitmproxy + appium + python 全自动抓取公众号文章_第1张图片

2.6.2 用Android真机测试

2.6.2.1 连接手机

  • 使用数据线通过USB接口将手机与电脑连接,在终端中执行如下命令:
  adb devices  

image.png
表示数据线已经连接成功,但是使用数据线有时候不是很方便,也不能准确测试耗电量,下面介绍无线连接方式

  • 使用无线连接(在同一网段)
    一般在设置-关于手机-状态-IP地址可以找到手机的IP,或者执行命令:

    adb shell ip -f inet addr show wlan0
    

    image.png

    adb tcpip 5555
    //多个设备的话需要指定具体的设备
    //adb -s f489be9c tcpip 5555
    adb connect 192.168.1.5:5555
    

    使用mitmproxy + appium + python 全自动抓取公众号文章_第2张图片

这时候就可以拔掉数据线了。
注:要断开连接,执行:adb disconnect

2.6.2.2 执行测试脚本

export ANDROID_PLATFORM_VERSION=6.0.1
export ANDROID_DEVICE_VERSION=192.168.1.5:5555
py.test test/test_android_selectors.py 

使用mitmproxy + appium + python 全自动抓取公众号文章_第3张图片

2.6.3 用ios 模拟器测试

2.6.3.1 ios 模拟器基本命令
列出可用的设备、设备类型、运行时或设备对。

simctl list [-j | --json] [-v] [devices|devicetypes|runtimes|pairs] [|available]
//列出可用的设备
xcrun simctl list devices

其他命令

#启动iPhone XR模拟器
open "/Applications/Xcode.app/Contents/Developer/Applications/Simulator.app/"
xcrun simctl boot "D9309483-64F9-499F-B295-CD2C5FAA75C8"
#重置iPhone XR模拟器
xcrun simctl erase "D9309483-64F9-499F-B295-CD2C5FAA75C8"
#关闭iPhone XR模拟器
xcrun simctl shutdown "D9309483-64F9-499F-B295-CD2C5FAA75C8"
#关闭所有模拟器
xcrun simctl shutdown booted

2.6.3.2 调试WebDriverAgent

$ which appium
/usr/local/bin/appium
$ ls -l /usr/local/bin/appium
lrwxr-xr-x  1 eyison  admin  44  7 19 01:34 /usr/local/bin/appium -> ../lib/node_modules/appium/build/lib/main.js
$ cd /usr/local/lib/node_modules/appium/node_modules/appium-xcuitest-driver/WebDriverAgent
# 用 Xcode 打开 WebDriverAgent.xcodeproj
$ open WebDriverAgent.xcodeproj

使用mitmproxy + appium + python 全自动抓取公众号文章_第4张图片

WebDriverAgentLib->Build Setting->Runpath Search Paths->添加变量:

$(SRCROOT)/../Carthage/Build/iOS
$(PROJECT)/Carthage/Build/iOS

直接在iPhone XR上运行IntegrationApp进行测试,执行没有报错就OK。

  • 遇到的错误1
'interfaceOrientation' is deprecated: first deprecated in iOS 8.0

解决:
双击错误定位,将self.interfaceOrientation 换成[[UIApplication sharedApplication] statusBarOrientation]

  if (UIInterfaceOrientationIsPortrait(self.interfaceOrientation)) {
    ...

改成

  if (UIInterfaceOrientationIsPortrait([[UIApplication sharedApplication] statusBarOrientation])) {
    ...  
  • 遇到的错误2:
 /usr/local/lib/node_modules/appium/node_modules/appium-xcuitest-driver/WebDriverAgent/WebDriverAgent.xcodeproj User-supplied CFBundleIdentifier value 'com.facebook.wda.integrationApp' in the Info.plist must be the same as the PRODUCT_BUNDLE_IDENTIFIER build setting value 'com.facebook.IntegrationApp23'.

解决:
双击错误定位,将Product Bundle Identifier的值改成和Info.plist 一致即可
使用mitmproxy + appium + python 全自动抓取公众号文章_第5张图片

2.6.3.3 执行测试脚本

export IOS_PLATFORM_VERSION=12.0
export IOS_DEVICE_NAME=iPhone XR
export UDID=D9309483-64F9-499F-B295-CD2C5FAA75C8
py.test test/test_ios_selectors.py

使用mitmproxy + appium + python 全自动抓取公众号文章_第6张图片

  • 遇到的问题1:
  [WD Proxy] Got response with status 200: {"value":"-[XCUIElementQuery elementSnapshotForDebugDescription]: unrecognized selector sent to instance 0x600000b80eb0\n\n(\n\t0   CoreFoundation   ...

解决方法:
参考github

$ cd /usr/local/lib/node_modules/appium/node_modules/appium-xcuitest-driver
sudo rm -fr WebDriverAgent
#或者直接下载zip,然后解压
git clone https://github.com/appium/WebDriverAgent.git

更新WebDriverAgent的代码之后按照2.6.3.2 重新调试

  • 遇到的问题2:
  =================================== FAILURES   ===================================
  _____________ TestIOSSelectors.test_should_find_elements_by_xpath   ______________
  
  self = 
  driver = 
  
    def test_should_find_elements_by_xpath(self, driver):
        action_bar_container_elements = driver.find_elements_by_xpath('//XCUIElementTypeWindow//XCUIElementTypeButton')
         assert 7 == len(action_bar_container_elements)
  E       assert 7 == 8
  E        +  where 8 = len([, ...])
  
  test/test_ios_selectors.py:52: AssertionError
  ===================== 1 failed, 4 passed in 150.54 seconds    =====================

解决:
修改test_ios_selectors.pytest_should_find_elements_by_xpath 方法,将assert 7 == len(action_bar_container_elements)换成assert 8 == len(action_bar_container_elements)

2.6.4 用ios真机测试

2.6.4.1 获取手机的udid
将手机通过usb连上电脑,然后打开itunes,然后选中链接的iPhone,点击一下序列号,然后会弹出 udid 。

使用mitmproxy + appium + python 全自动抓取公众号文章_第7张图片
或者执行下面命令获取

echo $(idevice_id -l | head -n1)

2.6.4.2 调试WebDriverAgent

真机的调试需要开发者账号和证书,可以参考Appium官网配置说明和苹果开发者账号说明(不上传App Store不需要交钱)

然后分别为WebDriverAgentLib、WebDriverAgentRunner和IntegrationApp在Signing & Cababilites设置开发者账号和证书

使用mitmproxy + appium + python 全自动抓取公众号文章_第8张图片

WebDriverAgentRunner另外还需要修改Product Bundle Identifier
Build Settings选项卡,将Product Bundle Identifier的值com.facebook.WebDriverAgentRunner更改成Xcode能接受的值就行,Info选项卡中也要保持一致。

使用mitmproxy + appium + python 全自动抓取公众号文章_第9张图片

然后再设置开发者账号和证书

使用mitmproxy + appium + python 全自动抓取公众号文章_第10张图片

IntegrationApp的需要配置的地方和WebDriverAgentRunner一样,这里不再介绍。
分别编译WebDriverAgentLib和WebDriverAgentRunner不报错,然后试着安装IntegrationApp看是否能够安装和运行。

这时候应该会报一个错

Install claimed to have succeeded, but application could not be found on device. bundleId = com.eyison.wda.integrationApp

需要在手机上信任证书:

设置>通用>描述文件与设备管理

再次执行应该可以安装并启动IntegrationApp。

$ which appium
/usr/local/bin/appium
$ ls -l /usr/local/bin/appium
lrwxr-xr-x  1 eyison  admin  44  7 19 01:34 /usr/local/bin/appium -> ../lib/node_modules/appium/build/lib/main.js
$ cd /usr/local/lib/node_modules/appium/node_modules/appium-xcuitest-driver/WebDriverAgent
$ xcodebuild -project WebDriverAgent.xcodeproj -scheme WebDriverAgentRunner -destination 'id={udid}' test

如果你看到下面这个就说明WebDriverAgent已经启动成功了,在手机上也同时多了一个WebDriverAgent的app

Test Case '-[UITestingUITests testRunner]' started.
    t =     0.00s Start Test at 2019-07-30 23:12:25.997
    t =     0.00s Set Up
2019-07-30 23:12:26.043077+0800 WebDriverAgentRunner-Runner[1710:445441] Built at July  30 2019 22:46:51
2019-07-30 23:12:26.057947+0800 WebDriverAgentRunner-Runner[1710:445441] ServerURLHere->http://172.18.32.226:8100<-ServerURLHere
2019-07-30 23:12:26.058656+0800 WebDriverAgentRunner-Runner[1710:445615] Using singleton test manager

执行以下命令,将 iOS 设备上 WebDriverAgentRunner 监听的 8100 端口映射到 macOS 本地的 8100 端口

iproxy 8100 8100  {udid}

接下来验证WebDriverAgent Server的状态

$ curl 'http://localhost:8100/status'
{
  "value" : {
    "state" : "success",
    "os" : {
      "name" : "iOS",
      "version" : "12.4",
      "sdkVersion" : "13.0"
    },
    "ios" : {
      "simulatorVersion" : "12.4",
      "ip" : "172.18.32.226"
    },
    "build" : {
      "time" : "July  30 2019 22:46:52",  
      "productBundleIdentifier" : "com.facebook.WebDriverAgentRunner"
    }
  },
  "sessionId" : "99D81C1E-F9A8-4126-94CE-0A9E768892A2",
  "status" : 0
}

不通过代理直接请求curl 'http://172.18.32.226:8100/status'一直是超时,不知道什么原因。

官网上测试代码的app包一直没在我的iphone8 plus上安装成功,最后放弃了,感觉掉坑里了,不应该在这上面浪费时间的,自己的包就没有问题,而且用脚本直接调用WDA的api也是没有问题的。报错大致有下面这些,最后也没有细究就放弃了
问题1:

WebDriverAgentRunner-Runner[1747:453117] [User Defaults] Couldn't write value for key KeyboardAutocorrection in CFPrefsPlistSource<0x2829c3780> (Domain: com.apple.Preferences, User: kCFPreferencesCurrentUser, ByHost: No, Container: (null), Contents Need Refresh: No): setting preferences outside an application's container requires user-preference-write or file-write-data sandbox access

问题2:

Error: Could not install app: 'Command 'ios-deploy --id exited with code 253'

问题3:

ios-deploy[27399:2413371] [ !! ] Error 0xe8008014: The executable contains an invalid signature. AMDeviceSecureInstallApplication(0, device, url, options, install_callback, 0)
2.7 微信公众号全自动化抓取

为了调试方便可以安装一个桌面版的Appium,官网下载最新版安装即可。
记得配置WebDriverAgent的签名等,目录在/Applications/Appium.app/Contents/Resources/app/node_modules/appium/node_modules/appium-xcuitest-driver/WebDriverAgent,配置方式同上面ios真机测试介绍的步骤。
然后启动appium服务
使用mitmproxy + appium + python 全自动抓取公众号文章_第11张图片

然后新建会话并填写配置,填完之后点击启动会话按钮来启动微信

使用mitmproxy + appium + python 全自动抓取公众号文章_第12张图片

{
  "platformName": "iOS",
  "platformVersion": "12.4",
  "deviceName": "iPhone",
  "bundleId": "com.tencent.xin",
  "udid": "",
  "xcodeSigningId": "iPhone Developer",
  "xcodeOrgId": ""
}

根据需求添加必要的参数,常用参数如下:

  • automationName:
    “Appium”, – 可选,搜索引擎,appium(默认)还是Selendroid
  • platformName:
    “iOS”, – 必填,应用平台,iOS, Android, or FirefoxOS
  • platformVersion:
    “10.3”, – 必填,测试的系统版本,设置两位就可以了
  • deviceName:
    “iPhone”, – 必填,使用的手机或模拟器类型,iPhone Simulator, Android Emulator, Galaxy S4
  • app:
    “com.apple.calculator”, – Android可选,iOS必填,应用的绝对路径,与browserName属性冲突
  • browserName:
    “Chromium”, – 做自动化时使用的浏览器名字, 与app 冲突
  • bundleId:
    “io.appium.TestApp”, – iOS未填app参数必填,用于在真实设备中启动测试,使用其他需要 bundle ID 的关键字启动测试。
  • udid:
    " ", – 多客户端链接多台手机时必填,连接真机的唯一设备号,iOS通过iTunes拷贝过来,IOS真机测试必填
  • noReset:
    “true” – 在当前 session 下不会重置应用的状态, 是否清除应用缓存。默认值为false,
  • fullReset:
    “false” – (iOS)删除所有的模拟器文件夹。(Android) 要清除 app 里的数据,请将应用卸载才能达到重置应用的效果。在 Android, 在 session 完成之后也会将应用卸载掉。默认值为false
  • xcodeOrgId:
    “123ADE4Y56”, – 十位字符的组织ID是苹果开发证书的组织单位,appium可以通过十位组织单位ID找到相应的组织,IOS真机测试必填(注意: 连接真机时,测试app的打包签名证书必须要与xcodeOrgId里的一致,否则会报证书错误,错误代码是65)
  • xcodeSigningId:
    “iPhone Developer”, – iOS真机测试必填,这个参数是固定的
  • wdaLocalPort:
    “8100” – 默认手机连接MAC本使用的端口,默认是8100,非必填
  • unicodeKeyboard:
    “true” – 使用 Unicode字符,输入中文必须参数
  • resetKeyboard"
    “true” – 重置键盘,输入中文必须参数

会话连接成功后就会展示 The Inspector,它是应用程序状态的可视化表示。

使用mitmproxy + appium + python 全自动抓取公众号文章_第13张图片

编写脚本,代码太长,贴出部分,回头上传到github分享出来

# -*- coding: utf-8 -*-
# @Time    : 2019/8/5 
# @Author  : zl  
# @Email   : [email protected]

from threading import Thread
from appium import webdriver
from appium.webdriver.common.touch_action import TouchAction

class AppiumWechatSpider(Thread):
    __bundle_id = 'com.tencent.xin'

    __IOS_BASE_CAPS = {
        'automationName': 'XCUITest',
        'platformName': 'iOS',
        'platformVersion': '12.4',
        'deviceName': 'iPhone',
        "bundleId": __bundle_id,
        'udid': '',
        'xcodeSigningId': 'iPhone Developer',
        'xcodeOrgId': '',
        'showIOSLog': False,
        'unicodeKeyboard': True,
        'resetKeyboard': True,
        'newCommandTimeout': 3000,
        'sendKeyStrategy': 'setValue'
    }
    __EXECUTOR = 'http://127.0.0.1:4723/wd/hub'

    def __init__(self):
        super().__init__()
        self._running = False
        self.name = 'AppiumWechatSpider'
        self.driver = webdriver.Remote(
            command_executor=self.__EXECUTOR,
            desired_capabilities=self.__IOS_BASE_CAPS
        )
        self.forward_step = 0
        self.focused_acount = 0

    def run(self):
        if self._running:
            return
        self._running = True
        print('微信已经启动')
        self.driver.find_element_by_xpath('//XCUIElementTypeSearchField[@name="搜索"]').click()
        print('点击搜索框')
        self.driver.find_element_by_xpath('//XCUIElementTypeButton[@name="公众号"]').click()
        print('点击公众号按钮')
        input = self.driver.find_element_by_xpath('(//XCUIElementTypeSearchField[@name="搜索公众号"])[1]')
        input.click()
        input.send_keys(wechat_name)

    ...
 

然后配置手机连上代理让脚本自动翻页公众号的文章列表即可抓取
官方参数介绍:
Appium Desired Capabilities
AppiumXcuitestDriver Desired Capabilities

【转载请注明出处】:https://blog.csdn.net/huahao1989/article/details/106180223

你可能感兴趣的:(使用mitmproxy + appium + python 全自动抓取公众号文章)