万字博文教你爬虫代理工具mitmproxy【详解篇】

每篇前言:


👇
☝️

一、简介和安装

mitmproxy是一个代理工具(软件安装或Python模块安装),实现代理请求(拦截请求或修改请求)。
在这里插入图片描述

Python爬虫用,以模块形式安装更适合我们【注意:python 版本>=3.6】:

pip install mitmproxy -i https://mirrors.aliyun.com/pypi/simple/

第一部分 - 介绍并下载安装完毕

(1)概念

Mitmproxy是一个免费的开源交互式的HTTPS代理。MITM即中间人攻击(Man-in-the-Middle Attack)。

(2)作用

  1. 代理的作用,转发请求,保障服务端与客户端的通信;
  2. 查看,记录,修改数据,引发服务端或客户端的特定行为。

在这里插入图片描述

(3)图解原理

在这里插入图片描述

(4)mitmproxy工具介绍

安装成功后在Python安装路径Script路径下可以找到 mitmdump.exe mitmproxy.exe mitmweb.exe 这三个可执行文件。
在这里插入图片描述

  • mitmproxy:命令行界面,允许交互式检查和修改http数据流。不支持windows;
  • mitmweb: Web界面,用户可以实时看到发生的请求,过滤请求,查看请求数据;
  • mitmdump: 一个命令行工具,没有界面,不能交互,但是可以通过启动参数并结合自定义脚本进行定制化功能的实现,咱就用这个。

这三个命令功能一致,且都可以加载自定义脚本,唯一的区别是交互界面的不同;mitmproxy,mitmweb主要用来做调试,部署项目时,使用mitmdump。

第二部分 - 配置并使用

(1)设置代理

PC端设置代理:

开启代理时需要把其他的代理都关掉!
在这里插入图片描述
开启代理:注意现在还没有安装证书,所以https的请求是无法获取的!
在这里插入图片描述

PC端安装证书:获取https请求
第一种获取证书的方式:
  1. 运行mitmweb工具:终端命令mitweb即可。
  2. 在代理状态下,访问mitm.it,PC端与移动端操作相同。
    在这里插入图片描述
第二种获取证书的方式:

还可以直接找到本地的证书,然后安装:
编写一个脚本,启动mitmproxy:

mitmdump -q  -p 8888 -s v1.py
#! python
# -*- coding: utf-8 -*-
# @Time    : 2024/10/10 66:66
# @Author  : GuHanZhe
# @File    : baidu_crawler.py
from mitmproxy import http
from mitmproxy.http import HTTPFlow


def request(flow: http.HTTPFlow):
    print("请求->", flow.request.path)


def response(flow: http.HTTPFlow):
    pass

在电脑 C:\Users\Administrator\.mitmproxy 中去获取。
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
开启代理(上面以开启代理,可以正常获取移动端的http请求,下面安装证书以获取https的请求!)
下载安装证书
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

移动端安装证书:获取https请求

在这里插入图片描述
在这里插入图片描述

(2)使用

此时我们的mitmproxy已经可以正常获取所有http以及https的请求了~
在这里插入图片描述

二、mitmdump的使用

其实,在我们下面的使用中会发现,mitmproxy功能跟fiddler几乎一模一样,我们为何来使用它呢?
通过下面对插件的使用,以及对插件的编写会发现,这个工具十分灵活,我们可以根据自己所需抓取想要的数据,也可以根据所需修改我们获取的响应,灵活多变!!!

(1)插件使用:

  1. 插件的本质就是一个脚本文件,在Python中就是一个类的实例对象。
  2. 此处插件是Counter实例对象,request方法是一个事件
  3. 对于request事件,它的参数是一个mitmproxy.http.HTTPFlow的对象。
    在这里插入图片描述
    上面是一个简单的插件,用于跟踪我们已经看到的流(或更具体的HTTP请求)数量。每次看到新的流量时,它都会使用mitmproxy的内部日志记录机制来进行提示。可以在交互式工具的事件日志中或mitmdump的控制台中找到输出。

比如:pycharm编写此脚本文件,Terminal中使用命令mitmdump -s ./anatomy.py运行插件。(./anatomy.py为此脚本文件的路径),即可在Terminal中观察到类似于下面的输出(因为使用的是mitmproxy的内部日志记录机制,所以会有很多记录数据):
在这里插入图片描述
小拓展:安静模式——使用命令mitmdump -q -s ./anatomy.py命令运行插件,即可屏蔽所有mitmproxy的日志信息,(注意:在request()函数中加入需要打印的信息!)输出格式如下:

#! python
# -*- coding: utf-8 -*-
# @Time    : 2024/10/10 66:66
# @Author  : GuHanZhe
# @File    : anatomy.py
"""
Basic skeleton of a mitmproxy addon.

Run as follows: mitmproxy -s anatomy.py
"""
from mitmproxy import ctx


class Counter:
    def __init__(self):
        self.num = 0

    def request(self, flow):
        self.num = self.num + 1
        ctx.log.info("We've seen %d flows" % self.num)
        # 需要打印的信息!
        print("We've seen %d flows" % self.num)


addons = [
    Counter()
]

在这里插入图片描述

