好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

抓取动态页面

抓取动态页面

  在ajax横行的年代,很多网页的内容都是动态加载的,而我们的小爬虫抓取的仅仅是web服务器返回给我们的html,这其中就

跳过了js加载的部分,也就是说爬虫抓取的网页是残缺的,不完整的,下面可以看下博客园首页

从首页加载中我们看到,在页面呈现后,还会有5个ajax异步请求,在默认的情况下,爬虫是抓取不到这些ajax生成的内容的,

这时候要想获取就必须调用浏览器的内核引擎来下载这些动态页面,目前内核引擎三足鼎立。

Trident: 也就是IE内核,WebBrowser就是基于该内核,但是加载性内比较差。

Gecko: FF的内核,性能相对Trident较好。

WebKit: Safari和Chrome的内核,性能你懂的,在真实场景中还是以它为主。

好了,为了简单方便,这里使用WebBrowser来玩一把,使用WebBrowser我们要注意以下几点:

第一:因为WebBrowser在System.Windows.Forms 中,属于winform控件,所以我们要设置STAThread标记。

第二:winform是事件驱动的,而Console并不会去响事件,所有事件在windows的消息队列中等待执行,为了不让程序假死,

         我们需要调用DoEvents方法转让控制权,让操作系统执行其他的事件。

第三:WebBrowser中的内容,我们需要用DomDocument来查看,而不是DocumentText。

判断一个动态网页是否加载完毕,一般常会有两种方法:

①:设定一个最大值,因为每当异步加载一个js,都会触发一个Navigating和DocumentCompleted事件,所以我们需要在此

       处记录一下count值即可。

  1   using   System;
   2   using   System.Collections.Generic;
   3   using   System.Linq;
   4   using   System.Text;
   5   using   System.Windows.Forms;
   6   using   System.Threading;
   7   using   System.IO;
   8  
  9   namespace   ConsoleApplication2
  10   {
  11       public   class   Program
  12       {
  13           static   int  hitCount =  0  ;
  14  
 15           [STAThread]
  16           static   void  Main( string  [] args)
  17           {
  18               string  url =  "  http://www.cnblogs.com  "  ;
  19  
 20              WebBrowser browser =  new   WebBrowser();
  21  
 22              browser.ScriptErrorsSuppressed =  true  ;
  23  
 24              browser.Navigating += (sender, e) =>
 25               {
  26                  hitCount++ ;
  27               };
  28  
 29              browser.DocumentCompleted += (sender, e) =>
 30               {
  31                  hitCount++ ;
  32               };
  33  
 34               browser.Navigate(url);
  35  
 36               while  (browser.ReadyState !=  WebBrowserReadyState.Complete)
  37               {
  38                   Application.DoEvents();
  39               }
  40  
 41               while  (hitCount <  16  )
  42                   Application.DoEvents();
  43  
 44               var  htmldocument =  (mshtml.HTMLDocument)browser.Document.DomDocument;
  45  
 46               string  gethtml =  htmldocument.documentElement.outerHTML;
  47  
 48               //  写入文件 
 49               using  (StreamWriter sw =  new  StreamWriter(Environment.CurrentDirectory +  "  //1.html  "  ))
  50               {
  51                   sw.WriteLine(gethtml);
  52               }
  53  
 54              Console.WriteLine( "  html 文件 已经生成!  "  );
  55  
 56               Console.Read();
  57           }
  58       }
  59  }

然后,我们打开生成好的1.html,看看js加载的内容是不是有了。

