Веб-страница, на которую вы ссылаетесь, содержит IFrames .
IFrame
содержит свой собственный HtmlDocument . На данный момент вы анализируете только основной контейнер Document.
Таким образом, вам нужно проанализировать HtmlElements
теги некоторых других Frame
.
На список фреймов веб-страниц ссылается свойство WebBrowser.Document.Window.Frames , которое возвращает HtmlWindowCollection .
Каждый HtmlWindow в коллекции содержит свой собственный HtmlDocument
объект.
Вместо анализа свойства объекта Document
, возвращаемого WebBrowser
, нам, в большинстве случаев, необходимо проанализировать каждый HtmlWindow.Document
в коллекции Frames
; если, конечно, мы уже не знаем, что требуемые элементы являются частью основного документа или другого известного Frame
.
Пример (относится к текущей задаче):
Примечание:
Помня, что веб-страница может состоять из нескольких документов, содержащихся в кадрах / IFrames, мы не удивимся, если событие будет вызвано несколько раз с ReadyState = WebBrowserReadyState.Complete
.
Document
каждого кадра вызовет событие, когда WebBrowser
завершит его загрузку.
Примечание:
Поскольку событие DocumentCompleted
вызывается несколько раз, нам необходимо убедиться, что значение атрибута HtmlElement
также не сохраняется несколько раз.
Здесь я использую пользовательский класс поддержки, который содержит все собранные значения вместе с HashCode каждой ссылочной ссылки (здесь, опираясь на реализацию по умолчанию GetHasCode()
).
Каждый раз, когда документ анализируется, мы проверяем, было ли уже сохранено значение, сравнивая его хэш.
- Остановите синтаксический анализ, когда мы проверим, что дублированный хэш был найден: элементы документа кадра уже извлечены.
Примечание
При синтаксическом анализе HtmlWindowCollection
неизбежно возникает ряд особых исключений:
1) UnauthorizedAccessException : доступ к некоторым кадрам невозможен.
2) InvalidOperationException : доступ к некоторым элементам / потомкам невозможен.
Мы ничего не можем сделать, чтобы этого избежать: элементы не null
, они просто выдают эти исключения, когда мы пытаемся получить доступ к любому их свойств (плохой дизайн базового класса).
Здесь я просто ловлю и игнорирую эти конкретные исключения: мы знаем, что в конечном итоге мы их получим, мы не можем этого избежать, иди дальше.
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 webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
if (webBrowser1.ReadyState != WebBrowserReadyState.Complete) return;
var DocumentFrames = webBrowser1.Document.Window.Frames;
foreach (HtmlWindow Frame in DocumentFrames)
{
try
{
var VideoElement =
Frame.Document.Body
.GetElementsByTagName("VIDEO").Cast<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
}
}