如何在 Frames/IFrames 中获取 HtmlElement 值?
Posted
技术标签:
【中文标题】如何在 Frames/IFrames 中获取 HtmlElement 值?【英文标题】:How to get an HtmlElement value inside Frames/IFrames? 【发布时间】:2019-04-12 07:38:16 【问题描述】:我正在使用Winforms
WebBrowser
控件从以下链接的站点收集视频剪辑的链接。
LINK
但是,当我逐个元素滚动时,我找不到<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 吗?
【问题讨论】:
【参考方案1】:您链接的网页包含IFrames。
一个IFrame
包含它自己的HtmlDocument。到目前为止,您只解析主 Document 容器。
因此,您需要解析其他一些Frame
的HtmlElements
TAG。
网页框架列表由WebBrowser.Document.Window.Frames 属性引用,该属性返回HtmlWindowCollection。
集合中的每个HtmlWindow 都包含它自己的HtmlDocument
对象。
大多数时候,我们需要解析Frames
集合中的每个HtmlWindow.Document
,而不是解析WebBrowser
返回的Document
对象属性;当然,除非我们已经知道所需的元素是主文档的一部分或另一个已知的Frame
。
一个例子(与当前任务相关):
订阅 WebBrowser 控件/类的DocumentCompleted 事件。 检查WebBrowser.ReadyState 属性以验证文档是否已完全加载。注意:
请记住,网页可能由 Frames/IFrames 中包含的多个文档组成,如果使用 ReadyState = WebBrowserReadyState.Complete
多次引发该事件,我们不会感到惊讶。
每个 Frame 的 Document
将在 WebBrowser
完成加载时引发事件。
Document.Window.Frames
集合中每个Frame的HtmlDocument
。
使用HtmlElement.GetAttribute方法提取HtmlElements
Attibute
。
注意:
由于DocumentCompleted
事件被多次引发,我们需要验证HtmlElement
属性值也没有被多次存储。
在这里,我使用了一个支持自定义类,它包含所有收集的值以及每个引用链接的 HashCode(这里依赖于 GetHasCode()
的默认实现)。
每次解析一个 Document 时,我们检查一个值是否已经被存储,比较它的 Hash。
注意:
在解析HtmlWindowCollection
时,不可避免地会引发一些特定的异常:
-
UnauthorizedAccessException: 部分 Frames 无法访问。
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
【讨论】:
我没有注意到 iframe!你的解释很到位!以上是关于如何在 Frames/IFrames 中获取 HtmlElement 值?的主要内容,如果未能解决你的问题,请参考以下文章
如何在Angular 7中单击按钮时获取下拉列表的选定选项[重复]