如何在 Frames/IFrames 中获取 HtmlElement 值?

Posted

技术标签:

【中文标题】如何在 Frames/IFrames 中获取 HtmlElement 值?【英文标题】:How to get an HtmlElement value inside Frames/IFrames? 【发布时间】:2019-04-12 07:38:16 【问题描述】:

我正在使用Winforms WebBrowser 控件从以下链接的站点收集视频剪辑的链接。

LINK

但是,当我逐个元素滚动时,我找不到<video> 标签。

void webBrowser_DocumentCompleted_2(object sender, WebBrowserDocumentCompletedEventArgs e)

    try
    
        htmlElementCollection pTags = browser.Document.GetElementsByTagName("video");
        int i = 1;
        foreach (HtmlElement link in links)
        

            if (link.Children[0].GetAttribute("className") == "vjs-poster")
            
                try
                

                    i++;
                
                catch (Exception ex)
                
                    MessageBox.Show(ex.Message);
                
            
        
       // Added by edit

使用后不久

HtmlElementCollection pTags = browser.Document.GetElementsByTagName("video");

我已经返回 0

我需要调用任何 ajax 吗?

【问题讨论】:

【参考方案1】:

您链接的网页包含IFrames。 一个IFrame 包含它自己的HtmlDocument。到目前为止,您只解析主 Document 容器。 因此,您需要解析其他一些FrameHtmlElements TAG。 网页框架列表由WebBrowser.Document.Window.Frames 属性引用,该属性返回HtmlWindowCollection。 集合中的每个HtmlWindow 都包含它自己的HtmlDocument 对象。

大多数时候,我们需要解析Frames集合中的每个HtmlWindow.Document,而不是解析WebBrowser返回的Document对象属性;当然,除非我们已经知道所需的元素是主文档的一部分或另一个已知的Frame

一个例子(与当前任务相关):

订阅 WebBrowser 控件/类的DocumentCompleted 事件。 检查WebBrowser.ReadyState 属性以验证文档是否已完全加载。

注意: 请记住,网页可能由 Frames/IFrames 中包含的多个文档组成,如果使用 ReadyState = WebBrowserReadyState.Complete 多次引发该事件,我们不会感到惊讶。 每个 Frame 的 Document 将在 WebBrowser 完成加载时引发事件。

使用Frame.Document.Body.GetElementsByTagName()方法解析Document.Window.Frames集合中每个Frame的HtmlDocument。 使用HtmlElement.GetAttribute方法提取HtmlElementsAttibute

注意: 由于DocumentCompleted 事件被多次引发,我们需要验证HtmlElement 属性值也没有被多次存储。 在这里,我使用了一个支持自定义类,它包含所有收集的值以及每个引用链接的 HashCode(这里依赖于 GetHasCode() 的默认实现)。 每次解析一个 Document 时,我们检查一个值是否已经被存储,比较它的 Hash。

当我们验证找到重复的哈希时停止解析:框架文档元素已被提取。

注意: 在解析HtmlWindowCollection 时,不可避免地会引发一些特定的异常:

    UnauthorizedAccessException: 部分 Frames 无法访问。 InvalidOperationException:某些元素/后代无法访问。

我们无法避免这种情况:元素不是null,当我们尝试访问它们的任何属性时,它们只会抛出这些异常。 在这里,我只是捕捉并忽略了这些特定的异常:我们知道我们最终会得到它们,我们无法避免它,继续前进。

public class MovieLink

    public MovieLink()  
    public int Hash  get; set; 
    public string VideoLink  get; set; 
    public string ImageLink  get; set; 


List<MovieLink> moviesLinks = new List<MovieLink>();

private void Browser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)

    var browser = sender as WebBrowser;
    if (browser.ReadyState != WebBrowserReadyState.Complete) return;

    var documentFrames = browser.Document.Window.Frames;
    foreach (HtmlWindow Frame in documentFrames) 
        try 
            var videoElement = Frame.Document.Body
                .GetElementsByTagName("VIDEO").OfType<HtmlElement>().FirstOrDefault();

            if (videoElement != null) 
                string videoLink = videoElement.Children[0].GetAttribute("src");
                int hash = videoLink.GetHashCode();
                if (moviesLinks.Any(m => m.Hash == hash)) 
                    // Done parsing this URL: remove handler or whatever 
                    // else is planned to move to the next site/page
                    return;
                

                string sourceImage = videoElement.GetAttribute("poster");
                moviesLinks.Add(new MovieLink() 
                    Hash = hash, VideoLink = videoLink, ImageLink = sourceImage
                );
            
        
        catch (UnauthorizedAccessException)   // Cannot be avoided: ignore
        catch (InvalidOperationException)     // Cannot be avoided: ignore
    

【讨论】:

我没有注意到 iframe!你的解释很到位!

以上是关于如何在 Frames/IFrames 中获取 HtmlElement 值?的主要内容,如果未能解决你的问题,请参考以下文章

如何获取 BrowserWindow 的 url?

如何在RowDataBound函数中获取特定列的值?

如何在Angular 7中单击按钮时获取下拉列表的选定选项[重复]

Matlab中如何修改x轴为汉字或字母?Matlab中如何将x轴设定为字母或者其他?

如何在jQuery中获取对具有特定值的表行的引用

当单元格的高度不同时,如何在表格视图中获取所有单元格的高度?