-1

幾天來,我正在研究基於WebBrowser的webscraper。在使用Threads和DocumentCompleted事件的幾個原型之後,我決定嘗試看看我能否做出一個簡單易懂的Webscraper。WebBrowser控件拋出看似隨機NullReferenceException

目標是創建一個不涉及實際線程對象的WebScraper。我希望它能夠以連續的步驟工作(即轉到網址,執行操作,轉到其他網址等)。

這是我走到這一步:

public static class Webscraper 
{ 
    private static WebBrowser _wb; 
    public static string URL; 

    //WebBrowser objects have to run in Single Thread Appartment for some reason. 
    [STAThread] 
    public static void Init_Browser() 
    { 
     _wb = new WebBrowser(); 
    } 


    public static void Navigate_And_Wait(string url) 
    { 
     //Navigate to a specific url. 
     _wb.Navigate(url); 

     //Wait till the url is loaded. 
     while (_wb.IsBusy) ; 

     //Loop until current url == target url. (In case a website loads urls in steps) 
     while (!_wb.Url.ToString().Contains(url)) 
     { 
      //Wait till next url is loaded 
      while (_wb.IsBusy) ; 
     } 

     //Place URL 
     URL = _wb.Url.ToString(); 
    } 
} 

我是新手程序員,但我認爲這是非常簡單的代碼。 這就是爲什麼我討厭,由於某種原因該計劃在這段代碼引發的NullReferenceException的事實:

_wb.Url.ToString().Contains(url) 

我只是叫_wb.Navigate()方法,因此NullReference不能在_wb對象本身。所以我能想象的唯一事情就是_wb.Url對象爲null。但_wb.IsBusy()循環應該阻止這一點。

那麼發生了什麼,我該如何解決?

回答

1

最有可能的地址並沒有被設定,你可以嘗試:

//Loop until current url == target url. (In case a website loads urls in steps) 
    //while (!_wb.Url.ToString().Contains(url)) 
    while (_wb.Url == null || !_wb.Url.ToString().Contains(url)) 
    { 
     //Wait till next url is loaded 
     while (_wb.IsBusy) ; 
    } 

但它仍然沒有真正的同步片狀的解決方案,可能有其他問題。

是不是有Loaded或「Navigated」事件,你可以處理?

4

在UI線程上忙於等待(while (_wb.IsBusy) ;)不是很明智。如果您使用的新功能.NET 4.5的async/await你可以得到類似的效果(即去URL,執行行動,去別的網址等等,等等)你想

public static class SOExtensions 
{ 
    public static Task NavigateAsync(this WebBrowser wb, string url) 
    { 
     TaskCompletionSource<object> tcs = new TaskCompletionSource<object>(); 
     WebBrowserDocumentCompletedEventHandler completedEvent = null; 
     completedEvent = (sender, e) => 
     { 
      wb.DocumentCompleted -= completedEvent; 
      tcs.SetResult(null); 
     }; 
     wb.DocumentCompleted += completedEvent; 

     wb.ScriptErrorsSuppressed = true; 
     wb.Navigate(url); 

     return tcs.Task; 
    } 
} 



async void ProcessButtonClick() 
{ 
    await webBrowser1.NavigateAsync("http://www.stackoverflow.com"); 
    MessageBox.Show(webBrowser1.DocumentTitle); 

    await webBrowser1.NavigateAsync("http://www.google.com"); 
    MessageBox.Show(webBrowser1.DocumentTitle); 
} 
+0

在我用的那一刻.Net 4.0,但這看起來像是我需要的東西。 – Jordy 2013-04-25 07:09:05

相關問題