zoukankan      html  css  js  c++  java
  • 【原创】网站抓包HttpWebRequest不返回Javascript生成的Cookie的解决办法

    前言:

    最近在做中国移动爬虫的过程中,首先遇到的就是 在某个请求中,有一个名为“WT_PFC"的cookie键值是由前端JavaScript生成的,没有进入到HttpWebResponse中。事实上,C#不会去执行客户端脚本 ,用到的HttpWebRequest不是一个真正意义上的web浏览器,它只会下载它所请求的地址的html信息,它永远不会去执行JavaScript或者ajax,同时WebClient这个类间接地也是调用了HttpWebRequest来请求的,所以结论是一致的。

    但是由于其他的请求的Request需要Sent该Cookie,所以查了很多资料,基本上只能 重新构建 js 算法 或者使用 WebBrowser自动去执行页面js

    IHTMLWindow2 win = (IHTMLWindow2)webBrowser1.Document.Window.DomWindow;
                string s = @"function confirm() {";
                s += @"return true;";
                s += @"}";
                s += @"function alert() {}";
                win.execScript(s, "javascript");

    , 但这些都不是最好最快的方法。我采用的是以下的

    C# 代码动态编译JavaScript代码的方式得出 JavaScript函数被调用之后的 返回值。

    1.Cookie(WT_FPC):

    2. 通过HttpWatch查到的生成该cookie的js代码,我提炼出了生成该Cookie的方法,并按格式写成如下形式:

    public static function GetWT_FPC(){
         
        var $t = "2";
        var $u = new Date();
        var $v = new Date($u.getTime() + 315360000000);
        var $w = new Date($u.getTime());
         
        if ($t.length < 10) { 
            var $x = $u.getTime().toString();
            for (var i = 2; i <= (32 - $x.length); i++) $t += Math.floor(Math.random() * 16.0).toString(16);
            $t += $x;
        };
        $t = encodeURIComponent($t); 
        return "WT_FPC=id=" + $t + ":lv=" + $u.getTime().toString() + ":ss=" + $w.getTime().toString() ;
        };
    

      请注意:请按以上的格式书写 脚本函数,即加上"public static ". 方法体不用动。

    3.JsHelper(动态编译Js代码):

    我把上面js代码放到本地"WT_FPC.js"文件中

    public static class JsHelper {
    		/// <summary>
    		/// 执行JS方法
    		/// </summary>
    		/// <param name="methodName">方法名</param>
    		/// <param name="para">参数</param>
    		/// <returns></returns>
    		public static string GetJsMethd(string methodName, object[] para) {
    			string path = AppDomain.CurrentDomain.BaseDirectory + "WT_FPC.js";
    			string str2 = File.ReadAllText(path);
    			StringBuilder sb = new StringBuilder();
    			sb.Append("package aa{");    
    			sb.Append(" public class JScript {");
    		
    			sb.Append(str2);
    			sb.Append("}}");
    			  
    
    			CompilerParameters parameters = new CompilerParameters();
    
    			parameters.GenerateInMemory = true;
    
    			CodeDomProvider _provider = new Microsoft.JScript.JScriptCodeProvider();
    
    			CompilerResults results = _provider.CompileAssemblyFromSource(parameters, sb.ToString());
    
    			Assembly assembly = results.CompiledAssembly;
    
    			Type _evaluateType = assembly.GetType("aa.JScript");
    
    			object obj = _evaluateType.InvokeMember("GetWT_FPC", BindingFlags.InvokeMethod,
    			null, null, para);
    
    			return obj.ToString();
    		}
    	}
    

    注意:以上的helper代码如果报错的话,99%都是由于 Js代码的问题,即js代码不规范或者 变量缺少定义之类。

    4. C#代码调用helper获得执行结果

    //设置Cookie"WT_FPC"
    			string wt_fpc = JsHelper.GetJsMethd("GetWT_FPC", null);
    			CookieCollection hcc = new CookieCollection();
    			Cookie wtcookie = new Cookie() {
    				Expires = DateTime.Now.AddYears(10),
    				Path = "/",
    				Domain = ".10086.cn",
    				Name = "WT_FPC", 
    				 Value = wt_fpc.Substring(wt_fpc.IndexOf('=') + 1, wt_fpc.Length - 7)// 
    			};
    			hcc.Add(wtcookie);
    			HttpHelperNew.cookie.Add(wtcookie);
    

      

    5. 小经验: 有时候 JavaScript前端生成的cookie,有时候 服务器端并不 校验,也就是,如果把这个cookie值不通过js代码动态得到,直接 写死的话 也应该可以。

    6. 其他:

    一:如果需要用C#执行前端js 函数计算的结果,比如 前端js的加密结果,在能找到js代码前提下,可以把js写在本地的html 页面里面,然后C#代码去访问 即可。so easy!

    二: Java 中使用WebClient获取js执行完返回的值。

    try{ 
            WebClient webClient = new WebClient(BrowserVersion.FIREFOX_24); 
            //设置webClient的相关参数 
            webClient.getOptions().setJavaScriptEnabled(true); 
            webClient.getOptions().setCssEnabled(false); 
            webClient.setAjaxController(new NicelyResynchronizingAjaxController()); 
            //webClient.getOptions().setTimeout(50000); 
            webClient.getOptions().setThrowExceptionOnScriptError(false); 
            //模拟浏览器打开一个目标网址 
                HtmlPage rootPage= webClient.getPage(url); 
                System.out.println("为了获取js执行的数据 线程开始沉睡等待"); 
                Thread.sleep(3000);//主要是这个线程的等待 因为js加载也是需要时间的 
                System.out.println("线程结束沉睡"); 
                String html = rootPage.asText(); 
                System.out.println(html); 
                }catch(Exception e){ 
                } 
    

      

  • 相关阅读:
    Android端 配置极光推送
    udev的使用-minicom没有权限打开串口,更改 ttyUSB0 的权限
    【Oracle】RAC删除节点
    Linux学习(二) wget命令的使用
    Struts2拦截器
    SpringMVC实战(三种映射处理器)
    rbd_rados命令拷屏
    网络威胁防护,Azure 靠的是它?
    一块钱使用开发测试环境,助你快速打造万圣节促销应用
    想要快速搭建开发测试环境?这么做就可以!
  • 原文地址:https://www.cnblogs.com/x-poior/p/5396353.html
Copyright © 2011-2022 走看看