c#抓取动态页面WebBrowser
在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 }
c#抓取动态页面WebBrowser的更多相关文章
- 手把手视频:万能开源Hawk抓取动态网站
Hawk是沙漠之鹰历时五年开发的开源免费网页抓取工具(爬虫),无需编程,全部可视化. 自从上次发布Hawk 2.0过了小半年,可是还是有不少朋友通过邮件或者微信的方式询问如何使用.看文档还是不如视频教 ...
- java抓取动态生成的网页
最近在做项目的时候有一个需求:从网页面抓取数据,要求是首先抓取整个网页的html源码(后期更新要使用到).刚开始一看这个简单,然后就稀里哗啦的敲起了代码(在这之前使用过Hadoop平台的分布式爬虫框架 ...
- php抓取ajax页面返回图片。
要抓取的页面:http://pic.hao123.com/ 当我们往下滚动的时候,图片是用ajax来动态获取的.这就需要我们仔细分析页面了. 可以看到,异步加载的ajax文件为: http://pic ...
- C#抓取AJAX页面的内容
原文 C#抓取AJAX页面的内容 现在的网页有相当一部分是采用了AJAX技术,所谓的AJAX技术简单一点讲就是事件驱动吧(当然这种说法可能很不全面),在你提交了URL后,服务器发给你的并不是所有是页面 ...
- Chrome + Python 抓取动态网页内容
用Python实现常规的静态网页抓取时,往往是用urllib2来获取整个HTML页面,然后从HTML文件中逐字查找对应的关键字.如下所示: import urllib2 url="http: ...
- selenium抓取动态网页数据
1.selenium抓取动态网页数据基础介绍 1.1 什么是AJAX AJAX(Asynchronouse JavaScript And XML:异步JavaScript和XML)通过在后台与服务器进 ...
- 使用scrapy-selenium, chrome-headless抓取动态网页
在使用scrapy抓取网页时, 如果遇到使用js动态渲染的页面, 将无法提取到在浏览器中看到的内容. 针对这个问题scrapy官方给出的方案是scrapy-selenium, 这是一个把sel ...
- scrapy和selenium结合抓取动态网页
1.安装python (我用的是2.7版本的) 2.安装scrapy: 详情请参考 http://blog.csdn.net/wukaibo1986/article/details/8167590 ...
- 利用curl抓取远程页面内容
最基本的操作如下 $curlPost = 'a=1&b=2';//模拟POST数据$cookie_file = tempnam('./temp','kie');//可选,保存ses ...
随机推荐
- 环保创业的可行之道——Leo鉴书上66
近2年,我一直在关注不同企业的发展历程,国内的国外的.看他们成功其中的共性与特性.<蚯蚓创业记>无疑给我开了扇窗--环保企业的怎样发展与壮大.读者还能从书里读出普通年轻人坚持自己梦想最终得 ...
- Jquery文本框小例(必填框)
<script src="../JavaScript/jquery-2.0.2.min.js"></script> <script type=&quo ...
- 树状DP
紫皮,各种,非原创 树状数组在我的理解就是在决策过程中具有层次关系,像是树一样,具有上下级关系或者上级对上级一定程度的限制条件 uva 12186 工人的请愿书 下属中不小于 T% 的人签字时会签字递 ...
- css3 animation动画事件
当使用css3时,会遇到利用@keyframes来定义动画事件,利用以下3个事件,能够捕捉当前元素的动画: AnimationEnd //动画结束时 AnimationStart //动画開始 An ...
- CSDN头版头条 《近匠》 Wijmo 5 CTO:从Web到移动,我的25年编程生涯
现年52岁的Bernardo Castilho先生是GrapeCity(中文名为葡萄城)ComponentOne公司的CTO,在与他的对话过程中.充满风趣严谨和厚重的历史感. 当作为年轻人的我们崇拜着 ...
- linux安装Tesseract-OCR
安装Tesseract-OCR 1. leptonica 需要源码编译安装http://www.leptonica.org/ leptonica 包: leptonica-1.73.tar.gz 解 ...
- NetBeans + Xdebug 调试WordPress
用NetBeans进行WordPress的相关开发和定制很顺手,配合Xdebug后调试起来也很方便. 详细配置过程如下(本例中Xampp安装目录为D:\xampp): 1: 下载xdebug(版本需匹 ...
- Linux系统基础命令
这是看itercast的学习笔记 Linux系统基础命令 日期时间 命令date用以查看.设置当前系统时间:格式化显示时间: +%Y--%m--%d 命令hwclock(clock)用以显示硬件时钟时 ...
- sofa-pbrpc 1.1.1 发布,RPC 网络通信库
https://www.oschina.net/news/77372/sofa-pbrpc-1-1-1 https://www.oschina.net/p/sofa-pbrpc
- js获取上传文件的绝对路径
在html中 <input type="file" id="importFile" /> <input type="bu ...