mitmdump 实时抓包处理

mitmdump 是 mitmproxy 的命令行接口,可以对接 Python 脚本处理请求和响应,这是比 Fiddler , Charles 等工具更加方便的地方,有了它,我们不用再手动抓取和分析HTTP 请求和响应,只要写好请求和响应的处理逻辑就好了。

正是由于 mitmdump 可以对接 Python 脚本,因此我们在 Python 脚本中获取请求和响应内容时,就可以顺便添加一些解析,存储数据的逻辑,这样就实现了数据的抓取和实时处理

实例引入

使用命令启动 mitmdump:    mitmdump -s script.py

这里使用 -s 参数指定本地脚本 script.py 为处理脚本,用来处理抓取的数据,需要将其放在当前命令的执行目录下

我们可以在 script.py 脚本里写入如下内容

def request(flow):
    flow.request.headers['User-Agent'] = 'MitmProxy'
    print(flow.request.headers)

其中定义了一个 request 方法,参数为 flow ,这是一个 HTTPFlow 对象,调用其 request 属性即可获取当前请求对象的请求头 User-Agent 修改成 MitmProxy , 然后打印出所有请求头

运行启动命令后,在手机端访问 http://www,httpbin.org/get   同时电脑端的控制台输出

手机端显示的

控制台输出的结果

日志输出

mitmdump 提供了专门的日志日志输出功能,可以设定以不同的颜色输出不同级别的结果。 把 script.py 脚本内容修改成

from mitmproxy import ctx
def request(flow):
    flow.request.headers['User-Agent'] = 'MitmProxy'
    ctx.log.info(str(flow.request.headers))
    ctx.log.warn(str(flow.request.headers))
    ctx.log.error(str(flow.request.headers))

这里调用了 ctx 模块,它有一个名为 log 的功能,调用不同的输出方法可以输出不同颜色的结果,以便我们方便直观的调试

请求

我们来看看 mitmdump 还有哪些使用的功能

from mitmproxy import ctx
# mitmdump 常用的功能
def request(flow):
    request = flow.request
    info = ctx.log.info
    info(request.headers)
    info(request.url)
    info(str(request.headers))
    info(str(request.cookies))
    info(request.host)
    info(request.method)
    info(request.port)
    info(request.scheme)

这里的 request 方法是 mitmdump 针对请求提供的处理接口。 将 script.py 脚本修改为如上内容,然后手机打开 http://www.httpbin.org/get , 即可看到电脑端控制台输出了一些列的请求。这里我们找到第一个请求,控制台打印出了该请求的一些常见属性,如请求 URL, 请求头,请求Cookie ,请求 Host ,请求方法,请求端口,请求协议等

我们可以根据需要修该里面的参数,例如修改 URL 为 www.baidu.com

def request(flow):
    url = 'https://www.baidu.com'
    flow.request.url = url

浏览器上方的地址栏呈现的网址还是原来的,页面却变成了百度首页。我们简单的脚本就成功修改了目标网站,意味着这种方式修改和伪造请求变得轻而易举,这也是中间攻击

注意: 这里提醒我们 url 正确并不意味着网站也正确,我们要提高防范意识

响应

对于爬虫来说,更加关心的其实是响应内容,响应体才是要爬取的结果。和请求一样,mitmdump 正对响应也提供了对应的处理接口, 就是 response 方法

# 响应
def response(flow):
    response = flow.response
    info = ctx.log.info
    info(str(response.status_code))
    info(str(response.headers))
    info(str(response.cookies))
    info(str(response.text))

将 script.py 改成如上代码,然后手机访问 https://www.httpbin.org/get 电脑端控制台就输出了如上的内容有 响应状态码,响应头 ,响应 cookie 和响应体几个属性,其中最后一个是网页的源代码

实战准备

我们将 APP中的接口数据爬取下来存储到 文本文件中

手机上安装APP:https://app5.scrape.center/

抓取分析

首先获取一下当前页面的 URL 和返回内容,编写一个脚本, 名叫 spider.py

def response(flow):
    print(flow.request.url)
    print(flow.response.text)

这里只是打印出了请求 URL 和响应体这两个最关键的部分,然后启动

