【轉載請注明出處】: 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
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