c# - 如何获取 Frames/IFrames 中的 HtmlElement 值?

标签 c# .net winforms webbrowser-control

我正在使用 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 吗?

最佳答案

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

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

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

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

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

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

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

  1. UnauthorizedAccessException : 无法访问某些框架。
  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
    }
}

关于c# - 如何获取 Frames/IFrames 中的 HtmlElement 值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53213782/

相关文章:

c# - 下载文件错误: Cannot convert type

c# - 为什么本地化不起作用

c# - ApplicationDeployment.CheckForUpdateAsync 方法处理异常

c# - 在 C# 中验证使用 BER/DER 编码的 ASN.1 格式的 DSA 签名

c# - 是否可以有一个也适用于其他项目的扩展类?

c# - 如何使用复选框控制 DataGridView 中所选项目的顺序?

c# - 如何动态获取文本框中datagridview列的总和

c# - 使用线程安全更新单例的属性

C#如何判断excel文件版本

c# - 如何在外部类中引用字符串 (C#)