我正在使用该Winforms WebBrowser控件从下面链接的站点收集视频剪辑的链接。
Winforms
WebBrowser
链接
但是,当我逐元素滚动时,找不到<video>标签。
<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。到目前为止,您只解析主Document容器。 因此,您需要解析HtmlElements其他标签Frame。 Web页面框架列表由WebBrowser.Document.Window.Frames属性引用,该属性返回HtmlWindowCollection。集合中的 每个HtmlWindow都包含自己的HtmlDocument对象。
IFrame
HtmlElements
Frame
HtmlDocument
相反解析的Document被返回的对象属性WebBrowser,我们大部分的时间,需要分析每个HtmlWindow.Document中Frames收集; 除非,当然,除非我们已经知道所需的元素是主文档或其他已知文档的一部分Frame。
Document
HtmlWindow.Document
Frames
一个示例(与当前任务有关):
订阅WebBrowser控件/类的DocumentCompleted事件。
检查WebBrowser.ReadyState属性以验证是否完全加载了Document。
注意: 请记住,网页可能是由Frames / IFrames中包含的多个Document组成的,如果使用多次引发事件,我们不会感到惊讶ReadyState = WebBrowserReadyState.Complete。加载完毕后, 每个Frame Document都会引发事件WebBrowser。
ReadyState = WebBrowserReadyState.Complete
使用Frame.Document.Body.GetElementsByTagName()方法解析集合HtmlDocument中每个Frame的。Document.Window.Frames
Document.Window.Frames
HtmlElements Attibute使用HtmlElement.GetAttribute方法提取。
Attibute
注意: 由于DocumentCompleted事件引发多次,因此我们需要验证HtmlElement属性值也没有存储多次。 在这里,我使用的是一个支持自定义类,该类包含所有收集的值以及每个引用Link的HashCode(此处依赖的默认实现GetHasCode())。 每次解析文档时,我们都会比较其哈希值,以检查是否已存储值。
DocumentCompleted
HtmlElement
GetHasCode()
注意 : 在解析时HtmlWindowCollection,不可避免地会引发一些特定的异常: 1)UnauthorizedAccessException:某些框架无法访问。 2)InvalidOperationException:某些元素/后代无法访问。
HtmlWindowCollection
我们没有什么可以避免的:元素不是null,当我们尝试访问它们的 任何 属性(基类的不良设计)时,它们只会抛出这些异常。 在这里,我只是捕捉并忽略了这些特定的例外:我们知道最终将获得它们,我们无法避免,继续前进。
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").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 } }