DOM
本指南描述了如何访问 DOM 文档、查找元素、修改 DOM 结构,以及模拟用户输入等。
概述
IBrowser
中加载的每个网页都有一个主 IFrame
。 IFrame
本身可能有子框架。 例如,当一个网页有多个 IFRAME
对象时,使用 IFrame
类来访问 DOM 和 JavaScript。
访问文档
每个 IFrame
都有一个 DOM IDocument
。 要访问 IDocument
,,请使用 IFrame.Document
属性:
IDocument document = frame.Document;
Dim document As IDocument = frame.Document
查找元素
您可以根据不同的条件在元素中查找 HTML 元素。 下面的代码示例演示了如何在文档元素中查找所有 DIV 元素:
IElement documentElement = document.DocumentElement;
IEnumerable<IElement> elements = documentElement?.GetElementsByTagName("div");
Dim documentElement As IElement = document.DocumentElement
Dim elements As IEnumerable(Of IElement) = documentElement?.GetElementsByTagName("div")
如果您只需要查找第一个 HTML 元素,请使用以下方法:
documentElement.GetElementByTagName("div");
documentElement.GetElementByTagName("div")
Here are the examples of searching for HTML elements by different conditions:
documentElement.GetElementById("<id>");
documentElement.GetElementsByName("<attr-name>");
documentElement.GetElementsByTagName("<tag-name>");
documentElement.GetElementsByClassName("<attr-class>");
documentElement.GetElementById("<id>")
documentElement.GetElementsByName("<attr-name>")
documentElement.GetElementsByTagName("<tag-name>")
documentElement.GetElementsByClassName("<attr-class>")
XPath
DotNetBrowser DOM API 允许使用 INode.Evaluate(string expression)
评估 XPath 表达式。 您可以使用以下代码示例评估指定 INode
范围内的 XPath 表达式:
IXPathResult result = node.Evaluate("count(//div)");
Dim result As IXPathResult = node.Evaluate("count(//div)")
评估结果存储在 IXPathResult
对象中。 确保结果包含预期的值类型,例如 Number
, Boolean
, String
, Node
, 并提取值本身:
if (result.Type == XPathResultType.Number) {
double? number = result.Numeric;
}
If result.Type = XPathResultType.Number Then
Dim number? As Double = result.Numeric
End If
查询选择器
要查找与指定选择器(例如, #root
)匹配的元素,请使用以下代码:
IEnumerable<IElement> elements = element.GetElementsByCssSelector("#root");
Dim elements As IEnumerable(Of IElement) = element.GetElementsByCssSelector("#root")
焦点元素
要在网页上找到当前获得焦点的元素,请使用 IDocument.FocusedElement
属性:
IElement focusedElement = document.FocusedElement;
Dim focusedElement As IElement = document.FocusedElement
点处的节点
要在网页上找到特定点的 INode
,例如 100x150,请使用以下方法:
PointInspection inspection = frame.Inspect(new Point(100, 150));
INode node = inspection.Node;
Dim inspection As PointInspection = frame.Inspect(New Point(100, 150))
Dim node As INode = inspection.Node
使用元素
元素边界
您可以通过相对于当前 IDocument
视口左上角的位置获取 IElement
的边界,如下所示:
Rectangle rect = element.BoundingClientRect;
Dim rect As Rectangle = element.BoundingClientRect
当元素具有 hidden
属性或元素的 CSS 样式包含 display: none
时,该方法返回一个空的 Rectangle
; 陈述。
元素属性
IElement
类提供的方法允许您获取、添加、删除或修改 HTML 元素属性。 下面的代码示例演示了如何获取元素的所有属性并打印它们的名称和值:
foreach (KeyValuePair<string, string> attr in element.Attributes)
{
Console.WriteLine($"{attr.Key}: {attr.Value}");
}
For Each attr As KeyValuePair(Of String, String) In element.Attributes
Console.WriteLine($"{attr.Key}: {attr.Value}")
Next
下面的代码示例演示了如何添加/修改元素属性:
element.Attributes["attrName"] = "attrValue";
element.Attributes("attrName") = "attrValue"
创建元素
DOM API 允许修改文档 DOM 结构。 以下示例演示了如何创建和插入带有一些文本的 <p>
元素:
// 创建一个新的段落元素。
IElement paragraph = document.CreateElement("p");
// 用给定的文本创建一个文本节点。
INode text = document.CreateTextNode("Text");
// 将文本节点插入段落元素。
if (paragraph.Children.Append(text)) {
// 将段落元素插入到所需的元素中。
bool success = element.Children.Append(paragraph);
}
' 创建一个新的段落元素。
Dim paragraph As IElement = document.CreateElement("p")
' 用给定的文本创建一个文本节点。
Dim text As INode = document.CreateTextNode("Text")
' 将文本节点插入段落元素。
If paragraph.Children.Append(text) Then
' 将段落元素插入到所需的元素中。
Dim success As Boolean = element.Children.Append(paragraph)
End If
DOM 事件
每个 INode
都实现了 IEventTarget
接口,该接口提供了注册 DOM 事件的方法。 您可以注册 DOM 监听器以接收 DOM 事件,例如 click
, mousedown
, mouseup
, keydown
, load
, error
等。
以下代码示例演示了如何为 HTML 文档元素注册点击事件监听器:
document.DocumentElement.Events.Click += (sender, e) => {
// 鼠标点击事件已被接收。
};
AddHandler document.DocumentElement.Events.Click, Sub(sender, e)
' 鼠标点击事件已被接收。
End Sub
DotNetBrowser 还允许您监听自定义 DOM 事件类型。 下面的代码示例演示了如何监听 MyEvent
DOM 事件:
// 创建一个自定义 DOM 事件类型。
EventType eventType = new EventType("MyEvent");
element.Events[eventType] += (sender, e) => {
// 已收到自定义事件。
};
' 已收到自定义事件。
Dim eventType As New EventType("MyEvent")
AddHandler element.Events(eventType).EventReceived, Sub(sender, e)
' 已收到自定义事件。
End Sub
自动化
DotNetBrowser DOM API 提供了自动填写网络表单所需的一切。 本节介绍如何更新文本字段中的文本、选择复选框或单选按钮、在下拉列表中选择一个或多个选项、模拟单击等。
要使用网络表单控件,请使用 IFormControlElement
接口。 该界面允许您检查控件是否已启用并修改其值。 所有的表单控件,如 INPUT
, SELECT
, TEXTAREA
等都继承了这个接口。
输入
要使用 INPUT
元素,请使用 IInputElement
接口。 它提供了检查输入类型和设置其值所需的所有方法。
文本、电子邮件和密码
要用新值替换文本、电子邮件或密码字段的默认值,请使用 IInputElement.Value
属性。
例如,您的网络表单包含具有以下类型的 <input>
元素:
<input type="text" id="firstname" placeholder="First Name">
<input type="email" id="email" placeholder="Email Address">
<input type="password" id="password" placeholder="Password">
您可以使用以下方法设置它们的值:
((IInputElement)documentElement.GetElementById("firstname")).Value = "John";
((IInputElement)documentElement.GetElementById("email")).Value = "me@company.com";
((IInputElement)documentElement.GetElementById("password")).Value = "Jkdl12!";
DirectCast(documentElement.GetElementById("firstname"), IInputElement).Value = "John"
DirectCast(documentElement.GetElementById("email"), IInputElement).Value = "me@company.com"
DirectCast(documentElement.GetElementById("password"), IInputElement).Value = "Jkdl12!"
复选框、单选按钮
要选择单选按钮或复选框,请使用 IInputElement.Checked
属性。 例如,您的网络表单包含具有以下类型的 <input>
元素:
<input type="checkbox" id="checkbox" value="Remember me">
<input type="radio" id="radio" checked>
您可以使用以下方法选择/取消选择它们:
((IInputElement)documentElement.GetElementById("checkbox")).Checked = true;
((IInputElement)documentElement.GetElementById("radio")).Checked = false;
DirectCast(documentElement.GetElementById("checkbox"), IInputElement).Checked = True
DirectCast(documentElement.GetElementById("radio"), IInputElement).Checked = False
文件
type=file
的 <input>
元素允许用户从他们的设备存储中选择一个或多个文件。 DotNetBrowser 允许以编程方式选择文件并更新 <input type=file>
元素的值。
例如,您的网络表单包含一个 <input>
元素,例如:
<input type="file" id="avatar" accept="image/png, image/jpeg" multiple>
您可以使用以下方法以编程方式选择所需的文件:
((IInputElement)documentElement.GetElementById("avatar")).Files = new[]{
"file1.png",
"file2.jpeg"};
DirectCast(documentElement.GetElementById("avatar"), IInputElement).Files =
{
"file1.png",
"file2.jpeg"
}
文本区
您有一个 <textarea>
元素,如下所示:
<textarea id="details"></textarea>
使用以下方法设置文本:
((ITextAreaElement)documentElement.GetElementById("details")).Value = "Some text...";
Dim textElement = DirectCast(documentElement.GetElementById("details"), ITextAreaElement)
textElement.Value = "Some text..."
选择 & 选项
有一个 SELECT
控件如下:
<select id="fruits" multiple>
<option>Apple</option>
<option>Orange</option>
<option>Pineapple</option>
<option>Banana</option>
</select>
您可以使用以下方法来选择某个项目:
var document = browser.MainFrame.Document;
var optionElements = ((ISelectElement)document.GetElementById("fruits"))
.Options
.ToList();
foreach (IOptionElement optionElement in optionElements)
{
// 检查是否找到了必要的项目。
if (optionElement.InnerText.Contains("Orange"))
{
// 选择必要的项目。
optionElement.Selected = true;
}
}
Dim document = browser.MainFrame.Document
Dim optionElements = DirectCast(document.GetElementById("fruits"), ISelectElement)
.Options
.ToList()
For Each optionElement As IOptionElement In optionElements
' 检查是否找到了必要的项目。
If optionElement.InnerText.Contains("Orange") Then
' 选择必要的项目。
optionElement.Selected = True
End If
Next
使用这种方法,您可以只选择一个必需的选项。
模拟点击
要模拟鼠标单击元素,请使用以下方法:
element.Click();
element.Click()
当 Click()
与受支持的元素(例如 <input>
)一起使用时,它会触发元素的 click
事件。 该事件向上冒泡到文档树中较高的元素并触发它们的 click
事件。
调度事件
您可以使用IEventTarget.DispatchEvent(IEvent)
方法在指定的 IEventTarget
处调度 IEvent
。
下面的代码示例演示了如何在指定元素处分派标准 click
事件:
// 客户端和屏幕位置。
Point location = new Point(10, 10);
// 使用所需的选项创建 MouseEvent。
MouseEventParameters eventParameters = new MouseEventParameters
{
Button = 0,
ClientLocation = location,
ScreenLocation = location,
UiEventModifierParameters = new UiEventModifierParameters()
{
EventParameters = new EventParameters.Builder()
{
Bubbles = true,
Cancelable = true
}.Build()
}
};
IMouseEvent mouseClickEvent = document.CreateMouseEvent(EventType.Click,
eventParameters);
// 在目标元素上生成点击事件。
element.DispatchEvent(mouseClickEvent);
' 客户端和屏幕位置。
Dim location As New Point(10, 10)
' 使用所需的选项创建 MouseEvent。
Dim eventParameters As New MouseEventParameters With {
.Button = 0,
.ClientLocation = location,
.ScreenLocation = location,
.UiEventModifierParameters = New UiEventModifierParameters() With
{
.EventParameters = New EventParameters.Builder() With
{
.Bubbles = True,
.Cancelable = True
}.Build()
}
}
Dim mouseClickEvent As IMouseEvent = document.CreateMouseEvent(EventType.Click,
eventParameters)
' 在目标元素上生成点击事件。
element.DispatchEvent(mouseClickEvent)
使用这种方法,您可以创建和调度各种 DOM 事件。 此类事件通常称为合成事件,而不是 IBrowser
本身触发的事件。
调度“更改”事件
在 DotNetBrowser 中,DOM 事件不会在更新值时自动调度,而某些网站可能需要它们。 在这种情况下,您需要显式发送这些事件以使网站正确识别更新。 DispatchEvent
的实际用法取决于您与之交互的 JavaScript 框架。
最常见的情况是在更新输入字段后调度 change
事件以触发 JavaScript 中的 onchange
事件监听器。 例如:
IDocument document = Browser.MainFrame.Document;
IInputElement email = document.GetElementById("email") as IInputElement;
email.Value = "me@example.com";
email.DispatchEvent(document.CreateEvent(EventType.Change,
new EventParameters.Builder().Build()));
Dim document As IDocument = Browser.MainFrame.Document
Dim email = TryCast(document.GetElementById("email"), IInputElement)
email.Value = "me@example.com"
email.DispatchEvent(document.CreateEvent(EventType.Change,
(New EventParameters.Builder()).Build()))
注入自定义 CSS
您可以指定要应用于 IBrowser
实例中加载的每个页面的自定义 CSS 规则。
您可以通过设置 IBrowser.InjectCssHandler
属性来配置自定义 CSS。 CSS 规则将应用于浏览器中加载的下一个页面。
string hideOverflowCss = "HTML, BODY {overflow:hidden;}";
browser.InjectCssHandler =
new Handler<InjectCssParameters, InjectCssResponse>(p =>
{
return InjectCssResponse.Inject(hideOverflowCss);
});
Dim hideOverflowCss = "HTML, BODY {overflow:hidden;}"
browser.InjectCssHandler =
New Handler(Of InjectCssParameters, InjectCssResponse)(Function(p)
Return InjectCssResponse.Inject(hideOverflowCss)
End Function)