目录:
每篇前言:
🏆🏆作者介绍:【孤寒者】—CSDN全栈领域优质创作者、HDZ核心组成员、华为云享专家Python全栈领域博主、CSDN原力计划作者
- 🔥🔥本文已收录于爬虫从入门到精通系列教程专栏:《爬虫从入门到精通系列教程》
- 🔥🔥热门专栏推荐:《Python全栈系列教程》 | 《爬虫从入门到精通系列教程》 | 《爬虫进阶+实战系列教程》 | 《Scrapy框架从入门到实战》 | 《Flask框架从入门到实战》 | 《Django框架从入门到实战》 | 《Tornado框架从入门到实战》 | 《爬虫必备前端技术栈》
- 🎉🎉订阅专栏后可私聊进一千多人Python全栈交流群(手把手教学,问题解答);进群可领取Python全栈教程视频 + 多得数不过来的计算机书籍:基础、Web、爬虫、数据分析、可视化、机器学习、深度学习、人工智能、算法、面试题等。
- 🚀🚀加入我【博主V信:GuHanZheCoder】一起学习进步,一个人可以走的很快,一群人才能走的更远!
👇 👉 🚔文末扫码关注本人公众号~🚔 👈☝️
一、简介和安装
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)作用
- 代理的作用,转发请求,保障服务端与客户端的通信;
- 查看,记录,修改数据,引发服务端或客户端的特定行为。
(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请求
第一种获取证书的方式:
- 运行mitmweb工具:终端命令mitweb即可。
- 在代理状态下,访问
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
中去获取。
移动端安装证书:获取https请求
(2)使用
此时我们的mitmproxy已经可以正常获取所有http以及https的请求了~
二、mitmdump的使用
其实,在我们下面的使用中会发现,mitmproxy功能跟fiddler几乎一模一样,我们为何来使用它呢?
通过下面对插件的使用,以及对插件的编写会发现,这个工具十分灵活,我们可以根据自己所需抓取想要的数据,也可以根据所需修改我们获取的响应,灵活多变!!!
(1)插件使用:
- 插件的本质就是一个脚本文件,在Python中就是一个类的实例对象。
- 此处插件是
Counter
实例对象,request
方法是一个事件 - 对于
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事件:
- 查看:
#! 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')
- 修改请求中的参数:
#! 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操作,都会将搜索内容改为“爬虫”!服务端收到的请求就是——百度搜索爬虫!!!
输出:
需要修改的参数: 猫咪图片
修改后的参数: 爬虫
- 拦截请求:
拦截的形式,可以是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事件:
- 查看:
#! 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())
- 修改响应内容:
#! 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终端中运行之后,百度图片中搜索一类图片(比如:猫咪图片),会发现浏览器加载图片速度稍微慢了一点点,其实,这就是我们编写的脚本代理在客户端和服务端中间截取数据,下载图片!!!
🌟 解决问题,拓展人脉,共同成长!(非诚勿扰)