Bagaimana cara mendapatkan nilai HtmlElement di dalam Frames / IFrames?
Saya menggunakan Winforms WebBrowserkontrol untuk mengumpulkan tautan klip video dari situs yang ditautkan di bawah.
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
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):
- Berlangganan acara DocumentCompleted dari Kontrol / Kelas Browser Web.
- Periksa properti WebBrowser.ReadyState untuk memverifikasi bahwa Dokumen dimuat sepenuhnya.
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.
- Parsing
HtmlDocumentsetiap Frame dalamDocument.Window.Frameskoleksi, menggunakan metode Frame.Document.Body.GetElementsByTagName () . - Ekstrak
HtmlElementsAttibutemenggunakan metode HtmlElement.GetAttribute .
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:
- UnauthorizedAccessException : beberapa Frames tidak dapat diakses.
- 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
}
}