Come ottenere un valore HtmlElement all'interno di Frames / IFrames?

Nov 09 2018

Sto utilizzando il Winforms WebBrowsercontrollo per raccogliere i collegamenti dei video clip dal sito collegato di seguito.

LINK

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

6 Jimi Nov 09 2018 at 07:17

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):

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.

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:

  1. UnauthorizedAccessException : non è possibile accedere ad alcuni frame.
  2. 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
    }
}