2016-04-21 78 views
4

序言WebBrowser控件中獲取子錨點元素

我使用WebBrowser控制,其用戶將與互動,所以解決方案將需要用可見WebBrowser控制工作。

問題

如何檢查元素是否有一個錨作爲一個孩子?所有瀏覽器都可以區分一個元素包含錨點(<a href=""...),並提供「在新選項卡中打開」功能。這正是我試圖複製的內容。但是,當我右鍵點擊一個HtmlElement我只能夠獲得父元素。

以BBC網站作爲一個例子,當我右擊突出顯示的元素上(下圖),我的輸出是DIV,但觀察源代碼有一個錨元件作爲子這div

bbc homepage example

SSCCE

using System; 
using System.Diagnostics; 
using System.Windows.Forms; 

namespace BrowserLinkClick 
{ 
    public partial class Form1 : Form 
    { 
     private WebBrowser wb; 
     private bool firstLoad = true; 

     public Form1() 
     { 
      InitializeComponent(); 
     } 

     private void Form1_Load(object sender, EventArgs e) 
     { 
      wb = new WebBrowser(); 
      wb.Dock = DockStyle.Fill; 
      Controls.Add(wb); 
      wb.Navigate("http://bbc.co.uk"); 
      wb.DocumentCompleted += wb_DocumentCompleted; 
     } 

     private void Document_MouseDown(object sender, HtmlElementEventArgs e) 
     { 
      if (e.MouseButtonsPressed == MouseButtons.Right) 
      { 
       HtmlElement element = wb.Document.GetElementFromPoint(PointToClient(MousePosition)); 
       //I assume I need to check if this element has child elements that contain a TagName "A" 
       if (element.TagName == "A") 
        Debug.WriteLine("Get link location, open in new tab."); 
       else 
        Debug.WriteLine(element.TagName); 
      } 
     } 


     private void wb_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e) 
     { 
      if (firstLoad) 
      { 
       wb.Document.MouseDown += new HtmlElementEventHandler(Document_MouseDown); 
       firstLoad = false; 
      } 
     } 

    } 
} 

請使用測試在BBC網站和突出標題任何建議的解決方案(標題的變化,但DOM保持不變)。

回答

2

你必須檢查,如果它是一個錨之前得到的element子元素:

HtmlElement element = wb.Document.GetElementFromPoint(PointToClient(MousePosition)); 
foreach (HtmlElement child in element.Children) 
{ 
    if (child.TagName == "A") 
     Debug.WriteLine("Get link location, open in new tab."); 
} 
+0

不幸的是,這仍然沒有返回我的例子'a'標籤。你可以嘗試從我的原始帖子的BBC例子,看看是否是你的情況?新聞項目已更改,但DOM結構保持不變。 – TEK

2

要訪問您需要的HtmlElement投射到非託管MSHTML接口之一所需要的性能,例如IHTMLAnchorElement

您必須添加Microsoft HTML Object Library COM參考到您的項目。
(文件名是mshtml.tlb)。

foreach (HtmlElement child in element.Children) 
{ 
    if (String.Equals(child.TagName, "a", StringComparison.OrdinalIgnoreCase)) 
    { 
     var anchorElement = (mshtml.IHTMLAnchorElement)child.DomElement; 
     Console.WriteLine("href: [{0}]", anchorElement.href); 
    } 
} 

有很多這樣的接口,但MSDN將幫助您選擇。 :)

Scripting Object Interfaces (MSHTML)

+0

可悲的是,這仍然沒有爲我的例子返回'a'標籤。你可以嘗試從我的原始帖子的BBC例子,看看是否是你的情況?新聞項目已更改,但DOM結構保持不變。 – TEK

+0

您可以使用遞歸方法檢查是否有任何'HtmlElement.Children'是'mshtml.IHtmlAnchorElement';如果沒有,則將當前元素設置爲其父元素並遞歸調用相同的方法(當然,您應該跳過已經檢查過的元素)。 – Gabor

2

我建議你以下解決方案:
url變量將所需輸出的URL,你就可以看到它在調試器窗口。

private void Document_MouseDown(object sender, HtmlElementEventArgs e) 
{ 
     if (e.MouseButtonsPressed == MouseButtons.Right) 
     { 
      HtmlElement element = wb.Document.GetElementFromPoint(PointToClient(MousePosition)); 
      //I assume I need to check if this element has child elements that contain a TagName "A" 
      if (element.TagName == "A") 
      { 
       Debug.WriteLine("Get link location, open in new tab."); 
       var urlRaw = element.OuterHtml; 
       string hrefBegin = "href="; 
       var idxHref = urlRaw.IndexOf(hrefBegin) + hrefBegin.Length + 1; 
       var idxEnd = urlRaw.IndexOf("\"", idxHref + 1); 
       var url = urlRaw.Substring(idxHref, idxEnd - idxHref); 
       Debug.WriteLine(url); 
      } 

      else 
       Debug.WriteLine(element.TagName); 
     } 
    } 
