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

优采云 发布时间: 2022-03-24 01:20

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

)

  在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事件,所以我们这里需要这样做

  记录计数值

  .

  

   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,稍后再查看

  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人工客服


线