¿Cómo obtener un valor HtmlElement dentro de Frames/IFrames?
Estoy usando el Winforms
WebBrowser
control 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?
La página web que vinculó contiene IFrames .
An IFrame
contiene su propio HtmlDocument . A partir de ahora, estás analizando solo el contenedor de documentos principal.
Por lo tanto, es necesario analizar las HtmlElements
ETIQUETAS 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 HtmlDocument
objeto.
En lugar de analizar la Document
propiedad del objeto devuelta por a WebBrowser
, la mayoría de las veces necesitamos analizar cada uno de los miembros HtmlWindow.Document
de la Frames
colecció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 Document
generará el evento cuando WebBrowser
termine de cargarlo.
- Analice
HtmlDocument
cada marco de laDocument.Window.Frames
colección utilizando el método Frame.Document.Body.GetElementsByTagName() . - Extraiga
HtmlElements
Attibute
utilizando el método HtmlElement.GetAttribute .
Nota:
Dado que el DocumentCompleted
evento se genera varias veces, también debemos verificar que un HtmlElement
valor 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:
- UnauthorizedAccessException : no se puede acceder a algunos marcos.
- 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
}
}