+0

@TEK有幫助嗎? –

+0

解析來自錨點的URL不是問題,而是在它是其他元素的子元素時獲取錨點標記(是的,解析鏈接是未來的問題,但我甚至無法獲得錨點)。使用我的原始文章中的BBC主頁,你會發現我無法找到一個錨點,當右鍵點擊其中的一個標題。然而,具有默認上下文菜單的'WebBrowser'控件可以區分是否存在錨點,以及其他Web瀏覽器。 – TEK

+0

你認爲什麼是主播?父標籤或兄弟標籤?你能提供一些你期望輸出的例子嗎? –

2

您的程序必須有其他錯誤。在BBC網站上,您的代碼適用於新聞文章(儘管我看到非英國版本的網站)。在其他地方有錨元素作爲子網站下面的代碼工作

private void Document_MouseDown(object sender, HtmlElementEventArgs e) 
    { 
     if (e.MouseButtonsPressed == MouseButtons.Right) 
     { 
      HtmlElement element = wb.Document.GetElementFromPoint(PointToClient(MousePosition)); 
      if (element.Children.Count > 0) 
      { 
       foreach (HtmlElement child in element.Children) 
       { 
        if (child.TagName == "A") 
         Debug.WriteLine("Get link location, open in new tab."); 
       } 
      } 
      else 
      { 
       //I assume I need to check if this element has child elements that contain a TagName "A" 
       if (element.TagName == "A") 
        Debug.WriteLine("Get link location, open in new tab."); 
       else 
        Debug.WriteLine(element.TagName); 
      } 
     } 
    } 
+0

我在原貼中發佈的代碼是我迄今爲止提供的這些解決方案的測試程序。爲了澄清,您可以右鍵單擊由示例圖像中的紅色框突出顯示的新聞項目(新聞項目已更改,DOM尚未更改),並且您可以獲取調試輸出「獲取鏈接位置,在新標籤頁中打開。「?,因爲根據我點擊那個新聞項目(元素)的位置,我所得到的只是'DIV'或'SPAN'。 你能發佈你右鍵點擊和輸出的屏幕截圖嗎? – TEK

+0

是的,您的代碼僅適用於BBC。但是,英國版本可能不同。無論我點擊它,我都會獲得錨標記。這是一張圖片:http://imgur.com/4uAB04p。我試圖在錨點位於標題標記後面的其他站點上面的代碼工作。 –

+0

感謝您發佈圖片......我開始覺得我瘋了!那真的是最令人費解的。這只是不顯示這些新聞項目的標記名爲「A」的元素。 :/ – TEK

1

與英國廣播公司網站上的挑戰,它必須對他們的網址有點不標準的方法。 下面去了A HREF的樣本之一:

<A tabIndex=-1 aria-hidden=true class=block-link__overlay-link href="http://www.bbc.com/news/world-africa-36132482" rev=hero5|overlay>Barbie challenges the 'white saviour complex' </A> 

所以,你需要,如果使用兩個部分:
1. element.TagName == 「A」 2.檢查屬性href的這:element.GetAttribute(「href」)

這兩個檢查可以爲您提供擔保,您可以使用標記a處理某些內容,並且該標記a具有屬性href。看另一個用法的例子:

private void Document_MouseDown(object sender, HtmlElementEventArgs e) 
    { 
     if (e.MouseButtonsPressed == MouseButtons.Right) 
     { 
      HtmlElement element = wb.Document.GetElementFromPoint(PointToClient(MousePosition)); 
      //I assume I need to check if this element has child elements that contain a TagName "A" 
      if (element.TagName == "A" && !string.IsNullOrEmpty(element.GetAttribute("href")))//it means we have deal with href 
      { 
       Debug.WriteLine("Get link location, open in new tab."); 
       var url = element.GetAttribute("href"); 
       Debug.WriteLine(url); 
      } 

      else 
       Debug.WriteLine(element.TagName); 
     } 
    } 
+0

我真的很感謝你的繼續努力,但根據我在哪個特定的新聞標題元素上右鍵單擊,它會輸出'DIV'或'SPAN',我根本無法獲得子錨('A')元素。事實上,我現在觀察到的是,如果錨點是來自* any *網站的任何*元素的孩子,我無法訪問它。我的'WebBrowser'控件沒有被修飾過,我使用我發佈的簡單樣本作爲發佈的任何解決方案的基礎,所以我不完全確定發生了什麼。 – TEK