Come ottenere un valore HtmlElement all'interno di Frames / IFrames?
Sto utilizzando il Winforms WebBrowsercontrollo per raccogliere i collegamenti dei video clip dal sito collegato di seguito.
Ma, quando scorro elemento per elemento, non riesco a trovare il <video>tag.
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
}
Subito dopo aver utilizzato il
HtmlElementCollection pTags = browser.Document.GetElementsByTagName("video");
Ho già restituito 0
Devo chiamare qualche ajax?
Risposte
La pagina Web collegata contiene IFrame .
An IFramecontiene il proprio HtmlDocument . A partire da ora, stai analizzando solo il contenitore di documenti principale.
Pertanto, è necessario analizzare i HtmlElementsTAG di altri Frame.
L'elenco dei frame delle pagine Web fa riferimento alla proprietà WebBrowser.Document.Window.Frames , che restituisce un HtmlWindowCollection .
Ogni HtmlWindow nella raccolta contiene il proprio HtmlDocumentoggetto.
Invece di analizzare la Documentproprietà dell'oggetto restituita da a WebBrowser, noi, la maggior parte delle volte, abbiamo bisogno di analizzare ciascuna HtmlWindow.Documentnella Framesraccolta; a meno che, ovviamente, non sappiamo già che gli Elementi richiesti fanno parte del Documento principale o di un altro noto Frame.
Un esempio (relativo all'attività corrente):
- Sottoscrivi l' evento DocumentCompleted del controllo / classe WebBrowser.
- Controllare la proprietà WebBrowser.ReadyState per verificare che un documento sia caricato completamente.
Nota:
ricordando che una pagina Web può essere composta da più documenti contenuti in Frames / IFrame, non saremo sorpresi se l'evento viene generato più volte con un ReadyState = WebBrowserReadyState.Complete.
Ogni Frame Documentsolleverà l'evento al WebBrowsertermine del caricamento.
- Analizza
HtmlDocumentogni Frame nellaDocument.Window.Framesraccolta, utilizzando il metodo Frame.Document.Body.GetElementsByTagName () . - Estrarre il
HtmlElementsAttibuteutilizzando il metodo HtmlElement.GetAttribute .
Nota:
poiché l' DocumentCompletedevento viene generato più volte, è necessario verificare che anche un HtmlElementvalore di attributo non venga memorizzato più volte.
Qui, sto usando una classe personalizzata di supporto che contiene tutti i valori raccolti insieme all'HashCode di ogni collegamento di riferimento (qui, basandosi sull'implementazione predefinita di GetHasCode()).
Ogni volta che un documento viene analizzato, controlliamo se un valore è già stato memorizzato, confrontando il suo hash.
- Interrompi l'analisi quando verifichiamo che è stato trovato un hash duplicato: gli elementi del documento Frame sono già stati estratti.
Nota :
durante l'analisi di HtmlWindowCollection, è inevitabile sollevare alcune eccezioni specifiche:
- UnauthorizedAccessException : non è possibile accedere ad alcuni frame.
- InvalidOperationException : alcuni elementi / discendenti non sono accessibili.
Non c'è niente che possiamo fare per evitarlo: gli Elementi non lo sono null, semplicemente generano queste eccezioni quando proviamo ad accedere a una qualsiasi delle loro proprietà.
Qui, sto solo catturando e ignorando queste eccezioni specifiche: sappiamo che alla fine le otterremo, non possiamo evitarlo, andare avanti.
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
}
}