mitmdump -s spider.py

在手机上打开下载好的 app5 ,便可以看到电脑端控制台输出了相应的内容,接着不断下拉,可以看到手机屏幕上的数据一页一页的加载,电脑的控制台输出了类似 JSON 数据的结果

选取其中一个 URL 观察一下, 具体为: 

https://app5.scrape.center/api/movie/?offset=30&limit=10&token=YjczZWE0NDEzOGIxOTg5YTU3MDU0NGNkYjU0NzkyZmIwMzU1Mjk2MiwxNzIzNjI0OTA1%0A

可以看到出了 offset limit 参数,里面还有一个 token ,我们把结果中响应体复制下来,并格式化处理  Json Beautifier - Json Formatter | Json Viewer | Json Editor 可以搜索 json beautifier 来格式化

"count": 103,
  "results": [
    {
      "id": 30,
      "name": "上帝之城",
      "alias": "Cidade de Deus",
      "cover": "https://p1.meituan.net/movie/b553d13f30100db731ab6cf45668e52d94703.jpg@464w_644h_1e_1c",
      "categories": [
        "剧情",
        "犯罪"
      ],
      "published_at": null,
      "minute": 130,
      "score": 8.8,
      "regions": [
        "巴西",
        "法国"
      ],
      "drama": "巴西里约热内卢的贫民窟,这里是“上帝之城”,更是魔鬼也会叹息着转身的地方。阿炮(亚历山大·罗德里格斯 饰)带着我们到了这里,他见证了这里二十多年来被残暴、贪婪、复仇、野心、背叛、掠夺所裹挟的混乱生活 以及最终导致的一场灾难性的黑帮争斗。虽然从小就要辗转于匪徒间求生存,但胆小怕事的性格与自我保护的本能却使他一直能平安度日。60年代初,阿毛、阿夹和阿呆是这里的“少年三侠”,在抢劫完旅馆之后,他们三人分道扬镳,阿夹重回上帝的怀抱,而阿呆和阿毛纷纷付出了生命的代价。70年,当年“少年三

通过对比可以发现这里的内容和 app5 里的内容是一样的,所以我们成功截获了响应体

那么这里为什么不能像前面那样直接用 Python 请求爬取数据? 因为这次 App 的接口带有 token 的加密参数,仅凭抓包是没法知道它是如何生成的,而通过 Python  则需要模拟 token 的生成逻辑

这里我们已经直接通过 mitmdump 抓取结果, 相当于是请求 App 构造的,我们直接拿到了响应结果,不需要再去构造请求了

数据抓取

现在我们稍微完善一下 spider.py 脚本,增加一些过滤 URL 和处理响应结果的逻辑

import json 
from mitmproxy import ctx

def response(flow):
    url = 'https://app5.scrape.center/api/movie/'
    if flow.request.url.startsswith(url):
        text = flow.response.text
        if not text:
            return
        data = json.loads(text)
        items = data.get('results')
        for item in items:
            ctx.log.info(str(item))

之后重新打开 app5 ,并在电脑端控制台观察输出结果

可以看到输出了每部电影的数据,数据以 JSON 形式呈现

提取保存

现在再修改一下 spider.py 脚本,将返回的结果保存下来,保存为文本文件即可

import json
from mitmproxy import ctx
import os

OUTPUT_FOLDER = 'movies'
os.path.exists(OUTPUT_FOLDER) or os.makedirs((OUTPUT_FOLDER))

def response(flow):
    url = 'https://app5.scrape.center/api/movie/'
    if flow.request.url.startswith(url):
        text = flow.response.text
        if not text:
            return
        data = json.loads(text)
        items = data.get('results')
        for item in items:
            ctx.log.info(str(item))
            with open(f'{OUTPUT_FOLDER}/{item["name"]}.json', 'w', encoding='utf-8') as f:
                f.write(json.dumps(item, ensure_ascii=False, indent=2))

然后重新打开 app5 , 滑动一下屏幕,这时候观察 movies 文件夹,会发现生成了一些 JSON 文件,这些文件以电影名称命名

打开任意一个json 文件,可以看到都实时保存了下来

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值