快速入门
SeleniumSDK是一个基于WebDriver协议的浏览器自动化的D库.它与Selenium,Ruby绑定的使用模式类似,API一致,大部分``W3C表面映射为你期望的.
当库与W3C``有所不同时,相关注意事项会在文中记录并说明.
安装
用DUB添加包:
cpp
dub add selenium-sdk
还需要在路径,PATH上安装WebDriver服务器.库会自动检测你要求的浏览器的正确版本.
Browser |
WebDriverbinary |
|---|---|
Chrome |
chromedriver |
Firefox |
geckodriver |
Edge |
msedgedriver |
Safari |
safaridriver |
最快的启动方式,是让库选择路径上第一个安装的驱动:
cpp
import selenium;
Driver driver = Driver.start();
scope (exit) driver.stop();
driver.go("https://example.com");
writeln(driver.title);
浏览器
浏览器描述了想从会话中得到的能力.基础浏览器是常见的;具体子类增加了供应商能力.构建一个,设置字段,然后交给Driver.start.
类型 |
浏览器名 |
额外 |
|---|---|---|
| 浏览器 | 常见 | 仅限标准W3C功能. |
Chrome |
chrome |
二进制binary,includeSwitches,excludeSwitches,prefs,扩展,记录,extensions,logging. |
Firefox |
Firefox |
二进制binary,args,prefs,配置profile. |
Edge |
微软Edge |
Chrome选项加上mobileEmulation,WebView2(useWebView). |
Safari |
safari |
automaticInspection,automaticProfiling,technologyPreview. |
标准功能在基础上,适合所有浏览器:
| 字段 | 目的 |
|---|---|
平台platform |
请求的主机平台(Platform.Windows,Platform.Linux等). |
接受不安全证书acceptInsecureCerts |
接受无效的TLS证书. |
页加载策略pageLoadStrategy |
正常,激进,或没有. |
未处理提示行为unhandledPromptBehavior |
如何处理突发提示. |
超时timeouts |
隐式等待,页加载和脚本超时. |
cpp
import selenium;
import core.time : seconds;
Chrome chrome = new Chrome();
chrome.binary = "/usr/bin/google-chrome";
chrome.includeSwitches = ["--headless=new", "--disable-gpu"];
chrome.timeouts.implicit = 5.seconds;
Driver driver = Driver.start(chrome);
scope (exit) driver.stop();
可按firstMatch列表传递替代,服务器会选择第一个它能满足的:
cpp
Driver driver = Driver.start(new Chrome(), [new Firefox()]);
桥
桥是拥有WebDriver进程或远程连接并管理其所有会话的低级主机.你一般不会直接触碰它:Driver.start会为你生成一个.
当你想在一个进程上运行多个会话,限制并发或连接到远程端点时,可选择桥.
与大多数客户不同,驱动和会话在此并非严格一对一.单个桥可服务多个会话,每个驱动都是其中一个会话的句柄.
| 成员 | 目的 |
|---|---|
Bridge.start(binary,args) |
在空闲端口上生成本地驱动进程. |
Bridge.connect(address) |
连接到已运行的服务器(远程或栅). |
容量capacity |
最大并发会话数,或无限会话为0. |
会话sessions |
以ID为键的活动会话. |
stop() |
干掉生成进程并去掉所有会话. |
cpp
import selenium;
//在两个会话中共享一个驱动进程.
Bridge bridge = Bridge.start(new Chrome().resolveBinary());
bridge.capacity = 2;
Driver first = Driver.start(bridge, new Chrome(), null);
Driver second = Driver.start(bridge, new Chrome(), null);
由Bridge.start创建的桥拥有其自己的进程,并在收集时析构.由Bridge.connect创建的桥则不会,因此停止不会干掉远程服务器.
驱动
驱动是使用SeleniumSDK的主要方式.它封装单一会话,并在浏览器上面提供方便的API.调用力求与W3C规范和SeleniumRuby绑定保持高度一致.
停止驱动只会结束自己的驱动,桥则为保活其他驱动.
浏览
调用 |
动作 |
|---|---|
driver.go(url) |
浏览到一个网址. |
driver.back()/driver.forward() |
通过历史移动. |
driver.refresh() |
重新加载文档. |
driver.url |
当前文档网址. |
驱动.标题driver.title |
当前文档标题. |
driver.source |
序化页资源. |
driver.screenshot |
视点的Base64的PNG截图. |
查找元素
使用By定位器,对单个元素使用找find,对每个匹配使用FindAll.
| 定位器 | 匹配 |
|---|---|
By.css(selector) |
CSS选择器. |
By.xpath(expr) |
XPath表达式. |
By.tagName(name) |
标签名. |
By.linkText(text) |
带精确可见的文本锚点. |
作者.部分链接文本(文本),By.partialLinkText(text) |
包含文本的锚点. |
cpp
Element button = driver.find(By.css("#submit"));
Element[] items = driver.findAll(By.xpath("//li[@class='item']"));
脚本与窗口
cpp
int sum = driver.execute!int("return arguments[0] + arguments[1];", JSONValue([2, 3]));
driver.window.maximize();
string[] handles = driver.window.handles();
string tab = driver.window.open("tab");
driver.window.switchTo(tab);
driver.frame.switchTo(0);
driver.frame.switchToParent();
小缓冲与记录日志
这些是每会话都可用,但不是快速入门的重点.简要说明:
cpp
import selenium;
driver.cookies.add(Cookie("session", "abc123"));
Cookie[] all = driver.cookies.all();
driver.cookies.clear();
driver.logger.drain(LogType.Browser);
//拉取等待的远程日志
元素
元素是页中节点的句柄.只有该节点仍连接在DOM上时才有效;过时句柄抛StaleElementReferenceException.
| 成员 | 目的 |
|---|---|
文本text |
已渲染可见的文本. |
标签名tagName |
小写标签名. |
attribute(name) |
标记属性值. |
property(name) |
活的DOM属性值. |
cssValue(name) |
计算出的CSS值. |
大小/位置size/position |
边框大小和偏移. |
已选中/允许selected/enabled |
元素状态. |
点击()click() |
点击元素. |
sendKeys(text...) |
输入进元素. |
clear() |
清理可编辑元素. |
find(by)/findAll(by) |
在该元素内搜索. |
截图screenshot |
元素的Base64的PNG截图. |
cpp
Element form = driver.find(By.tagName("form"));
Element input = form.find(By.css("input[name='username']"));
input.sendKeys("alice");
writeln(input.attribute("placeholder"));
writeln(input.enabled);
form.find(By.css("button[type=submit']")).click();