动态网页抓取(ajax横行的年代,我们的网页是残缺的吗? )

优采云 发布时间: 2021-09-26 12:05

  动态网页抓取(ajax横行的年代,我们的网页是残缺的吗?

)

  在Ajax时代,许多网页的内容都是动态加载的,我们的小爬虫只抓取web服务器返回给我们的HTML

  跳过了JS加载部分,即爬虫抓取的网页不完整、不完整。你可以看到下面博客花园的首页

  

  从主页加载中,我们可以看到页面呈现后,将有五个Ajax异步请求。默认情况下,爬虫程序无法抓取Ajax生成的内容

  此时,如果要获取这些动态页面,必须调用浏览器的内核引擎来下载这些动态页面。目前,内核引擎有三个支柱

  三叉戟:即内核。WebBrowser基于此内核,但其可加载性较差

  壁虎:FF的内核比Trident有更好的性能

  WebKit:Safari和chrome的内核性能,你知道,在真实场景中仍然基于它

  好吧,为了简单和方便,让我们使用WebBrowser来玩。使用WebBrowser时,我们应注意以下几点:

  第一:因为WebBrowser是system.windows.forms中的WinForm控件,所以我们需要设置StatThread标志

  第二:WinForm是事件驱动的,控制台不响应事件。所有事件都在windows的消息队列中等待执行。为了不让程序假装死亡

  我们需要调用Doevents方法来转移控制,并让操作系统执行其他事件

  第三:我们需要使用domdocument而不是documenttext来查看WebBrowser中的内容

  通常有两种方法来判断是否加载了动态网页:

  ① : 在这里设置一个最大值,因为每次异步加载JS时,都会触发导航和documentcompleted事件,所以我们需要

  只需将计数值记录在

  

   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加载的内容是否可用

  

  ② : 当然,除了通过判断最大值来判断加载是否完成外,我们还可以通过设置定时器来判断,如3S、4S、5S等

  是否已加载web浏览器

  

   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 }

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线