Bagaimana cara mendapatkan nilai HtmlElement di dalam Frames / IFrames?

Nov 09 2018

Saya menggunakan Winforms WebBrowserkontrol untuk mengumpulkan tautan klip video dari situs yang ditautkan di bawah.

TAUTAN

Tapi, ketika saya menggulir elemen demi elemen, saya tidak dapat menemukan <video>tagnya.

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
}

Segera setelah menggunakan

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

Saya sudah mengembalikan 0

Apakah saya perlu menelepon ajax?

Jawaban

6 Jimi Nov 09 2018 at 07:17

Halaman Web yang Anda tautkan berisi IFrames .
An IFrameberisi HtmlDocumentnya sendiri . Sampai sekarang, Anda hanya mengurai wadah Dokumen utama.
Jadi, Anda perlu mengurai HtmlElementsTAG dari beberapa lainnya Frame.
Daftar Bingkai Halaman Web direferensikan oleh properti WebBrowser.Document.Window.Frames , yang mengembalikan HtmlWindowCollection .
Setiap HtmlWindow dalam koleksi berisi HtmlDocumentobjeknya sendiri .

Alih-alih mengurai Documentproperti objek yang dikembalikan oleh a WebBrowser, kita, sebagian besar waktu, perlu mengurai masing-masing HtmlWindow.Documentdalam Frameskoleksi; kecuali, tentunya kita sudah mengetahui bahwa Elemen yang dibutuhkan adalah bagian dari Dokumen Utama atau yang lain yang diketahui Frame.

Contoh (terkait dengan tugas saat ini):

Catatan:
Mengingat bahwa Halaman Web dapat disusun oleh beberapa Dokumen yang terdapat dalam Frames / IFrames, kami tidak akan terkejut jika acara dimunculkan beberapa kali dengan a ReadyState = WebBrowserReadyState.Complete.
Setiap Frame Documentakan menaikkan event ketika WebBrowserselesai memuatnya.

Catatan:
Karena DocumentCompletedevent dimunculkan beberapa kali, kita perlu memverifikasi bahwa HtmlElementnilai Attribute tidak disimpan beberapa kali juga.
Di sini, saya menggunakan Class kustom dukungan yang menyimpan semua nilai yang dikumpulkan bersama dengan HashCode dari setiap Tautan referensi (di sini, mengandalkan implementasi default GetHasCode()).
Setiap kali Dokumen diurai, kami memeriksa apakah suatu nilai telah disimpan, membandingkan Hash-nya.

  • Hentikan penguraian saat kami memverifikasi bahwa duplikat Hash telah ditemukan: Elemen Dokumen Bingkai telah diekstraksi.

Catatan :
Saat mengurai HtmlWindowCollection, memunculkan beberapa Pengecualian tertentu:

  1. UnauthorizedAccessException : beberapa Frames tidak dapat diakses.
  2. InvalidOperationException : beberapa Elements / Descendants tidak dapat diakses.

Tidak ada yang dapat kami lakukan untuk menghindari hal ini: Elemen tidak null, mereka hanya membuang pengecualian ini saat kami mencoba mengakses salah satu propertinya.
Di sini, saya hanya menangkap dan mengabaikan Pengecualian khusus ini: kita tahu pada akhirnya kita akan mendapatkannya, kita tidak dapat menghindarinya, lanjutkan.

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
    }
}