c#抓取动态页面WebBrowser

时间:2022-09-03 14:50:02

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

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

c#抓取动态页面WebBrowser

从首页加载中我们看到,在页面呈现后,还会有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值即可。

c#抓取动态页面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         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 }
c#抓取动态页面WebBrowser

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

c#抓取动态页面WebBrowser

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

WEBbrowser 是否加载完毕。

c#抓取动态页面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 }
c#抓取动态页面WebBrowser

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

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

c#抓取动态页面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
 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 }

c#抓取动态页面WebBrowser的更多相关文章

  1. 手把手视频:万能开源Hawk抓取动态网站

    Hawk是沙漠之鹰历时五年开发的开源免费网页抓取工具(爬虫),无需编程,全部可视化. 自从上次发布Hawk 2.0过了小半年,可是还是有不少朋友通过邮件或者微信的方式询问如何使用.看文档还是不如视频教 ...

  2. java抓取动态生成的网页

    最近在做项目的时候有一个需求:从网页面抓取数据,要求是首先抓取整个网页的html源码(后期更新要使用到).刚开始一看这个简单,然后就稀里哗啦的敲起了代码(在这之前使用过Hadoop平台的分布式爬虫框架 ...

  3. php抓取ajax页面返回图片。

    要抓取的页面:http://pic.hao123.com/ 当我们往下滚动的时候,图片是用ajax来动态获取的.这就需要我们仔细分析页面了. 可以看到,异步加载的ajax文件为: http://pic ...

  4. C&num;抓取AJAX页面的内容

    原文 C#抓取AJAX页面的内容 现在的网页有相当一部分是采用了AJAX技术,所谓的AJAX技术简单一点讲就是事件驱动吧(当然这种说法可能很不全面),在你提交了URL后,服务器发给你的并不是所有是页面 ...

  5. Chrome &plus; Python 抓取动态网页内容

    用Python实现常规的静态网页抓取时,往往是用urllib2来获取整个HTML页面,然后从HTML文件中逐字查找对应的关键字.如下所示: import urllib2 url="http: ...

  6. selenium抓取动态网页数据

    1.selenium抓取动态网页数据基础介绍 1.1 什么是AJAX AJAX(Asynchronouse JavaScript And XML:异步JavaScript和XML)通过在后台与服务器进 ...

  7. 使用scrapy-selenium&comma; chrome-headless抓取动态网页

        在使用scrapy抓取网页时, 如果遇到使用js动态渲染的页面, 将无法提取到在浏览器中看到的内容. 针对这个问题scrapy官方给出的方案是scrapy-selenium, 这是一个把sel ...

  8. scrapy和selenium结合抓取动态网页

    1.安装python (我用的是2.7版本的) 2.安装scrapy:   详情请参考 http://blog.csdn.net/wukaibo1986/article/details/8167590 ...

  9. 利用curl抓取远程页面内容

    最基本的操作如下 $curlPost = 'a=1&b=2';//模拟POST数据$cookie_file    =    tempnam('./temp','kie');//可选,保存ses ...

随机推荐

  1. ftl文件格式化jsp形式显示

    通过myeclipse设置ftl的编辑器为jsp的编辑器,达到效果. Myeclipse->windows->preferences 1\ 2\ 3\ 完成后即可.

  2. 关于cocos2d这个东西

    我是在今年6月份左右接触到cocos2d这个东西的,当时就是想写个小游戏,结果买书的时候误打误撞就买了cocos2d的书. cocos2d是一个开源的游戏引擎,用于构建2d游戏,同时也可以用它写各种图 ...

  3. Ubuntu 16&period;04 设置MySQL远程访问权限

    本文记录一下在Ubuntu 16.04版本下设置MySQL数据库的远程访问. 第一步:修改配置文件的端口绑定 打开的目录可能会根据MySQL的版本稍有不同,可以先尝试打开/etc/mysql/my.c ...

  4. 在 IDEA中运行 WordCount

    一.新建一个maven项目 二.pom.xml 中内容 <?xml version="1.0" encoding="UTF-8"?> <pro ...

  5. &lbrack;Swift&rsqb;LeetCode21&period; 合并两个有序链表 &vert; Merge Two Sorted Lists

    Merge two sorted linked lists and return it as a new list. The new list should be made by splicing t ...

  6. JS获取客户端IP地址、MAC和主机名的7个方法汇总

    今天在搞JS(javascript)获取客户端IP的小程序,上网搜了下,好多在现在的系统和浏览器中的都无效,很无奈,在Chrome.FireFox中很少搞到直接利用ActiveX获取IP等的JS脚本. ...

  7. R语言中的遗传算法详细解析

    前言 人类总是在生活中摸索规律,把规律总结为经验,再把经验传给后人,让后人发现更多的规规律,每一次知识的传递都是一次进化的过程,最终会形成了人类的智慧.自然界规律,让人类适者生存地活了下来,聪明的科学 ...

  8. jquery使用ajax报错&lbrack;Uncaught SyntaxError&colon; Unexpected token &colon;&rsqb;

    $.post('/ajax/validate.do',{"id": id},function(ret){ //ret }); 返回值明明是json,格式也是正确的,却解析不成功,在 ...

  9. C语言多线程编程二

    一. 线程通信----事件: 1.一对一模式: #include <stdio.h> #include <stdlib.h> #include <Windows.h&gt ...

  10. Arduino可穿戴教程之第一个程序——连接硬件选择板子&lpar;二&rpar;

    Arduino可穿戴教程之第一个程序——连接硬件选择板子(二) 2.4.2  连接硬件 在选择好示例程序后就可以将LilyPad通过LilyPad编程器连接到电脑了. 2.4.3  选择板子 如果你了 ...