您链接的网页包含IFrames https://learn.microsoft.com/en-us/dotnet/api/system.windows.forms.htmlwindow.frames.
An IFrame
包含它自己的Html文档 https://learn.microsoft.com/en-us/dotnet/api/system.windows.forms.htmlwindow.document。到目前为止,您仅解析主文档容器。
因此,您需要解析HtmlElements
其他一些标签Frame
.
网页框架列表由WebBrowser.Document.Window.Frames https://learn.microsoft.com/en-us/dotnet/api/system.windows.forms.htmlwindow.frames属性,它返回一个HtmlWindow集合 https://learn.microsoft.com/en-us/dotnet/api/system.windows.forms.htmlwindowcollection.
Each html窗口 https://learn.microsoft.com/en-us/dotnet/api/system.windows.forms.htmlwindow集合中包含它自己的HtmlDocument
object.
而不是解析Document
由 a 返回的对象属性WebBrowser
,大多数时候,我们需要解析每个HtmlWindow.Document
in the Frames
收藏;当然,除非我们已经知道所需的元素是主文档或其他已知元素的一部分Frame
.
示例(与当前任务相关):
- 订阅文件已完成 https://learn.microsoft.com/en-us/dotnet/api/system.windows.forms.webbrowser.documentcompleted?view=netframework-4.7.2Web 浏览器控件/类的事件。
- 检查WebBrowser.ReadyState https://learn.microsoft.com/en-us/dotnet/api/system.windows.forms.webbrowser.readystate?view=netframework-4.7.2属性来验证文档是否已完全加载。
Note:
请记住,一个网页可能由包含在 Frames/IFrames 中的多个文档组成,如果使用某个事件多次引发该事件,我们不会感到惊讶。ReadyState = WebBrowserReadyState.Complete
.
每一帧的Document
将引发该事件时WebBrowser
已完成加载。
- 解析
HtmlDocument
中每一帧的Document.Window.Frames
集合,使用Frame.Document.Body.GetElementsByTagName() https://learn.microsoft.com/en-us/dotnet/api/system.windows.forms.htmlelement.getelementsbytagname method.
- 提取
HtmlElements
Attibute
使用HtmlElement.GetAttribute https://learn.microsoft.com/en-us/dotnet/api/system.windows.forms.htmlelement.getattribute method.
Note:
自从DocumentCompleted
事件被多次引发,我们需要验证HtmlElement
属性值也不会被多次存储。
在这里,我使用一个支持自定义类,它保存所有收集的值以及每个引用链接的 HashCode(这里依赖于默认实现)GetHasCode()
).
每次解析文档时,我们都会检查一个值是否已被存储,并比较其哈希值。
- 当我们验证已找到重复的哈希时,停止解析:框架文档元素已被提取。
Note:
在解析时HtmlWindowCollection
,不可避免地要提出一些具体的异常:
-
未经授权的访问异常 https://learn.microsoft.com/en-us/dotnet/api/system.unauthorizedaccessexception:某些框架无法访问。
-
无效操作异常 https://learn.microsoft.com/en-us/dotnet/api/system.invalidoperationexception:某些元素/后代无法访问。
我们无法避免这种情况:元素不是null
,当我们尝试访问时,它们只是抛出这些异常any他们的财产。
在这里,我只是捕获并忽略这些特定的异常:我们知道我们最终会得到它们,我们无法避免它,继续前进。
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
}
}