我正在使用 Winforms
WebBrowser
控制从下面链接的站点收集视频剪辑的链接。
但是,当我逐个元素滚动时,我找不到 <video>
标签。
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
}
使用后不久
HtmlElementCollection pTags = browser.Document.GetElementsByTagName("video");
我已经返回0
我需要调用任何 ajax 吗?
最佳答案
您链接的网页包含 IFrames .
IFrame
包含自己的 HtmlDocument .到目前为止,您只解析主文档容器。
因此,您需要解析其他一些 Frame
的 HtmlElements
标签。
网页框架列表由 WebBrowser.Document.Window.Frames 引用属性,返回 HtmlWindowCollection .
每个HtmlWindow在集合中包含它自己的 HtmlDocument
对象。
大多数时候,我们需要解析每个 HtmlWindow.Document
,而不是解析 WebBrowser
返回的 Document
对象属性在 Frames
集合中;当然,除非我们已经知道所需的元素是主文档或另一个已知的 Frame
的一部分。
一个例子(与当前任务相关):
- 订阅DocumentCompleted WebBrowser 控件/类的事件。
- 检查 WebBrowser.ReadyState属性来验证文档是否已完全加载。
注意:
请记住,网页可能由框架/IFrames 中包含的多个文档组成,如果使用 ReadyState = WebBrowserReadyState.Complete
多次引发该事件,我们不会感到惊讶。
当 WebBrowser
完成加载时,每个框架的 Document
将引发事件。
- 使用 Frame.Document.Body.GetElementsByTagName() 解析
Document.Window.Frames
集合中每个 Frame 的HtmlDocument
方法。 - 使用 HtmlElement.GetAttribute 提取
HtmlElements
Attibute
方法。
注意:
由于 DocumentCompleted
事件被多次引发,我们需要验证 HtmlElement
属性值也没有被多次存储。
在这里,我使用了一个支持自定义类,它包含所有收集的值以及每个引用链接的 HashCode(此处依赖于 GetHasCode()
的默认实现)。
每次解析一个 Document 时,我们检查一个值是否已经存储,比较它的 Hash。
- 当我们确认已找到重复哈希时停止解析:框架文档元素已被提取。
注意:
在解析 HtmlWindowCollection
时,不可避免地会引发一些特定的异常:
- UnauthorizedAccessException : 无法访问某些框架。
- 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 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
}
}
关于c# - 如何获取 Frames/IFrames 中的 HtmlElement 值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53213782/