为了账号安全,请及时绑定邮箱和手机立即绑定

玩玩小爬虫——抓取动态页面

标签:
资讯

 

       在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 ConsoleApplication210 {11     public class Program12     {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 ConsoleApplication210 {11     public class Program12     {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 Program11     {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 }

复制代码

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消