【问题标题】:How to get an HtmlElement value inside Frames/IFrames?如何在 Frames/IFrames 中获取 HtmlElement 值?
【发布时间】: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 吗?

【问题讨论】:

    标签: c# .net winforms webbrowser-control


    【解决方案1】:

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

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

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

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

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

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

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

    1. UnauthorizedAccessException: 部分 Frames 无法访问。
    2. 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!你的解释很到位!
    猜你喜欢
    • 2011-02-05
    • 1970-01-01
    • 2017-10-16
    • 2011-02-25
    • 2021-08-03
    • 1970-01-01
    • 2014-12-05
    • 2012-04-01
    • 2016-12-11
    相关资源
    最近更新 更多