上面使用的是官方给的插件例子,需要将事件放入类中进行运行。但是,如果我们只需要编写单一功能的插件,比如上面的只获取请求数量的插件,可以不那么麻烦编写——直接编写事件函数即可!(注意:事件函数名一定不能变!!!)

#! python
# -*- coding: utf-8 -*-
# @Time    : 2024/10/10 66:66
# @Author  : GuHanZhe
# @File    : anatomy.py
from mitmproxy import ctx

# 事件函数
num = 0
def request(flow):
    global num
    num += 1
    print('简单方法获取访问次数:', num)
    # 打印请求的url
    print(flow.request.url)
    ctx.log.info("We've seen %d flows" % num)
   

(2)HTTP事件

常用事件:
在这里插入图片描述

①request事件:

  1. 查看:
#! python
# -*- coding: utf-8 -*-
# @Time    : 2024/10/10 66:66
# @Author  : GuHanZhe
# @File    : anatomy.py
def request(flow):
    print('请求头:', flow.request.headers)
    print('请求url:', flow.request.url)
    print('域名:', flow.request.host)
    # 请求路径:url除域名之外的内容
    print('请求路径:', flow.request.path)
    # 返回MultiDictView类型的数据,URL的键值参数
    print('请求参数:', flow.request.query)
    print('请求方法:', flow.request.method)
    print('请求协议/类型(http/https):', flow.request.scheme)

    # 获取请求内容
    print('请求内容:', flow.request.get_text)
    print('内容类型:', type(flow.request.get_text))
    print('获取内容:', flow.request.get_text())
    print('请求内容bytes:', flow.request.raw_content)
    print('请求内容bytes:', flow.request.get_content())
    print('请求内容类型:', type(flow.request.get_content()))  # 输出: <class 'bytes'>
    print('==========================', end='\n')

  1. 修改请求中的参数:
#! python
# -*- coding: utf-8 -*-
# @Time    : 2024/10/10 66:66
# @Author  : GuHanZhe
# @File    : anatomy.py
def request(flow):
    if 'https://www.baidu.com' in flow.request.url:
        print('需要修改的参数:', flow.request.query.get('wd'))
        # .set_all()方法设置请求参数
        flow.request.query.set_all('wd', ['爬虫'])
        print('修改后的参数:', flow.request.query.get('wd'))

观察百度搜索,其中搜索内容的参数是:wd。
客户端浏览器中百度中不管搜索什么,经过此mitmproxy操作,都会将搜索内容改为“爬虫”!服务端收到的请求就是——百度搜索爬虫!!!

输出:
需要修改的参数: 猫咪图片
修改后的参数: 爬虫

  1. 拦截请求:
    拦截的形式,可以是kill当前请求:
#! python
# -*- coding: utf-8 -*-
# @Time    : 2024/10/10 66:66
# @Author  : GuHanZhe
# @File    : baidu_crawler.py
from mitmproxy import http
from mitmproxy.http import HTTPFlow


def request(flow: HTTPFlow):
    if flow.request.url.startswith("https://dig.chouti.com/"):
        flow.kill()


def response(flow: http.HTTPFlow):
    pass

在这里插入图片描述

②response事件:

  1. 查看:
#! python
# -*- coding: utf-8 -*-
# @Time    : 2024/10/10 66:66
# @Author  : GuHanZhe
# @File    : anatomy.py
def response(flow):
    # 状态码
    print(flow.response.status_code)

    # 返回内容,已解码
    print(flow.response.text)

    # 返回内容,Bytes类型
    print(flow.response.content)

    # 取得响应的文本
    print(flow.response.get_text())

  1. 修改响应内容:
#! python
# -*- coding: utf-8 -*-
# @Time    : 2024/10/10 66:66
# @Author  : GuHanZhe
# @File    : anatomy.py
def response(flow):
    print('======执行修改操作======')
    flow.response.set_text('信息已经被修改!')

此时不管你访问哪个网站,浏览器给你的响应都只要这一句话——信息已经被修改!

三、实战 - 下载百度图片

#! python
# -*- coding: utf-8 -*-
# @Time    : 2024/10/10 66:66
# @Author  : GuHanZhe
# @File    : baidu_crawler.py
import os

index = 0


def response(flow):
    global index
    print('===========开始执行===========')

    if 'JPEG' in flow.request.url:
        # 存放图片的文件夹
        file_one = 'image'
        if not os.path.exists(file_one):
            os.mkdir(file_one)

        file_name = file_one + '/' + str(index) + '.jpg'
        with open(file_name, 'wb') as f:
            f.write(flow.response.get_content())
            print(index)
            index += 1

Terminal终端中运行之后,百度图片中搜索一类图片(比如:猫咪图片),会发现浏览器加载图片速度稍微慢了一点点,其实,这就是我们编写的脚本代理在客户端和服务端中间截取数据,下载图片!!!
在这里插入图片描述


👇🏻可通过点击下面——>关注本人运营 公众号👇🏻

🎯 深度交流 | 📌 标注“来自 CSDN”
🌟 解决问题,拓展人脉,共同成长!(非诚勿扰)
🚀 不止是交流,更是你的技术加速器!
评论 20
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

孤寒者

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值