②: 当然除了通过判断最大值确定是否已经加载完成,我们还可以通过设定一个Timer来判断,比如3s,4s,5s后来查看

      WEBbrowser 是否加载完毕。

  1   using   System;
   2   using   System.Collections.Generic;
   3   using   System.Linq;
   4   using   System.Text;
   5   using   System.Windows.Forms;
   6   using   System.Threading;
   7   using   System.IO;
   8  
  9   namespace   ConsoleApplication2
  10   {
  11       public   class   Program
  12       {
  13           [STAThread]
  14           static   void  Main( string  [] args)
  15           {
  16               string  url =  "  http://www.cnblogs.com  "  ;
  17  
 18              WebBrowser browser =  new   WebBrowser();
  19  
 20              browser.ScriptErrorsSuppressed =  true  ;
  21  
 22               browser.Navigate(url);
  23  
 24               //  先要等待加载完毕 
 25               while  (browser.ReadyState !=  WebBrowserReadyState.Complete)
  26               {
  27                   Application.DoEvents();
  28               }
  29  
 30              System.Timers.Timer timer =  new   System.Timers.Timer();
  31  
 32               var  isComplete =  false  ;
  33  
 34              timer.Elapsed +=  new  System.Timers.ElapsedEventHandler((sender, e) =>
 35               {
  36                   //  加载完毕 
 37                  isComplete =  true  ;
  38  
 39                   timer.Stop();
  40               });
  41  
 42              timer.Interval =  1000  *  5  ;
  43  
 44               timer.Start();
  45  
 46               //  继续等待 5s,等待js加载完 
 47               while  (! isComplete)
  48                   Application.DoEvents();
  49  
 50               var  htmldocument =  (mshtml.HTMLDocument)browser.Document.DomDocument;
  51  
 52               string  gethtml =  htmldocument.documentElement.outerHTML;
  53  
 54               //  写入文件 
 55               using  (StreamWriter sw =  new  StreamWriter(Environment.CurrentDirectory +  "  //1.html  "  ))
  56               {
  57                   sw.WriteLine(gethtml);
  58               }
  59  
 60              Console.WriteLine( "  html 文件 已经生成!  "  );
  61  
 62               Console.Read();
  63           }
  64       }
  65  }

当然,效果依旧,就不截图了,从上面的两种写法来看,我们的WebBrowser都是放在主线程中,下面我们来看看如何放在工作线程上,

很简单,只要将该工作线程设定为STA模式即可。

  1   using   System;
   2   using   System.Collections.Generic;
   3   using   System.Linq;
   4   using   System.Text;
   5   using   System.Windows.Forms;
   6   using   System.Threading;
   7  
  8   namespace   ConsoleApplication2
   9   {
  10       public   class   Program
  11       {
  12           static   int  hitCount =  0  ;
  13  
 14           //  [STAThread] 
 15           static   void  Main( string  [] args)
  16           {
  17              Thread thread =  new  Thread( new  ThreadStart(() =>
 18               {
  19                   Init();
  20                   System.Windows.Forms.Application.Run();
  21               }));
  22  
 23               //  将该工作线程设定为STA模式 
 24               thread.SetApartmentState(ApartmentState.STA);
  25  
 26               thread.Start();
  27  
 28               Console.Read();
  29           }
  30  
 31           static   void   Init()
  32           {
  33               string  url =  "  http://www.cnblogs.com  "  ;
  34  
 35              WebBrowser browser =  new   WebBrowser();
  36  
 37              browser.ScriptErrorsSuppressed =  true  ;
  38  
 39              browser.DocumentCompleted +=  new   WebBrowserDocumentCompletedEventHandler(browser_DocumentCompleted);
  40  
 41              browser.Navigating +=  new   WebBrowserNavigatingEventHandler(browser_Navigating);
  42  
 43               browser.Navigate(url);
  44  
 45               while  (browser.ReadyState !=  WebBrowserReadyState.Complete)
  46               {
  47                   Application.DoEvents();
  48               }
  49  
 50               while  (hitCount <  16  )
  51                   Application.DoEvents();
  52  
 53               var  htmldocument =  (mshtml.HTMLDocument)browser.Document.DomDocument;
  54  
 55               string  gethtml =  htmldocument.documentElement.outerHTML;
  56  
 57               Console.WriteLine(gethtml);
  58           }
  59  
 60           static   void  browser_Navigating( object   sender, WebBrowserNavigatingEventArgs e)
  61           {
  62              hitCount++ ;
  63           }
  64  
 65           static   void  browser_DocumentCompleted( object   sender, WebBrowserDocumentCompletedEventArgs e)
  66           {
  67              hitCount++ ;
  68           }
  69       }
  70  }

跪求程序员二枚,有意向请 查看详情 ,也可与我联系! 如果觉得文章对你有帮助,欢迎在 IT博客大赛中投我一票

分类:  小爬虫系列

作者: Leo_wl

    

出处: http://www.cnblogs.com/Leo_wl/

    

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

版权信息

查看更多关于抓取动态页面的详细内容...

  阅读:36次