1. 项目概述:当QA遇上Vibe Coding
作为一名在测试一线摸爬滚打了十多年的老QA,我深知一个趁手的抓包工具对我们有多重要。无论是排查前后端接口数据不一致,还是复现线上偶现的诡异Bug,抓包分析都是我们定位问题的“火眼金睛”。但现实情况是,市面上主流的抓包工具如Fiddler、Charles、mitmproxy,功能虽强大,却各有各的“脾气”。Fiddler在Windows上如鱼得水,到了Mac上就水土不服;Charles的证书配置对新手来说是个不小的门槛;而mitmproxy,命令行操作对零代码基础的同事来说,简直是天书。我们常常需要在这些工具间切换,或者忍受某些不顺手的功能,效率大打折扣。
最近,一个叫“Vibe Coding”的概念火了起来。简单说,它就是一种通过自然语言描述需求,让AI(比如DeepSeek、豆包等大模型)直接生成可运行代码的开发方式。这让我眼前一亮:我们这些日常跟测试用例、需求文档打交道的QA,大多没有深厚的编程功底,但我们对测试场景、对工具的需求痛点却了如指掌。能不能用Vibe Coding,为自己量身定制一款抓包工具呢?一款能同时监听HTTP/HTTPS、界面直观、过滤方便、还能一键导出报告的工具?
这个想法让我很兴奋。经过一番摸索和实践,我真的用Vibe Coding“拼”出了一款足够好用的抓包工具原型。整个过程,我没有写一行传统意义上的代码,全靠和AI“对话”来完成。这篇文章,我就把这套方法、踩过的坑以及最终成型的工具思路,完整地分享出来。无论你是零代码基础的测试新人,还是想提升效率的资深QA,相信都能从中获得启发,打造属于你自己的“瑞士军刀”。
2. 核心思路与方案选型:为什么是Vibe Coding + mitmproxy?
决定动手之前,我先盘点了需求和现有方案。我们的核心诉求很明确:图形化界面、支持HTTPS解密、请求/响应过滤、数据搜索、导出功能。市面上成熟的抓包工具底层无一例外都依赖于代理服务器和SSL/TLS中间人攻击技术。这意味着,我们没必要从零发明轮子,而是应该找一个可靠、开源的核心库,然后为它套上一个我们喜欢的“壳”。
2.1 底层核心库选型:mitmproxy的胜出
我评估了三个常见的底层库:
- FiddlerCore:.NET库,功能强大,但绑定Windows平台,且授权复杂。
- Charles的Java版本:并未提供独立的可嵌入库,主要是商业桌面应用。
- mitmproxy:Python编写,完全开源,不仅是一个工具,更是一套完整的、可编程的代理框架。它提供了
mitmproxy命令行工具、mitmdump数据导出工具,以及最重要的mitmproxy的Python库,允许你通过编写插件(addon)来深度定制每一个请求和响应的处理逻辑。
对于Vibe Coding来说,mitmproxy几乎是唯一选择。原因有三:第一,Python是AI大模型生成代码最熟练、最可靠的语言之一,生态丰富,出错率低。第二,mitmproxy的文档和社区非常活跃,任何遇到的问题,几乎都能找到答案或思路。第三,它的架构清晰,事件驱动模型(如request、response事件)非常容易理解,我们只需要告诉AI“当收到请求时,把数据存起来并显示在表格里”,AI就能生成对应的代码框架。
2.2 图形界面选型:Tkinter的务实之选
确定了“发动机”(mitmproxy),接下来要选“驾驶舱”(UI)。Python的GUI库很多,PyQt/PySide功能强大但复杂,打包后体积大;Kivy适合移动端;Web技术(如Flask+浏览器)需要启动服务,稍显笨重。 对于我们的定制化工具,Tkinter脱颖而出。它是Python的标准库,无需额外安装,AI对其生成代码的掌控力非常强。虽然界面复古,但实现列表、按钮、文本框、菜单等核心组件绰绰有余。我们的目标是“好用”而非“好看”,Tkinter完全满足需求,且最终打包成单个可执行文件(如用PyInstaller)也非常方便。
2.3 Vibe Coding工作流设计
方案定了,怎么用Vibe Coding实现?我总结了一个高效的工作流:
- 分治:不要求AI一次性生成整个复杂程序。而是将大项目拆解成独立的小模块,例如“设计主窗口布局”、“实现请求列表显示”、“集成mitmproxy核心并启动代理”、“实现HTTPS证书安装指引”、“添加过滤搜索功能”。
- 精准描述:给AI的指令(Prompt)必须具体、清晰,包含输入、处理、输出的期望。例如,不是“给我一个表格”,而是“使用Tkinter的Treeview组件创建一个表格,表格有这些列:序号、方法、URL、状态码、耗时、大小。当有数据来时,插入新行。”
- 迭代与调试:AI生成的代码很少能一次完美运行。我们需要扮演“测试员”和“产品经理”的角色,运行代码,看报错信息,然后将错误日志或异常现象反馈给AI,让它修正。这个过程本身就是一种“对话式开发”。
基于以上思路,我们的技术栈最终确定为:Python + mitmproxy(核心库) + Tkinter(UI),通过Vibe Coding(我主要使用了DeepSeek)进行串联开发。
注意:这里有一个关键点,mitmproxy本身是一个独立的进程,我们的Tkinter GUI是另一个进程。如何让它们通信?我采用了线程+队列的方式。在GUI应用中启动一个线程来运行mitmproxy,并通过mitmproxy的addon将抓到的数据放入一个队列,GUI主线程定时从队列中取数据并更新UI。这个架构思路需要提前明确,并在给AI的指令中说明。
3. 分步实现与核心代码解析
下面,我将按照实际开发顺序,拆解各个核心模块的实现。你可以把这些Prompt和代码思路当作模板,直接用于你的AI对话。
3.1 第一步:构建图形化主界面骨架
首先,我们需要一个能看见、能操作的窗口。我给AI的Prompt如下: “请用Python Tkinter创建一个窗口,标题为‘QA抓包工具’。窗口布局分为上中下三部分:顶部是工具栏(放置‘开始抓包’、‘停止抓包’、‘清除日志’按钮和过滤输入框);中间主体部分是一个表格(Treeview),用于显示抓到的HTTP请求列表,列包括:ID、方法、URL、状态码、内容类型、大小;底部是一个多行文本框(Text),用于显示选中某条请求的详细内容(包括请求头和响应头)。请使用grid或pack布局管理器,确保界面整洁。”
AI通常会生成一个结构清晰的代码。这里我强调几个需要手动调整或注意的关键点:
- Treeview样式优化:AI生成的Treeview可能没有滚动条,或者列宽不合适。你需要补充指令:“为表格添加垂直和水平滚动条,并设置每列的初始宽度,让URL列更宽一些。”
- 数据存储结构:我们需要在内存中保存抓到的数据,以便在表格和详情框之间联动。我会定义一个全局列表(如
request_list = [])来存储字典格式的请求数据,字典的键对应表格的每一列。 - 事件绑定:需要告诉AI,为Treeview绑定事件,例如
<<TreeviewSelect>>,当用户点击表格某一行时,底部详情框应显示该请求的详细信息。Prompt可以是:“为Treeview组件绑定选择事件,当用户选中一行时,从request_list中根据ID找到对应的请求数据,并将其请求头和响应头格式化后显示在底部的Text组件中。”
3.2 第二步:集成mitmproxy并实现数据捕获
这是最核心的一步。我们需要在后台启动mitmproxy,并捕获所有流经的请求。
首先,安装依赖。在项目目录下,你需要一个requirements.txt文件,内容为:
mitmproxy>=10.0通过pip install -r requirements.txt安装。
然后,编写mitmproxy插件。我给AI的Prompt较长,但必须详细: “请编写一个mitmproxy的addon(插件),命名为CaptureAddon。这个addon需要做两件事:1. 在request事件中,捕获请求的method、url、headers,并生成一个唯一ID。2. 在response事件中,捕获状态码、响应头、响应体大小和内容类型。请将每次请求和对应的响应信息,组合成一个字典对象。为了能让Tkinter界面获取到这些数据,请使用一个queue.Queue队列。将这个字典放入队列中。同时,请确保这个addon能处理HTTPS流量,这意味着不需要在addon内做额外配置,但主程序需要能引导用户安装mitmproxy的根证书。”
AI生成的addon.py代码骨架会类似这样:
# addon.py import queue from mitmproxy import http class CaptureAddon: def __init__(self, data_queue: queue.Queue): self.data_queue = data_queue self.request_map = {} # 临时存储请求信息,用flow.id关联 def request(self, flow: http.HTTPFlow): # 存储请求信息 request_id = f"{flow.id}_{flow.request.timestamp}" self.request_map[flow.id] = { 'id': request_id, 'method': flow.request.method, 'url': flow.request.pretty_url, 'request_headers': dict(flow.request.headers), 'timestamp': flow.request.timestamp } def response(self, flow: http.HTTPFlow): # 关联请求,组合完整信息 req_info = self.request_map.pop(flow.id, {}) if req_info: response = flow.response item = { **req_info, 'status_code': response.status_code, 'content_type': response.headers.get('Content-Type', ''), 'size': len(response.content) if response.content else 0, 'response_headers': dict(response.headers), # 注意:谨慎保存响应体,可能很大。可以只保存文本类型的预览。 'response_preview': self._get_preview(response) } # 放入队列,供GUI消费 self.data_queue.put(item) def _get_preview(self, response): # 一个简单的预览生成函数,只处理文本内容 content_type = response.headers.get('Content-Type', '').lower() if 'json' in content_type or 'text' in content_type: try: return response.content.decode('utf-8', errors='ignore')[:500] # 只取前500字符 except: pass return '[Binary Data]'接着,在GUI中启动mitmproxy线程。我们需要修改主程序,在点击“开始抓包”按钮时,在一个独立线程中启动mitmproxy。 Prompt:“在Tkinter程序中,为‘开始抓包’按钮编写事件处理函数。点击后,在一个新线程中启动mitmproxy。启动命令需要:1. 指定代理监听的端口(如8080)。2. 加载我们刚才写的CaptureAddon插件,并将一个队列实例传递给它。3. 设置quiet=True以减少控制台输出。请确保线程能正确启动和停止,当点击‘停止抓包’按钮时,能安全地关闭mitmproxy。”
关键代码段会涉及线程管理和mitmproxy的options、master等对象,AI可能会需要几次调试才能生成正确代码。核心是学会使用from mitmproxy import options, master和from mitmproxy.tools.dump import DumpMaster。
3.3 第三步:实现GUI与抓包数据的联动
数据在队列里,UI需要定时去取。这里我们需要一个定时任务。 Prompt:“在Tkinter主窗口类中,添加一个方法,例如update_request_list。使用after方法,每100毫秒调用一次自己。在这个方法里,从与CaptureAddon共享的数据队列中,尝试获取所有新到达的请求数据。如果取到数据,就将其追加到request_list中,并在Treeview表格中插入新的一行。同时,更新状态栏显示抓包数量。”
这个环节要注意线程安全。Tkinter的UI操作必须在主线程中进行。我们的队列queue.Queue是线程安全的,所以从队列取数据这个操作在after回调函数(在主线程执行)中进行是安全的。取到数据后,直接操作request_list和Treeview即可。
3.4 第四步:处理HTTPS解密与证书安装
这是让很多新手QA头疼的问题。mitmproxy要解密HTTPS流量,必须在客户端(手机或浏览器)安装其根证书。 我们的工具不能指望用户自己去命令行生成证书,必须提供一键式或向导式的安装指引。
我的做法是:
在工具内提供证书生成与查看功能。Prompt:“在菜单栏添加一个‘证书’菜单,其下有一个‘安装根证书’选项。点击后,执行以下步骤:首先,检查用户目录下是否存在mitmproxy的证书文件(通常位于
~/.mitmproxy/mitmproxy-ca-cert.pem)。如果不存在,则弹窗提示用户需要先启动一次抓包工具以自动生成证书。如果存在,则用Tkinter的filedialog和messagebox,引导用户将证书文件复制到桌面,并弹出详细的操作说明(图文并茂),说明如何将证书安装到手机(描述通用路径)或电脑浏览器。”编写详细的指引文档。这部分可以提前写好,放在一个帮助对话框里。内容包括:
- iOS安装:描述如何通过Safari访问
http://mitm.it,下载证书后,到“设置-通用-关于本机-证书信任设置”中启用完全信任。 - Android安装:描述如何通过浏览器访问
http://mitm.it,下载证书后,在设置中搜索“安装证书”或“CA证书”进行安装(不同品牌路径不同,需给出常见品牌的查找关键词)。 - Windows/浏览器安装:引导用户将
.pem文件导入到系统的受信任根证书颁发机构。
- iOS安装:描述如何通过Safari访问
实操心得:证书安装是成功率的关键。我在工具里直接内置了一个简单的HTTP服务器,当用户点击“生成安装指引”时,自动在本地启动一个页面,用更直观的HTML页面展示针对不同设备的安装步骤截图和视频链接(可以是录制好的GIF),这比纯文字说明体验好得多。这个HTTP服务器也可以用Vibe Coding让AI生成,就是一个简单的Python
http.server,指向一个我们准备好的静态HTML目录。
3.5 第五步:增强功能——过滤、搜索与导出
基础抓包功能有了,接下来是提升效率的增强功能。
过滤:工具栏上的过滤输入框,可以实时过滤表格中显示的请求。Prompt:“为过滤输入框绑定<KeyRelease>事件。每当输入框内容变化时,遍历request_list,将URL或方法包含输入文本的请求重新显示在Treeview中,隐藏不匹配的项。” 这里注意性能,如果请求量很大,需要做防抖处理(比如延迟300毫秒再执行过滤)。
搜索:实现一个独立的搜索对话框,可以搜索请求头、响应体中的内容。这需要遍历request_list中保存的response_preview和request_headers。Prompt:“创建一个新的Toplevel窗口作为搜索框。提供一个输入框和一个‘搜索’按钮。点击按钮后,在新的窗口中列出所有请求URL、请求头或响应预览中包含搜索关键词的条目,并支持点击跳转到主窗口的对应请求。”
导出:这是报告的关键。QA经常需要把抓包记录保存下来。Prompt:“在菜单栏添加‘导出’菜单,支持两种格式:1. 导出为JSON(完整数据,便于程序分析)。2. 导出为HTML报告(便于阅读和分享)。HTML报告可以用Jinja2模板生成,模板需要展示请求列表和每个请求的详情。” 你可以让AI先写一个简单的Jinja2 HTML模板,然后让AI写代码将request_list数据渲染进去并保存为文件。
4. 常见问题、调试技巧与避坑指南
用Vibe Coding开发,整个过程就是与AI不断调试、磨合的过程。我遇到了不少典型问题,这里分享出来,帮你节省时间。
4.1 mitmproxy启动失败或无法抓包
问题:点击开始后,控制台报错
Address already in use。原因:端口(默认8080)被其他程序(如你之前打开的Charles、Fiddler或其他mitmproxy实例)占用。
解决:在工具设置里增加端口配置选项,或提示用户更换端口(如8081, 8888)。Prompt:“修改启动mitmproxy的代码,从界面的一个Spinbox组件中读取端口号,而不是写死8080。”
问题:工具显示已启动,但手机/浏览器设置代理后无法上网。
原因1:电脑防火墙阻止了mitmproxy。
解决:在防火墙设置中允许Python或你打包后的可执行程序通过防火墙。
原因2:代理设置不正确。
解决:在工具界面明确显示“代理服务器地址:
本机IP:端口”(例如192.168.1.100:8080),并提供“复制地址”按钮。指导用户必须在同一局域网下设置代理。
4.2 HTTPS流量显示为Tunnel to或无法解密
- 问题:抓到的HTTPS请求,URL列显示为
Tunnel to xxx:443,没有具体的请求路径。 - 原因:客户端(手机/浏览器)没有正确安装或信任mitmproxy的根证书。这是最常见的问题。
- 解决:
- 确保你的工具已成功引导用户安装了证书。
- 对于iOS,必须额外在“设置-通用-关于本机-证书信任设置”里启用对mitmproxy证书的完全信任,这一步极易被忽略。
- 对于某些App(如银行类、强校验的App),它们可能使用了证书绑定技术,会拒绝mitmproxy的证书。这种情况下,常规抓包无效,需要更高级的逆向手段,这超出了本工具的范围。在工具帮助文档中应说明这一点。
4.3 GUI界面卡顿或无响应
- 问题:抓包一段时间后,界面卡死,或者滚动表格时很卡。
- 原因:UI线程被阻塞,或数据量太大导致Treeview操作变慢。
- 解决:
- 确保耗时操作在独立线程:启动/停止mitmproxy、导出报告等操作,必须放在单独线程,避免阻塞Tkinter主循环。
- 优化数据存储与显示:
request_list不要无限制增长,可以提供“清除”按钮。对于Treeview,可以尝试只显示最近N条(如500条)请求,更早的存入文件或内存数据库(如sqlite)。AI可以帮你写一个带最大长度限制的列表管理逻辑。 - 使用
after进行异步更新:我们已经用了after来更新UI,这是正确的。确保在update_request_list方法中,每次从队列取数据的操作要快,如果队列里积累了太多数据,可以分批取出,比如一次最多处理10条。
4.4 Vibe Coding过程中的调试技巧
- 精准报错:当AI生成的代码运行出错,不要简单地说“代码错了”。把完整的错误信息(Traceback)复制给AI。AI能根据错误信息精准定位问题所在,比如是导入错误、变量未定义还是逻辑错误。
- 分步验证:不要等所有模块都写完再测试。每让AI生成一个功能模块(如按钮点击事件、表格更新函数),就立刻运行测试一下。确保这个小模块是work的,再继续下一个。
- 提供上下文:当你要求AI修改或添加功能时,最好把相关的那段代码也贴给它,并说明“在以下代码的基础上,请添加...功能”。这能避免AI凭空想象,生成不兼容的代码。
- 自己理解逻辑:不要完全做“甩手掌柜”。AI生成的代码,你要尽量去读懂它。这不仅能帮你排查问题,更是你学习的过程。下次遇到类似需求,你甚至能自己修改几行代码就搞定。
5. 打包分发与后续迭代
当你的工具开发完成,你肯定想把它分享给组里的其他QA同事,他们可能没有Python环境。
打包成可执行文件:使用PyInstaller。这是另一个可以用Vibe Coding完成的步骤。创建一个spec文件或直接使用命令行。Prompt:“我有一个Tkinter程序,主文件是main.py,依赖了mitmproxy。请给出使用PyInstaller将其打包为单个Windows可执行文件(exe)的命令,并处理可能遇到的隐藏导入问题。”
典型的命令是:pyinstaller --onefile --windowed --add-data “./cert_help;cert_help” main.py。其中--add-data是为了包含我们之前做的证书帮助文档的静态资源文件夹。
后续迭代:你的工具1.0版上线后,同事们会给你反馈。“能不能加一个重放请求的功能?”“能不能对比两次请求的差异?”“能不能自动生成接口测试用例?” 这些都可以作为2.0、3.0版本的需求。因为核心框架已经搭好,每个新功能都可以作为一个独立的模块,继续用Vibe Coding的方式去实现。例如,“重放请求”功能,其实就是从request_list中取出某条请求的历史数据,再用requests库按照原样发出去。把这个需求描述给AI,它就能帮你生成一个带参数设置的“重放”对话框和对应的执行代码。
整个过程下来,我从一个只会提需求的QA,变成了一个能为自己团队打造专属工具的“开发者”。这种成就感,远超于找到一个严重的Bug。Vibe Coding并没有让我变成真正的程序员,但它给了我一把“翻译”的钥匙,把我对测试工作的深刻理解,翻译成了实实在在的生产力工具。如果你也在为找不到顺手的工具而烦恼,不妨现在就打开你的AI对话窗口,从一句“我想用Python和Tkinter创建一个简单的窗口”开始,你的定制化抓包工具之旅,或许就在今天启程。