使用Appium+python爬取手機App


一、搭建運行環境

1、jdk安裝 8版本

環境配置

JDK官網下載:http://www.oracle.com/technetwork/java/javase/downloads/index.html

安裝完成后配置環境變量:

打開:我的電腦->屬性->高級系統設置->環境變量

1、新建JAVA_HOME:C:\Program Files\Java\jdk1.8.0_161(jdk目錄路徑)

2、找到Path,沒有的話新建Path:%JAVA_HOME%\bin;%PATH%

     注意:如果是Windows10系統,要寫jdk和jre的絕對路徑

    Path:C:\Program Files\Java\jre1.8.0_161\bin;C:\Program Files\Java\jdk1.8.0_161\bin

3、新建CLASSPATH:.;%JAVA_HOME%\lib;%JAVA_HOME%\lib\tools.jar

配置完成。

測試:

cmd運行java -version:

cmd運行javac:

2、sdk安裝

sdk下載地址:http://tools.android-studio.org/index.php/sdk 

下載並安裝Android SDK

首先,下載Android SDK Tools。下載地址:http://www.androiddevtools.cn/。

打開網址(http://www.androiddevtools.cn/),找到SDK Tools,選擇一個最新的版本就行了。注意,這里有exe和zip兩種文件可供下載,exe的就是個安裝程序,下載下來需要自己雙擊安裝。這里建議下載zip壓縮包,下載后,直接解壓縮到你想要安裝Android的路徑就行了。

解壓后的文件目錄如下:

然后就雙擊“SDK Manager.exe”,啟動SDK Manager,如圖所示:

在這里我只說幾個必須要安裝的,如上圖所示的,Tools文件夾里面的Android SDK Tools(這個我們在之前的一步已經下載好了的,一般不會讓你再安裝了,不過有可能會讓你更新),然后就是Android SDK Platform-tools和Android SDKBuild-tools,注意只需要下載最新的版本就行了。

然后就是API的選擇了。我們可以看到這里提供了很多很多從Android 2.1到Android 8.x的很多版本的API,那么怎么選擇呢。這里我建議,新手的話,選擇一個最新的版本就好了,因為Android是向下兼容的。其他的以后你要用到了在下載就行了。這里我下載了Android 8.1.0(API27)。這里需要說明的是,如果你以后不打算用模擬器調試,而是一直用真機來調試的話,那么就可以不用裝“system images“了。

最后就是extras文件夾中的東西了,如下圖所示,

接下來就可以進行安裝了。要注意,由於這些東西都是在google 的服務器上下載的。由於俺們天朝有牆,所以可能會出現連接不上的情況,如下圖:

這種時候,我們可以通過有Android SDK的國內鏡像服務器來下載安裝,這里推薦幾個:

1、中科院開源協會鏡像站地址:

IPV4/IPV6 : http://mirrors.opencas.ac.cn 端口:80

2、北京化工大學鏡像服務器地址:

IPv4: http://ubuntu.buct.edu.cn/  端口:80

IPv4: http://ubuntu.buct.cn/  端口:80

IPv6: http://ubuntu.buct6.edu.cn/  端口:80

3、大連東軟信息學院鏡像服務器地址:

http://mirrors.neusoft.edu.cn  端口:80

隨便選擇一個就行啦。這里我選擇的是第三個站點,即大連東軟的鏡像,使用方法如下:

首先,點擊菜單中的“Tools”,然后選擇下拉中的“Options…”

然后在彈出的對話框中,填寫HTTP Proxy Server為mirrors.neusoft.edu.cn(鏡像服務器的地址,注意前面不要加http),然后填寫HTTP Proxy Port為80 (端口號)。最后在勾選下面的『Forcehttps://... sources to be fetched using http://...』復選框,如下圖所示,

接着點擊close,關閉對話框,再重新啟動SDK Manager就行啦。

經過漫長的下載安裝過程后,我們可以看到,之前選中安裝的項目后面的狀態都由之前的“Not installed”變為了如今的“Installed”,這就表示我們已經安裝成功了!

若按以上操作依然無法下載sdk,可以直接下載我打包好的:百度網盤(鏈接:https://pan.baidu.com/s/1Pv4TjEGJtwtU_kjDCv5IuA 提取碼:2j5q),按照以下步驟配置好環境變量即可

配置Android SDK環境變量(這里用的win10)

配置Android SDK環境變量主要是為Android命令行工具提供方便,可以直接在終端使用部分shell命令。Android SDK附帶了一系列命令行工具,位於Android SDK安裝目錄的tools文件夾以及platform-tools下。這里需要把”\platform-tools“和”\tools”路徑追加到系統環境變量Path中,具體如下:

首先,新建一個系統環境變量,變量名為ANDROID_SDK_HOME,變量值為你的SDK安裝路徑,這里我的安裝路徑為G:\AndroidDevTools\android-sdk-windows,如圖所示:(變量值后不加分號“;”)

 然后就是在系統的Path變量后,追加;% ANDROID_SDK_HOME%\platform-tools;% ANDROID_SDK_HOME%\tools,如圖所示:(這里每個變量值后不需要加分號“;”系統會自動分隔每個變量值)

最后,測試一下是否成功:開始-運行-輸入cmd-在終端輸入

命令:android -h

顯示以下視圖則說明tools配置成功;

再輸入命令:adb

顯示以下視圖則說明platform-tools配置成功;

如圖配置成功!!!!!

二、用模擬器的情況下(不用請忽略)

SDK中的adb和模擬器中的adb版本同步

1、復制SDK目錄下platform-tools文件夾下
    adb.exe
    AdbWinApi.dll
    AdbWinUsbApi.dll
2、替換夜神模擬器中以上的3個同名文件
3、復制夜神模擬器中的adb.exe 名字改為nox_adb.exe 替換原有的nox_adb.exe
4、重啟模擬器完成adb升級

三、安裝Appium服務端和客戶端

服務端導官網下載即可:http://appium.io/

1、啟動界面直接點擊啟動即可

2、通過appium內置工具定位app標簽

3、填入設備信息

信息詳解:

{
  "platformName": "Android",      # 手機系統
  "platformVersion": "8.0.0",     # 版本號
  "deviceName": "28fc7344",       # 服務號   命令行adb devices 查看
  "appPackage": "me.yidui",       # app唯一標識,對哪個app進行自動化   E:\android-sdk\build-tools\29.0.2\aapt.exe dum badging C:\Users\v_mcsong\Desktop\yidui.apk
  "appActivity": "com.yidui.ui.login.SplashActivity",     # 同上 在命令行窗口查看
  "noReset": true                        # 不會每次都重啟app  保存session
} 

appPackage

appActivity

下載python支持的appium客戶端

安裝pip install Appium-Python-Client

滑動手機屏幕(模擬人滑動)

import time
from appium import webdriver
from selenium.webdriver.support.ui import WebDriverWait  # 等待一個控件出現
# 安裝pip install Appium-Python-Client

# 獲取屏幕的長度和寬度
def get_size():
    x = driver.get_window_size()["width"]
    y = driver.get_window_size()["height"]
    return (x,y)


# 會話配置
desired_caps = {
        "platformName":"Android",
        "platformVersion":"8.0.0",
        "deviceName":"28fc7344",
        "appPackage":"me.yidui",
        "appActivity":"com.yidui.ui.login.SplashActivity",
        "noReset": True
    }

driver = webdriver.Remote("http://127.0.0.1:4723/wd/hub",desired_caps)
print(driver)
time.sleep(3)
l = get_size()    # 獲取屏幕也長度和寬度
x1 = int(l[0]*0.5)
y1 = int(l[1]*0.75)
y2 = int(l[1]*0.25)
while  True:
    # 鼠標從什么地方開始到什么地方結束
    driver.swipe(x1,y1,x1,y2)

四、配置mitmproxy用於截取響應數據

安裝pip install mitmproxy

啟動 mitmproxy

mitmweb    # mitmproxy有三種啟動方式,此處使用的命令可以提供一個web交互界面

mitmproxy有三種啟動命令:

(1) mitmweb
-- 提供一個web界面;
-- 代理端口:綁定了 *:8080作為代理端口;
-- 交互界面地址:localhost:8081;
(2) mitmproxy
-- 提供命令行界面;
-- 可以通過命令過濾請求;
(3) mitmdump
-- 【TODO】

安裝CA證書

第一步,將電腦和手機連到同一個 WiFi 中;

第二步,獲取本機的內網IP地址;

得到電腦本機的內網IP地址為 192.168.1.102。

第三步,給手機WiFi配置代理

  • 服務器地址為電腦內網IP地址,端口為8080

第四步,安裝證書

使用手機瀏覽器訪問 mitm.it,得到下圖。

 我的手機為iPhone,點擊 Apple 后得到下圖。

 

點擊允許,開始安裝。

安裝完成后,得到已驗證的提示。

開啟證書

手機依次點擊:設置 -> 通用 -> 關於本機 -> 證書信任設置,開啟 mitmproxy 證書。

配置完成

此時,mitmweb 頁面出現下圖內容,紅框中的為 mitmproxy 抓取的手機的請求。

安卓手機如果出現無法現在證書的情況建議更換瀏覽器進行下載,或在電腦下載好導入手機:

在mitmproxy軟件證書配置中,其中手機的證書安裝過程一般為:

“將mitmproxy-ca-cert.pem”文件發送到手機上,點擊證書文件,便會出現一個安裝窗口。”

但是,

部分Android手機並不識別pem文件,如華為P10+。

解決方法為:

1.打開手機“設置”;

2.選擇“安全和隱私”;

3.點擊“更多安全設置”,找到“從SD卡安裝”;

4.搜索該證書文件,點擊安裝。

PC端安裝mitmproxy,生成證書,並在手機端安裝android證書,然后設置手機ip代理,仍然報錯,錯誤如下圖

解決方法

執行如下命令即可:mitmproxy -s tls_passthrough.py

passthrough.py下載地址:https://github.com/mitmproxy/mitmproxy/blob/master/examples/complex/tls_passthrough.py

執行上述命令之后即可正常使用:

編寫python腳本用於截獲響應數據

import json
import time
from db import mdb,conn

def write_mongo(data):
    # 將指紋存儲到redis數據庫
    ex = conn.sadd('project_yidui', data["aid"])
    # ex == 1 :字符串插入成功   ex == 0 插入的字符串重復了 增量式爬取
    if ex == 1:
        print("正在下載:{}".format(data["member_id"]))
        mdb["yiduiInfo"].update({"aid": data["aid"]}, {"$set": data}, True)
    else:
        print("數據存在暫無更新!!!")

def response(flow):
    # http://api.douguo.net/recipe/v2/search 這個url是通過我們用抓包工具分析出來的獲取響應數據的接口
    if "https://api.520yidui.com/v2/members/info.json?target_id=" in flow.request.url:
        # https://api.520yidui.com/v2/members/list?page=    進入用戶主頁獲取更多信息
        # with open("test.txt","w") as f:
        #     f.write(flow.response.text)
        print(flow.response.text)  
        info = json.loads(flow.response.text)
        try:
            data = {
                "aid":info.get("id"),                                       # 用戶主頁id
                "member_id":info.get("member_id"),                          # 伊對id
                "avatar_url":info.get("avatar_url"),                        # 頭像url
                "sex":info.get("sex"),                                      # 性別
                "location":info.get("location"),                            # 地區
                "nickname":info.get("nickname"),                            # 昵稱
                "age":info.get("age"),                                      # 年齡
                "height":info.get("height"),                                # 身高
                "vip":info.get("vip"),                                      # 是否是vip用戶
                "monologue":info.get("monologue"),                          # 交友心聲
                "education":info["detail"].get("education"),                # 學歷
                "profession":info["detail"].get("profession"),              # 職業
                "marriage":info["detail"].get("marriage"),                  # 婚姻狀況
                "salary":info["detail"].get("salary"),                      # 月收入
                "living_condition":info["detail"].get("living_condition"),  # 住房
                # 征友條件
                "Friend_location":info["relationship_proposal"].get("location"),   # 對方地區
                "Friend_age":info["relationship_proposal"].get("age"),       # 對方年齡
                "Friend_height":info["relationship_proposal"].get("height"), # 對方身高
                "Friend_salary":info["relationship_proposal"].get("salary"), # 對方薪資
                "Friend_education":info["relationship_proposal"].get("education"),  # 對方學歷
                "Friend_content":info["relationship_proposal"].get("content"),       # 交友條件
                "ds": int(time.strftime("%Y%m%d", time.localtime(time.time()))),  # 日期時間戳 例如 20190101
                "insert_time": int(time.time() * 1000),  # 插入日期時間戳
            }
            print(data)
            write_mongo(data)
        except Exception as e:
            ...
#         """
#         {
#         'id': 'c723c05c8f20455254710db3a5bd6df5',
#          'member_id': 57539327,
#          'avatar_url': 'https://img.520yidui.com/uploads/member_avatar/avatar/57539327/fff0214a2e7fa83fa229ca65c805e0af.jpg@!normal',
#          'sex': 1,
#          'location': '廣東',
#          'nickname': '許你一世對我好',
#          'age': 21,
#          'height': 161,
#          'vip': False,
#          'monologue': '說話溫和 做人做事有風度,但人得好',
#          'education': '高中及以下',
#          'profession': '自由職業',
#          'marriage': '未婚',
#          'salary': '4000-6000',
#          'living_condition': '其他',
#          'Friend_location': '不限',
#          'Friend_age': '26-27',
#          'Friend_height': '175-178',
#          'Friend_salary': '4000-6000',
#          'Friend_education': '大專',
#          'Friend_content': '我想找26-27歲的異性.'}
#         """

數據庫配置

from redis import Redis
from pymongo import MongoClient

# mongodb連接
my_client = MongoClient(host="127.0.0.1",port=27017)
mdb = my_client["project_yidui"]   # 指定連接的庫名
print("mongodb連接成功>>>:",mdb)

# redis連接
conn = Redis(host='127.0.0.1', port=6379)
print("redis連接成功>>>:",conn)

啟動命令 :mitmdump -s 腳本絕對路徑 -p 8889

滑動手機得到響應數據:

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM