【轉載請註明出處】:https://segmentfault.com/a/1190000022667615
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=
然後再執行測試腳本
2.6.2 用Android真機測試
2.6.2.1 連接手機
-
使用數據線通過USB接口將手機與電腦連接,在終端中執行如下命令:
adb devices
表示數據線已經連接成功,但是使用數據線有時候不是很方便,也不能準確測試耗電量,下面介紹無線連接方式
- 使用無線連接(在同一網段)
一般在設置-關於手機-狀態-IP地址
可以找到手機的IP,或者執行命令:
adb shell ip -f inet addr show wlan0

adb tcpip 5555
//多個設備的話需要指定具體的設備
//adb -s f489be9c tcpip 5555
adb connect 192.168.1.5:5555

這時候就可以拔掉數據線了。
注:要斷開連接,執行: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
2.6.3 用ios 模擬器測試
2.6.3.1 ios 模擬器基本命令
列出可用的設備、設備類型、運行時或設備對。
simctl list [-j | --json] [-v] [devices|devicetypes|runtimes|pairs] [<search term>|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
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 一致即可
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
- 遇到的問題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 = <test_ios_selectors.TestIOSSelectors object at 0x10ab56290>
driver = <appium.webdriver.webdriver.WebDriver (session="dddb8afc-6146-4c3a-8079-952eb333586c")>
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([<appium.webdriver.webelement.WebElement (session="dddb8afc-6146-4c3a-8079-952eb333586c", element="10000000-0000-0000-...ment.WebElement (session="dddb8afc-6146-4c3a-8079-952eb333586c", element="1B000000-0000-0000-AC7F-010000000000")>, ...])
test/test_ios_selectors.py:52: AssertionError
===================== 1 failed, 4 passed in 150.54 seconds =====================
解決:
修改test_ios_selectors.py
的test_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 。
或者執行下面命令獲取
echo $(idevice_id -l | head -n1)
2.6.4.2 調試WebDriverAgent
真機的調試需要開發者賬號和證書,可以參考Appium官網配置說明和蘋果開發者賬號說明(不上傳App Store不需要交錢)
然後分別為WebDriverAgentLib、WebDriverAgentRunner和IntegrationApp在Signing & Cababilites
設置開發者賬號和證書
WebDriverAgentRunner另外還需要修改Product Bundle Identifier
。
在Build Settings
選項卡,將Product Bundle Identifier
的值com.facebook.WebDriverAgentRunner
更改成Xcode能接受的值就行,Info
選項卡中也要保持一致。
然後再設置開發者賬號和證書
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服務
然後新建會話並填寫配置,填完之後點擊啟動會話
按鈕來啟動微信
{
"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,它是應用程序狀態的可視化表示。
編寫腳本,代碼太長,貼出部分,回頭上傳到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://segmentfault.com/a/1190000022667615