Fiddler脚本

写好脚本则更能够帮你抓取数据到文件、数据库,部分实现自动化,甚至远超一些同类专业产品。

常规功能
可以用来指定抓取所有的WEB通讯,也可以只抓取指定进程的通讯。

File-Capture Traffic ; Any Process 或拖动选定进程窗口

2.可以用来查看一个URL打开后,浏览器与后端的交互

3.可以查看任意一个HTTP交互,看请求和响应的原始报文,帮助你了解HTTP协议

4.可以设置丰富的过滤条件,确保聚焦

5.可以以各种形态查看数据,并提供了工具来做转换【这个比较丰富,但隐藏较深】

6.可以编写脚本,实现各个阶段的处理

可以基于类似Windows下的WScript,甚至使用一些ActiveX组件实现并发机制、通讯与数据存储。

OnBeforeRequest 在请求发生前调用,请求经过Fiddler发送给服务器之前会先调用这个函数,因此,如果想要修改请求,可以写在这个函数里
OnPeekAtResponseHeaders 在头到达后调用
OnBeforeResponse 在内容到达后,还没有处理前调用,从服务器读完响应后,且在将响应发送给客户端之前执行的。通过修改这个函数,可以修改服务器的响应头或者响应体

把网页上的JSON文件下载到本地

把以下内容放入OnBeforeResponse里面,

    if (m_Hide304s && oSession.responseCode == 304) {
        oSession["ui-hide"] = "true";
    }

    if (oSession.uriContains("https://www.tiktok.com/api/recommend/item_list/")){
        var strBodytk=oSession.GetResponseBodyAsString();
        //var spstk = oSession.PathAndQuery.slice(-58,);
        //FiddlerObject.alert(spstk)
        var timestamptk=new Date().getTime();
        var filenametk = "D:\\tiktokzl" + "\/" + timestamptk + ".json";
        //var filename = "D:\抖音评论资料" + "/" + sps + timestamp + ".json";
        var curDatetk = new Date(); 
        var swtk : System.IO.StreamWriter; 
        if (System.IO.File.Exists(filenametk)){ 
            swtk = System.IO.File.AppendText(filenametk); 
            swtk.Write(strBodytk); 
        } 
        else{ 
            swtk = System.IO.File.CreateText(filenametk); 
            swtk.Write(strBodytk); 
        } 
        swtk.Close(); 
        swtk.Dispose(); 

    }

