2016-10-15 34 views
2

我需要在類庫中創建一個方法來獲取URL(可以由JavaScript動態填充)的內容。在類庫中使用WebBrowser進行網頁抓取

我一無所知,但有谷歌上搜索了整整一天,這是我想出了:(大部分的代碼是從here

using System; 
using System.Threading.Tasks; 
using System.Threading; 
using System.Windows.Forms; 

public static class WebScraper 
{ 
    [STAThread] 
    public async static Task<string> LoadDynamicPage(string url, CancellationToken token) 
    { 
     using (WebBrowser webBrowser = new WebBrowser()) 
     { 
      // Navigate and await DocumentCompleted 
      var tcs = new TaskCompletionSource<bool>(); 
      WebBrowserDocumentCompletedEventHandler onDocumentComplete = (s, arg) => tcs.TrySetResult(true); 

      using (token.Register(() => tcs.TrySetCanceled(), useSynchronizationContext: true)) 
      { 
       webBrowser.DocumentCompleted += onDocumentComplete; 
       try 
       { 
        webBrowser.Navigate(url); 
        await tcs.Task; // wait for DocumentCompleted 
       } 
       finally 
       { 
        webBrowser.DocumentCompleted -= onDocumentComplete; 
       } 
      } 

      // get the root element 
      var documentElement = webBrowser.Document.GetElementsByTagName("html")[0]; 

      // poll the current HTML for changes asynchronosly 
      var html = documentElement.OuterHtml; 
      while (true) 
      { 
       // wait asynchronously, this will throw if cancellation requested 
       await Task.Delay(500, token); 

       // continue polling if the WebBrowser is still busy 
       if (webBrowser.IsBusy) 
        continue; 

       var htmlNow = documentElement.OuterHtml; 
       if (html == htmlNow) 
        break; // no changes detected, end the poll loop 

       html = htmlNow; 
      } 

      // consider the page fully rendered 
      token.ThrowIfCancellationRequested(); 
      return html; 
     } 
    } 
} 

目前,它拋出這個錯誤

ActiveX控件'8856f961-340a-11d0-a96b-00c04fd705a2'不能被 實例化,因爲當前線程不在單線程的 公寓中。

我關閉了嗎?有沒有解決上述問題?

或者如果我不在軌道上,是否有現成的解決方案來使用.NET(可以從類庫中調用)獲取動態Web內容?

回答

1

這是我在Web應用程序中測試並正常工作的。

它採用了WebBrowser控制在另一個線程,並返回一個包含Task<string>當瀏覽器的內容完全載入其中完成:

using System; 
using System.Threading.Tasks; 
using System.Threading; 
using System.Windows.Forms; 
public class BrowserBasedWebScraper 
{ 
    public static Task<string> LoadUrl(string url) 
    { 
     var tcs = new TaskCompletionSource<string>(); 
     Thread thread = new Thread(() => { 
      try { 
       Func<string> f =() => { 
        using (WebBrowser browser = new WebBrowser()) 
        { 
         browser.ScriptErrorsSuppressed = true; 
         browser.Navigate(url); 
         while (browser.ReadyState != WebBrowserReadyState.Complete) 
         { 
          System.Windows.Forms.Application.DoEvents(); 
         } 
         return browser.DocumentText; 
        } 
       }; 
       tcs.SetResult(f()); 
      } 
      catch (Exception e) { 
       tcs.SetException(e); 
      } 
     }); 
     thread.SetApartmentState(ApartmentState.STA); 
     thread.IsBackground = true; 
     thread.Start(); 
     return tcs.Task; 
    } 
} 
+0

謝謝!它不適用於https://www.google.com/#q=where+am+i,但它可能足以滿足我現在需要的 – Aximili

+1

不客氣。關於另一個問題,我想這是因爲WebBrowser控件默認不會使用最新版本的瀏覽器。你可以強制它使用最新版本。我爲Windows窗體應用程序應用了[解決方案](http://stackoverflow.com/a/38514446/3110834)。 –