我們在做採集軟體的時候
有些網站通過直接分析html文本是很麻煩的事情
在利用WinForm編程的情況下
有一種更好的方式當然是分析HtmlDocument
然而,這HtmlDoucment並不能直接建立
它必須由 WebBroswer控制項Navigate產生一個頁面後
才能取得wb.HtmlDocument
然後就可以對HtmlDocument的各元素、標籤進行分析。
事實上,在採集的時候
並不是採集只會採集單個頁面
這樣的話,在主表單中就可以完成
譬如採集一些列表頁面,有N多個頁
那麼,一個迴圈下去,
用WebBrowser去響應,那就會導致假死
這時候,我們肯定會想到用多線程去做這件事情
C#的多線程,
大家應該都知道,有STA,MTA兩種模式
然而,WebBrowser控制項卻有一個不好的特點
那就是:它只支援多線程STA模式
例如下面的代碼,
Thread tread = new Thread(new ParameterizedThreadStart(BeginCatch));
tread.SetApartmentState(ApartmentState.STA);
tread.Start(url);
private void BeginCatch(object obj)
{
string url = obj.ToString();
WebBrowser wb = new WebBrowser();
wb.ScriptErrorsSuppressed = true;
wb.Navigate(url);
wb.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(wb_DocumentCompleted);
}
需要分析WebBrowser產生 的HtmlDocument時,必須在事件DocumentCompleted裡面去操作
只有這時候,WebBrowser才算載入完成
不過,這隻是一個陷阱!!!!
WebBrowser有一個特性,那就是在多線程STA的時候,根本就不等到DocumentCompleted的執行
也就是無法再進行後面的操作!!!
這樣的話,我們該如何辦呢?
也許有人會想:wb.Document.Write(string)方法,如下:
private void BeginCatch(object obj)
{
string url = obj.ToString();
WebBrowser wb = new WebBrowser();
wb.ScriptErrorsSuppressed = true;
string htmlcode = GetHtmlSource(url);
wb.Document.Write(htmlcode);
//執行分析操作
}
//WebClient取網頁源碼
private string GetHtmlSource(string Url)
{
string text1 = "";
try
{
System.Net.WebClient wc = new WebClient();
text1 = wc.DownloadString(Url);
}
catch (Exception exception1)
{}
return text1;
}
但這時候,我們會發現,wb.DocumentText總是沒有的
當時我也很鬱悶,搜尋園子裡的文章與MSDN,都是可以用DocumentText賦值的
但也在網上發現了很多說操作後沒有結果的
經過努力搜尋
在園子裡發現了一篇有用的文章裡提到的一個例子
經過測試後發現
WebBrowser必須經過Navigate後才會產生Document
於是忽,終於可以實現了多線程下面的操作了
最終代碼如下
private void ThreadWebBrowser(string url)
{
Thread tread = new Thread(new ParameterizedThreadStart(BeginCatch));
tread.SetApartmentState(ApartmentState.STA);
tread.Start(url);
}
private void BeginCatch(object obj)
{
string url = obj.ToString();
WebBrowser wb = new WebBrowser();
wb.ScriptErrorsSuppressed = true;
//在這裡Navigate一個空白頁面
wb.Navigate("about:blank");
string htmlcode = GetHtmlSource(url);
wb.Document.Write(htmlcode);
//執行分析操作 ……(略)
}
//WebClient取網頁源碼
private string GetHtmlSource(string Url)
{
string text1 = "";
try
{
System.Net.WebClient wc = new WebClient();
text1 = wc.DownloadString(Url);
}
catch (Exception exception1)
{}
return text1;
}
當然,線上程裡面處理每個結點與資料庫操作的時候,可以用ThreadPool
這樣效果與效能可能好一些
希望此文對有大家有所協助~:)