¿Cómo obtener un valor HtmlElement dentro de Frames/IFrames?

Resuelto Will V asked hace 6 años • 1 respuestas

Estoy usando el Winforms WebBrowsercontrol para recopilar los enlaces de los videoclips del sitio vinculado a continuación.

ENLACE

Pero, cuando me desplazo elemento por elemento, no puedo encontrar la <video>etiqueta.

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
}

Poco después de usar el

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

ya regreso 0

¿Necesito llamar a algún ajax?

Will V avatar Nov 09 '18 01:11 Will V
Aceptado

La página web que vinculó contiene IFrames .
An IFramecontiene su propio HtmlDocument . A partir de ahora, estás analizando solo el contenedor de documentos principal.
Por lo tanto, es necesario analizar las HtmlElementsETIQUETAS de algún otro archivo Frame.
La lista de marcos de páginas web hace referencia a la propiedad WebBrowser.Document.Window.Frames , que devuelve un HtmlWindowCollection .
Cada HtmlWindow de la colección contiene su propio HtmlDocumentobjeto.

En lugar de analizar la Documentpropiedad del objeto devuelta por a WebBrowser, la mayoría de las veces necesitamos analizar cada uno de los miembros HtmlWindow.Documentde la Framescolección; a menos, por supuesto, que ya sepamos que los Elementos requeridos son parte del Documento principal u otro conocido Frame.

Un ejemplo (relacionado con la tarea actual):

  • Suscríbase al evento DocumentCompleted del control/clase WebBrowser.
  • Verifique la propiedad WebBrowser.ReadyState para verificar que un documento esté completamente cargado.

Nota:
Recordando que una página web puede estar compuesta por múltiples documentos contenidos en marcos/IFrames, no nos sorprenderá si el evento se genera varias veces con un archivo ReadyState = WebBrowserReadyState.Complete.
Cada fotograma Documentgenerará el evento cuando WebBrowsertermine de cargarlo.

  • Analice HtmlDocumentcada marco de la Document.Window.Framescolección utilizando el método Frame.Document.Body.GetElementsByTagName() .
  • Extraiga HtmlElements Attibuteutilizando el método HtmlElement.GetAttribute .

Nota:
Dado que el DocumentCompletedevento se genera varias veces, también debemos verificar que un HtmlElementvalor de atributo no se almacene varias veces.
Aquí, estoy usando una clase personalizada de soporte que contiene todos los valores recopilados junto con el HashCode de cada enlace de referencia (aquí, confiando en la implementación predeterminada de GetHasCode()).
Cada vez que se analiza un Documento, comprobamos si ya se ha almacenado un valor, comparando su Hash.

  • Detenga el análisis cuando verifiquemos que se ha encontrado un Hash duplicado: los elementos del documento del marco ya se han extraído.

Nota :
Al analizar el archivo HtmlWindowCollection, es inevitable generar algunas excepciones específicas:

  1. UnauthorizedAccessException : no se puede acceder a algunos marcos.
  2. InvalidOperationException : no se puede acceder a algunos elementos/descendientes.

No hay nada que podamos hacer para evitar esto: los Elementos no lo son null, simplemente lanzan estas excepciones cuando intentamos acceder a cualquiera de sus propiedades.
Aquí, simplemente estoy captando e ignorando estas Excepciones específicas: sabemos que eventualmente las obtendremos, no podemos evitarlo, sigamos adelante.

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
    }
}
Jimi avatar Nov 09 '2018 00:11 Jimi