Appium + mitmproxy 全自动化抓取APP 数据

 

 

背景

公司新接到一个某某公司的一个项目需求,其中有一个子项是抓取诸如今日头条、网易新闻、腾讯新闻等新闻类 APP 的新闻,远端根据一个关键词或者一个主账号名称查找获取关于该关键词的所有新闻或主账号下的所有文章,通过简单的抓包分析,发现只有少数 APP 网络请求参数未做签名处理,像这类的能直接分析 url 和 param,利用 python 全自动化获取数据,但是大部分比如网易新闻这类 APP 安全级别较高,参数做了加密或者签名校验,服务端也有同一签名的请求访问次数限制,所以在这样的情况下想要直接获取通过外部调用获取数据几乎变得不可能。

分析

在以上的背景之下,简单分析和调研之后,觉得有以下办法可以获取到那些请求加密的 APP 的数据,如下:

  • 逆向分析该 APP,揪出加密方法及对应的逻辑,第三方使用同样的逻辑加密请求参数获取数据;
  • 寻找该新闻 APP 在 WEB 端的接口,同样也能获取到数据;
  • 对 APP 使用网络代理,使用手机获取新闻,使用中间人攻击(MITM)获取数据 并做对应处理。

这三个方案中,第一种,难度最大,因为了解所有明白,以我的逆向水平暂时达不到,虽然可行,但暂时不考虑;第二种,经验证,很多在 APP 端有的接口在 WEB 端没有,也放弃;第三种,面临几个问题,因为整个过程要全自动化,所以这个操作使用获取新闻的过程要自动,手机获取到新闻后数据抓取的过程要自动,这就意味着不能使用 Wireshark、Charles、Fiddler 等抓包工具人为干预,要解决这两个问题,即要解决这两个问题:

  • 使用脚本自动化 UI 操作
  • 代理软件能与脚本交互

为解决第一个问题,可以使用AppiumGithub主页

Q:Appium 是什么?

A:Appium 是一个自动化测试开源工具,支持 iOS 平台和 Android 平台上的原生应用,web 应用和混合应用。

  • “移动原生应用”是指那些用 iOS 或者 Android SDK 写的应用。

  • “移动 web 应用”是指使用移动浏览器访问的应用(Appium 支持 iOS 上的 Safari 和 Android 上的 Chrome)。

  • “混合应用”是指原生代码封装网页视图——原生代码和 web 内容交互。比如,我们在微信里可以查看网页,可以通过网页应用买电影票等。

Appium 适配了与诸如 JAVA、Python、Javascript、Ruby 等众多语言的交互,我选择 Python,即:Appium + python

为解决第二个问题,找到了两个解决方案,第一个是 mitmproxyGithub主页,第二个是AnyProxyGithub主页,这两个都是开放式的HTTP/HTTPS代理服务,后者是阿里巴巴基于 Node.js 开发的一款开源代理服务,前者是一款免费开源的可交互的HTTP/HTTPS代理服务,可与 Python 交互,且功能更强大,我选择了后者,即:mitmproxy + python

编码

方案已经确定了,就开始看文档进行编码工作,过程与细节就不写了,直接上成果。

自动操作 UI 部分

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
拷贝
#!/usr/bin/python3

from appium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from appium.webdriver.common.touch_action import TouchAction
import time
import sys
import getopt
import json
import os
import selenium
import argparse

platformName = 'iOS'
deviceName = 'iPhone 6s'
bundleId = 'com.netease.news'
udid = 'your_uuid'
automationName = 'XCUITest'
xcodeOrgId = 'your_ xcodeOrgId'
xcodeSigningId = 'your_certificate_name'
driverServer = 'http://127.0.0.1:4723/wd/hub'

class Input:
    type = ''
    keyWord = ''


class NeteaseNewsSpider():
    def __init__(self):
        self.desired_caps = {
            'platformName': platformName,
            'deviceName': deviceName,
            'bundleId': bundleId,
            'udid': udid,
            'automationName': automationName,
            'clearSystemFiles': True,
        }
        self.driver = webdriver.Remote(driverServer, self.desired_caps)

    def tearDown(self):
        self.driver.quit()

    def performActionForKeyword(self, keyWord):

        driver = self.driver
        wait = WebDriverWait(driver, 300)

        time.sleep(5)

        try:
            el1 = wait.until(EC.presence_of_element_located(
                (By.XPATH, '//XCUIElementTypeApplication[@name=\"网易新闻\"]/XCUIElementTypeWindow[1]/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther[1]/XCUIElementTypeButton[1]')))
        except selenium.common.exceptions.NoSuchElementException:
            pass
        el1.click()

        time.sleep(0.5)

        TouchAction(self.driver).tap(x=206, y=44).perform()

        print('输入目标关键词:%s' % keyWord)
        el3 = wait.until(EC.presence_of_element_located(
            (By.XPATH, '//XCUIElementTypeApplication[@name=\"网易新闻\"]/XCUIElementTypeWindow[1]/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther[1]/XCUIElementTypeOther/XCUIElementTypeTextField')))
        el3.send_keys(keyWord)

        print('点击搜索按钮')
        el3.send_keys('\n')

    def findForKeyWord(self, keyWord):
        self.performActionForKeyword(keyWord)

        time.sleep(0.5)
        print('动作结束')
        os.system('say 动作结束')

    def findForUser(self, keyWord):
        driver = self.driver

        self.performActionForKeyword(keyWord)

        time.sleep(0.5)

        # 点击用户
        print('点击用户')
        el1 = driver.find_element_by_xpath(
            "//XCUIElementTypeOther[@name=\"i\"]/XCUIElementTypeOther[1]/XCUIElementTypeOther[4]")
        el1.click()

        time.sleep(0.5)

        # 点击用户第一个
        if self.isExistElement(By.XPATH, '//XCUIElementTypeOther[@name=\"i\"]/XCUIElementTypeOther[2]/XCUIElementTypeOther[1]/XCUIElementTypeOther[1]/XCUIElementTypeImage'):
            print('点击用户列表第一个')
        
  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值