抓取动态网页(横行的年代,性能相对Trident较好的抓取 )

优采云 发布时间: 2021-10-26 12:20

  抓取动态网页(横行的年代,性能相对Trident较好的抓取

)

  您需要登录才能下载或查看,还没有账号?立即注册

  

  x

  楼主今天在博客园看到了这个文章,转载并交流。

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

  记录计数值

  .

  [C#] 纯文本视图复制代码

  using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Windows.Forms;

using System.Threading;

using System.IO;

namespace ConsoleApplication2

{

public class Program

{

static int hitCount = 0;

[STAThread]

static void Main(string[] args)

{

string url = "http://www.cnblogs.com";

WebBrowser browser = new WebBrowser();

browser.ScriptErrorsSuppressed = true;

browser.Navigating += (sender, e) =>

{

hitCount++;

};

browser.DocumentCompleted += (sender, e) =>

{

hitCount++;

};

browser.Navigate(url);

while (browser.ReadyState != WebBrowserReadyState.Complete)

{

Application.DoEvents();

}

while (hitCount < 16)

Application.DoEvents();

var htmldocument = (mshtml.HTMLDocument)browser.Document.DomDocument;

string gethtml = htmldocument.documentElement.outerHTML;

//写入文件

using (StreamWriter sw = new StreamWriter(Environment.CurrentDirectory + "//1.html"))

{

sw.WriteLine(gethtml);

}

Console.WriteLine("html 文件 已经生成!");

Console.Read();

}

}

}

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

  

  ②:当然,除了通过判断最大值来判断加载是否完成,我们也可以通过设置一个Timer来判断,比如3s、4s、5s,然后再检查WEBbrowser是否加载完毕。

  [C#] 纯文本视图复制代码

  using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Windows.Forms;

using System.Threading;

using System.IO;

namespace ConsoleApplication2

{

public class Program

{

[STAThread]

static void Main(string[] args)

{

string url = "http://www.cnblogs.com";

WebBrowser browser = new WebBrowser();

browser.ScriptErrorsSuppressed = true;

browser.Navigate(url);

//先要等待加载完毕

while (browser.ReadyState != WebBrowserReadyState.Complete)

{

Application.DoEvents();

}

System.Timers.Timer timer = new System.Timers.Timer();

var isComplete = false;

timer.Elapsed += new System.Timers.ElapsedEventHandler((sender, e) =>

{

//加载完毕

isComplete = true;

timer.Stop();

});

timer.Interval = 1000 * 5;

timer.Start();

//继续等待 5s,等待js加载完

while (!isComplete)

Application.DoEvents();

var htmldocument = (mshtml.HTMLDocument)browser.Document.DomDocument;

string gethtml = htmldocument.documentElement.outerHTML;

//写入文件

using (StreamWriter sw = new StreamWriter(Environment.CurrentDirectory + "//1.html"))

{

sw.WriteLine(gethtml);

}

Console.WriteLine("html 文件 已经生成!");

Console.Read();

}

}

}

  当然效果还是一样的,就不截图了。从上面两种写法来看,我们的WebBrowser是放在主线程的。让我们看看如何将它放在工作线程上。这很简单。工作线程可以设置为STA模式。

  [C#] 纯文本视图复制代码

  using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Windows.Forms;

using System.Threading;

namespace ConsoleApplication2

{

public class Program

{

static int hitCount = 0;

//[STAThread]

static void Main(string[] args)

{

Thread thread = new Thread(new ThreadStart(() =>

{

Init();

System.Windows.Forms.Application.Run();

}));

//将该工作线程设定为STA模式

thread.SetApartmentState(ApartmentState.STA);

thread.Start();

Console.Read();

}

static void Init()

{

string url = "http://www.cnblogs.com";

WebBrowser browser = new WebBrowser();

browser.ScriptErrorsSuppressed = true;

browser.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(browser_DocumentCompleted);

browser.Navigating += new WebBrowserNavigatingEventHandler(browser_Navigating);

browser.Navigate(url);

while (browser.ReadyState != WebBrowserReadyState.Complete)

{

Application.DoEvents();

}

while (hitCount < 16)

Application.DoEvents();

var htmldocument = (mshtml.HTMLDocument)browser.Document.DomDocument;

string gethtml = htmldocument.documentElement.outerHTML;

Console.WriteLine(gethtml);

}

static void browser_Navigating(object sender, WebBrowserNavigatingEventArgs e)

{

hitCount++;

}

static void browser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)

{

hitCount++;

}

}

}

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线