使用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

滑动手机得到响应数据:

 

 

posted @ 2020-04-03 10:14  叫我大表哥  阅读(3066)  评论(0编辑  收藏  举报