使用Fiddler抓包的时候,自动化、定制化的保存请求数据或响应数据是一个高频且刚需的需求。
实现过程
- 编写js脚本
- 获取响应数据
- 保存数据或处理数据
设置脚本
Fiddler支持 自定义脚本来实现该功能,默认支持js脚本。
选择:Rules->Customize Rules..(规则-> 自定义规则)
也可以直接使用快捷键 Ctrl+R
这时会自动使用默认的文本编辑器打开Rules脚本文件。一般是Windows系统自带的txt软件,也可以自定义指定,我这里指定使用vscode软件。
设置过程如下:
这里就可以随意修改,增加你的自定义规则了。
脚本代码就是js语言。
保存Response
比如我这里做的:我抖音里关注了一千多个作者,设置fiddler抓包后,发现返回的是分页的json数据,我想让fiddler自动把这些json保存到磁盘文件。
修改脚本,找到 OnBeforeResponse 方法修改即可,修改后可能需要重启。
static function OnBeforeResponse(oSession) {
if (m_Hide304s && oSession.responseCode == 304) {
oSession["ui-hide"] = "true";
}
//过滤:抖音关注接口
if (oSession.fullUrl.Contains("https://api3-normal-c-lq.amemv.com/aweme/v1/user/following/list")){
// 保存文件到本地
var fso;
var file;
fso = new ActiveXObject("Scripting.FileSystemObject");
// ActiveXObject.OpenTextFile()方法 必须是目录存在,需要提前建立文件目录
file = fso.OpenTextFile("D:\\FiddlerData\\Sessions.txt",8 ,true, true);
// oSession.GetResponseBodyAsString() 为获取相应的json数据
file.writeLine(oSession.GetResponseBodyAsString());
file.writeLine("\n");
file.close();
}
}
抓取到数据如下:
记录下其他代码,方便拷贝:
保存数据并且发送给自己的某服务示例
static function OnBeforeResponse(oSession: Session) {
if (m_Hide304s && oSession.responseCode == 304) {
oSession["ui-hide"] = "true";
}
// if (oSession.fullUrl.Contains("baidu.com")){
if (1){
oSession.utilDecodeResponse();//消除保存的请求可能存在乱码的情况
var jsonString = oSession.GetResponseBodyAsString();
var responseJSON = Fiddler.WebFormats.JSON.JsonDecode(jsonString);
if((responseJSON.JSONObject=='System.Collections.ArrayList' || responseJSON.JSONObject=='System.Collections.Hashtable')&&jsonString!='[]'&&jsonString!='{}'){
// 判断是否是json数据 然后保存
var str='{}';//构造自己的JSON http请求的信息及返回的结果
var data = Fiddler.WebFormats.JSON.JsonDecode(str);
data.JSONObject["request_method"] = oSession.RequestMethod;
var requestString = oSession.GetRequestBodyAsString();
data.JSONObject["request_body"]= requestString;
data.JSONObject["response_data"] = responseJSON.JSONObject;
data.JSONObject["url"] = oSession.fullUrl;
data.JSONObject["response_code"] = oSession.responseCode;
jsonString = Fiddler.WebFormats.JSON.JsonEncode(data.JSONObject)
// 保存文件到本地
var fso;
var file;
fso = new ActiveXObject("Scripting.FileSystemObject");
file = fso.OpenTextFile("E:\\spider_img\\Sessions.dat",8 ,true, true);
file.writeLine(jsonString);
file.writeLine("\n");
file.close();
// 数据通过post请求发送自己的后台服务保存
FiddlerObject.log('2222222222222222'+jsonString);
// methods
var method = "POST";
var myUrl = 'http://localhost:8000/fiddler'
var url = myUrl+'?data='+Utilities.UrlEncode(jsonString);
var protocol = "HTTP/1.1";
var raw="";
var selected: Session = oSession;
raw += method + " " + url + " " + protocol + "\r\n";
raw +="Host:localhost:8000\r\n";
raw +="Connection: keep-alive\r\n";
raw +="Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8\r\n";
raw +="User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.122 Safari/537.36\r\n";
raw +="Accept-Encoding: gzip,deflate,sdch\r\n";
raw +="Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.6,en;q=0.4\r\n";
raw +="Content-Type: application/json\r\n";
var body= "jsondata=''";
raw += "\r\n" + body;
FiddlerObject.utilIssueRequest(raw);
}
}
}
保存图片示例
static function OnDone(oSession: Session) {
//检查Content-Type
if (oSession.ResponseHeaders["Content-Type"]!=null || oSession.ResponseHeaders["content-type"]!=null)
{
//避免不规范标头
var contentType=oSession.ResponseHeaders["Content-Type"];
if (String.IsNullOrEmpty(contentType) )
contentType=oSession.ResponseHeaders["content-type"];
//判定请求是否图片
if (contentType.Contains("image"))
{
//确定文件名(保存用)
var fileName="";
var fileIndex = oSession.RequestHeaders.RequestPath.LastIndexOf ("/");
if (fileIndex>0)
fileName = oSession.RequestHeaders.RequestPath.Substring (fileIndex+1);
//如果文件名非法(名称含非法字符)
if(fileName.IndexOf('?')>0 || fileName.IndexOf('&') )
fileName=String.Empty;
//输出日志(在Fiddler 主窗口,日志处输出)
//FiddlerObject.log("Content-Type:"+ contentType +" RequestPath:"+oSession.RequestHeaders.RequestPath);
//如果文件名为Null,自行创建一个文件名(Guid)
if (String.IsNullOrEmpty( fileName))
{
fileName=Guid.NewGuid().ToString();
var extName= contentType.Replace("image/","");
fileName=fileName+"."+extName;
}
//太小的图片不要,比如站位图片(自行调节)
if (oSession.ResponseBody.Length>100)
{
//指定保存位置
var saveDir="d:\\Temp\\";
//不存在则创建文件夹
if (!System.IO.Directory.Exists(saveDir))
System.IO.Directory.CreateDirectory(saveDir);
//保存响应流
oSession.SaveResponseBody(saveDir+fileName);
//写日志
FiddlerObject.log("[文件保存]:"+fileName)
}
}
}
}
保存Request
理,也可以修改Request,把下面代码贴在OnBeforeRequest()
方法末尾
//过滤无关请求,只关注特定请求
if (oSession.fullUrl.Contains("szhome.com"))
{
var fso;
var file;
fso = new ActiveXObject("Scripting.FileSystemObject");
//文件保存路径,可自定义
file = fso.OpenTextFile("D:\\Fiddler Sessions\\Sessions.txt",8 ,true, true);
file.writeLine("Request url: " + oSession.url);
file.writeLine("Request header:" + "\n" + oSession.oRequest.headers);
file.writeLine("Request body: " + oSession.GetRequestBodyAsString());
file.writeLine("\n");
file.close();
}
FiddlerScript 中的主要方法
你的FiddlerScript 文件中包含一个静态类Handlers,一般来说,你的代码应该写在这个类的静态方法中。
Fiddler 运行时会自动执行一些” Application event methods”:
static function OnBoot | fiddler 启动时调用 |
---|---|
static function OnShutdown | fiddler关闭时调用 |
static function OnAttach | fiddler注册成系统代理时调用 |
static function OnDetach | fiddler 取消注册系统代理时调用 |
static function Main | 在每次fiddler启动时和编译CustomRules.js 脚本时调用。 |
// 在这个方法中修改Request的内容, 我们用得最多
static function OnBeforeRequest(oSession: Session)
// 在这个方法中修改Response的内容
static function OnBeforeResponse(oSession: Session)
// 在个方法中包含Fiddler 命令,在Fiddler界面中左下方的QuickExec Box,如果你的脚本处理了指定的命令,则返回true,否则返回false.
static function OnExecAction(sParams: String[])
参考资料
- JScript.NET语言参考:http://msdn.microsoft.com/en-us/library/z688wt03(VS.80).aspx
- 控制Session 的UI样式:http://www.fiddlerbook.com/Fiddler/dev/SessionFlags.asp
- Fiddler Script 的官方帮助文档:http://www.fiddlerbook.com/Fiddler/dev/ScriptSamples.asp
- 修改Fiddler 请求与响应:http://fiddler2.com/documentation/KnowledgeBase/FiddlerScript/ModifyRequestOrResponse
- Fiddler Blog: http://www.telerik.com/automated-testing-tools/blog/eric-lawrence.aspx