抓到 请求的数据  保存本地txt 文件里面

  • 将下代码  粘到OnBeforeRequest 的函数里头
  • if (oSession.fullUrl.Contains("填写需要抓取的域名")) {    var fso;    var file;    fso = new ActiveXObject("Scripting.FileSystemObject");    //文件保存路径可自定义    file = fso.OpenTextFile("填写保存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();}

自动化抓取图片并提出重复的
static function FileExsitInDirectory(fso:Object, filename:String , dirpath:String )
{
var curPath = dirpath + “/” + filename ;
var objset , objFolders , FolderName, ret;

    if (fso.FileExists(curPath)) 
    {
        return  curPath;
    }
    else
    {
        var objset = fso.getFolder(dirpath);

        var objFolders = objset.SubFolders;

        var fenum = new Enumerator(objset.SubFolders); 

        for (var i = 0 ; !fenum.atEnd(); fenum.moveNext(),i++)
        { 

            var FolderName = dirpath + "/" + fenum.item().Name + "/";

            var ret = FileExsitInDirectory(fso, filename, FolderName);

            if( ret != "NULL" ) 
            {
                return ret
            }                                   
        } 
        return "NULL";  
    } 
}

static function OnBeforeResponse(oSession: Session)
{
if (m_Hide304s && oSession.responseCode == 304)
{
oSession[“ui-hide”] = “true”;
}

    //如果来自指定网站,且是jpg,则写文件 image/jpeg
    if(
        (oSession.RequestHeaders.AllValues("Host").Contains(".mm115.net") ||
        oSession.RequestHeaders.AllValues("Host").Contains(".jzsjwk.com"))

        &&
        oSession.ResponseHeaders.AllValues("Content-Type").Contains("image/jpeg") )
    {      

        var whindex = oSession.url.IndexOf ('?');           

        if (whindex <= 0)
            whindex = oSession.url.Length;

        var file_url = oSession.url.Substring (0,whindex);

        whindex = oSession.url.IndexOf ('.jpg');            

        if ((whindex > 0) && (oSession.GetResponseBodyAsString().Length > 40000))
        {
            whindex = whindex+4;            


            file_url = file_url.Substring (0,whindex).Replace ('/','_').Replace('%','B').Replace('?','7').Replace('&','-').Replace('img22.jzsjwk.com','img1.mm115.net');

            var file_path  = "d:/PRVIT/jpg/"+file_url;

            try
            {
                var fso = new ActiveXObject("Scripting.FileSystemObject"); 

                var retval = FileExsitInDirectory(fso,file_url,"d:/PRVIT/jpg/");

                FiddlerObject.log (retval);

                if ("NULL" == retval)
                {           
                    var stream = new ActiveXObject('Adodb.Stream');  
                    stream.Mode = 3;  
                    stream.Open();  


                    stream.Type = 1;  
                    //stream.Charset = 'unicode';  
                    //stream.WriteText(s);  

                    stream.Position = 0;  
                    stream.Type = 1;  
                    //stream.Position = 2;  
                    //var bs = stream.Read();  
                    //stream.Position = 0;  
                    stream.Write(oSession.responseBodyBytes);  
                    //stream.SetEOS();  

                    stream.SaveToFile(file_path,1);  

                    stream.Close(); 


                    oSession["ui-backcolor"] = "yellow";
                }
                else
                {
                    oSession["ui-strikeout"] = "true";
                    oSession["ui-backcolor"] = "green";
                }

            }
            catch(err)
            {
                FiddlerObject.log (err.message);
                oSession["ui-backcolor"] = "red";
            }


        }
        else
        {
            oSession["ui-color"] = "red";
        }

    }





}

抓取内容,并存放到数据库
var sql = “”;
try
{
var con =new ActiveXObject(“ADODB.Connection”);

            //con.Provider="Microsoft.ACE.OLEDB.18.0";



            var rs=new ActiveXObject("ADODB.Recordset");

            /**
            Provider=Microsoft.ACE.OLEDB.12.0;Data Source=Y:/TEST/fiddler_web_service_analysis.accdb;Persist Security Info=False;
            **/

            //var access_db_path = "d:/fiddler_web_service_analysis.accdb" ;

            //con.ConnectionString="Data Source="+access_db_path;

    //ODBC DSN name ,config by windows odbc
            con.open("DSN=db_hsb_vs_ahs;") ;


            //FiddlerObject.alert(1);




            sql = "insert into  t_call_record (call_timestamp,request_send_timestamp,response_recv_timestamp,sitename,url,request,response,spend_second,content_type,content_length) values(" +
                strVar1(oSession.Timers.FiddlerBeginRequest) + "," +
                strVar1(oSession.Timers.ClientDoneRequest) + "," +
                strVar1(oSession.Timers.ServerDoneResponse) + "," +
                strVar1(oSession.RequestHeaders.AllValues("Host")) + "," +
                strVar1(oSession.url.Substring (0,whindex)) + "," +
                strVar1(oSession.RequestHeaders.ToString ()+oSession.GetRequestBodyAsString()) + "," +
                strVar1(oSession.ResponseHeaders.ToString ()+oSession.GetResponseBodyAsString()) + "," +
                etimes*1000  + "," +
                strVar1(oSession.ResponseHeaders.AllValues("Content-Type")) +"," +
                oSession.ResponseHeaders.AllValues("Content-Length")+0

                +");";

            //FiddlerObject.alert(sql);

            rs.open(sql,con);

            oSession["ui-color"] = "red";

            //rs.close();
            // rs=NULL;

            con.close();
            // con = NULL;



        }
        catch(exp)
        {

            var txt="Error description: " + exp.message + "\n\n" + sql;
            FiddlerObject.log(txt);
            oSession["ui-strikeout"] = "true";

        }

  1. 在此处【重定向urlplace】host和url的判断
  if(oSession.HostnameIs("host") && oSession.url.IndexOf("url_path") > -1){
	    oSession.hostname = "api.mobile.xxx.com"
		  }
  1. 在此处【设置请求的header】,测试网络爬虫时候会用,
// TSET FOR Spider: 根据网站来限定请求
if (oSession.HostnameIs("test.com")) {
    // 模拟修改请求的用户端ip,这种情况对独立的网络有效,对于公司级的网络,还是有一些问题,需要借助vpn
    oSession.oRequest["X-Forwarded-For"]="16.12.23.16";
    // 修改请求的header
    oSession.oRequest["User-Agent"] = "spider Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.81 Safari/537.36 SE 2.X MetaSr 1.0";

}

2019.04.26 手机模拟添加cookie(区别于种cookie 在onBeforeResponse里)

  • 删除所有的cookie oSession.oRequest.headers.Remove("Cookie");
  • 新建cookie oSession.oRequest.headers.Add("Cookie", "username=testname;testpassword=P@ssword1");

注意: Fiddler script不能直接删除或者编辑单独的一个cookie, 你需要用replace方法或者正则表达式的方法去操作cookie的string

if (oSession.HostnameIs("******") && oSession.oRequest.headers.Exists("Cookie") ) {

    var sCookie = oSession.oRequest["Cookie"]; 
    //用replace方法或者正则表达式的方法去操作cookie的string
    //sCookie = sCookie.Replace("cookieName=", "ignoreme="); 
    sCookie = sCookie + ";tt_spver=1";

    oSession.oRequest["Cookie"] = sCookie; 
}


在此处修改response的bady内容【使用正则匹配方式】
   if(oSession.HostnameIs("host") && oSession.url.IndexOf("url_path") > -1){
        // 获取response中的body字符串
        var strBody=oSession.GetResponseBodyAsString();
        // 用正则表达式或者replace方法去修改string
        var regx = '"stream_mode":\d*?'
        strBody=strBody.replace(regx,'"stream_mode":0');
        // 弹个对话框检查下修改后的body               
        FiddlerObject.alert(strBody);
        // 将修改后的body,重新写回Request中
        oSession.utilSetResponseBody(strBody);
    }
在此处修改json中的数据【修改接口字段的值】
    if(oSession.HostnameIs("host") && oSession.url.IndexOf("url_path") > -1){
        // 获取Response Body中JSON字符串
        var responseStringOriginal =  oSession.GetResponseBodyAsString();
        // 转换为可编辑的JSONObject变量
        var responseJSON = Fiddler.WebFormats.JSON.JsonDecode(responseStringOriginal);
        // 修改JSONObject变量,修改字段数据
        responseJSON.JSONObject["new_core"] = "True";  
        responseJSON.JSONObject["stream_mode"] = 5;
        // 重新设置Response Body
        var responseStringDestinal = Fiddler.WebFormats.JSON.JsonEncode(responseJSON.JSONObject);
        oSession.utilSetResponseBody(responseStringDestinal);
	}
在此处修改json中的数据【增加接口字段=值】
    if(oSession.HostnameIs("host") && oSession.url.IndexOf("url_path") > -1){
        // 获取Response Body中JSON字符串
        var responseStringOriginal =  oSession.GetResponseBodyAsString();
        // 转换为可编辑的JSONObject变量
        var responseJSON = Fiddler.WebFormats.JSON.JsonDecode(responseStringOriginal);
        // 修改JSONObject变量,修改字段数据
        responseJSON.JSONObject["type_arr"] = ["bullet"];
        // 重新设置Response Body
        var responseStringDestinal = Fiddler.WebFormats.JSON.JsonEncode(responseJSON.JSONObject);
        oSession.utilSetResponseBody(responseStringDestinal);
        }
使指定URL支持CORS跨域请求有时候,你调用一个 json 接口,发现跨域了,你需要去找接口的开发人支持跨域,显然傻傻等待后端开发完毕再联调是低效率的, 这个时候就就要在后台改完之前就自己实现跨域的模拟,此时 fiddler 显然是再好不过的利器。支要持 CORS 跨域, 就是要为请求的返回头增加 Access-Control-Allow-Origin 属性,因此需要修改 OnBeforeResponse函数,在该函数的末尾添加你的 CORS 逻辑
    static function OnBeforeResponse(oSession: Session) {
        	...

        	if(oSession.uriContains("要处理的url")){
        		oSession.oResponse["Access-Control-Allow-Origin"] =  "允许的域名";
        		oSession.oResponse["Access-Control-Allow-Credentials"] = true;
        	}
    }








oSession常用的相关属性和方法
 // 修改session中的显示样式
 oSession["ui-color"] = "orange";
 // 移除http头部中的MQB-X5-Referer字段
 oSession.oRequest.headers.Remove("MQB-X5-Referer");
 // 修改http头部中的Cache-Control字段
 oSession.oRequest["Cache-Control"] = "no-cache";
 // 修改host
 oSession.host = "example.domain"; 
 // 修改Origin字段
 oSession.oRequest["Origin"] = "http://domain";
 // 删除所有的cookie
 oSession.oRequest.headers.Remove("Cookie");
 // 新建cookie
 oSession.oRequest.headers.Add("Cookie", "username=cookiename;");
 // 修改Referer字段
 oSession.oRequest["Referer"] = "https://yoururl";
 
 // 获取Request中的body字符串
 var strBody=oSession.GetRequestBodyAsString();
 // 用正则表达式或者replace方法去修改string
 strBody=strBody.replace("aaaa","bbbbbb");
 // 将修改后的body,重新写回Request中
 oSession.utilSetRequestBody(strBody);
// 判断连接中是否包含字符串str
oSession.uriContains(str)
// 给连接请求添加一个字段TEST
oSession.oRequest["TEST"]="TEST NEW Request";





可参考
https://github.com/gitjayzhen/FiddlerUseScript