-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

相关问题