(待修订):
参考官网链接:https://www.selenium.dev/documentation/webdriver/locating_elements/
首先要明确:
我们的页面中有些dom是在页面加载完成后(document.readyState后)就出现的,而有些dom元素,是通过js动态生成加入的。例如document.body.appendChild(newElement),或是因为触发了某些鼠标或键盘事件,而动态生成或显示的(display:block;)。例如常见的点击或touch触发了modal模态框,popper气泡框,下拉列表等。或者服务端接口暂时没有返回数据,渲染内容为空等异步情况。所以我们可以说dom是存在异步的 。而selenium的操作是同步的 ,所以需要协调两者 。所以有了wait方法和sleep方法。
在selenium中:
WebDriver 代表浏览器 WebElement 表示特定的 DOM 节点(控件,例如链接或输入字段等) 所有方法基本上都是返回promise,所以要配合使用async/await,按顺序执行流程
对象的几种类型:
- Locator类型 代表一个定位器,类似于css选择器,但功能更强大
- WebDriver类型 代表浏览器
- WebElement类型 代表一个dom元素
- WebElementPromise类型 代表一个会返回WebElement的promise
- Condition类型 代表wait方法的第一个入参
- WebElementCondition类型 返回的WebElement将作为wait方法的判定条件或返回值
- function(){ return xxx } 返回的任何真值将作为wait方法的判定条件或返回值
wait方法和sleep方法:
WebDriver类型具有wait方法和sleep方法 wait方法主要有四个入参,第一个为Condition类型,第二个为最多等待时间Number类型 wait方法可以没有返回值,如果有返回值的话,它等于第一个参数返回的真值。 在第一个参数没有返回真值期间,wait方法会循环执行,阻塞住主线程,等待条件判定结果,直至超时报错。 until需要在wait方法中使用。
因此我们可以这样获取WebElement:
let target = await driver.wait(
until.elementLocated(By.css("#title")),
10000
);
let target = await driver.findElement(By.css("#title"));
sleep方法,只有一个入参,代表着需要主线程阻塞多久。这个一般用于我们触发了一个按钮,然后弹框出现。这时需要我们在触发完按钮之后“等一会”,等弹框中的内容加载完毕,然后我们在继续流程,防止某些元素没找到,或者不可交互。 没找到:是指页面上根本没有这个dom 不可交互:是指这个dom元素不可见,比如hidden或none
...
await modalbutton.click();
await driver.sleep(3000);
...
executeScript方法:
它可以执行javascript语句,可以类似成eval()。它的第二个参数可以是一个WebElement,也就是说我们可以对某个已获取到的WebElement执行js,类似于操纵此dom。使用时以arguments代表WebElement或WebElements。
const box = await driver.wait(
until.elementLocated(By.css("#box")),
10000
);
const offsetTop = await driver.executeScript(
"return arguments[0].offsetTop",
box
);
设置cookies:
需要先加载页面,才能设置cookies。 比如我们get的网址是一个需要登陆态的网址,那么我们需要先get这个网址,然后添加这个网址登陆所需的cookies,然后再get一遍这个网址。三步完成设置cookie登陆。
await driver.get("http://xxx.com/ts/#/manage/work");
await driver.manage().addCookie(cookie1);
await driver.manage().addCookie(cookie2);
await driver.manage().addCookie(cookie3);
...
await driver.sleep(1000);
await driver.get("http://xxx.com/ts/#/manage/work");
使用chrome的无头模式:
const { Builder } = require("selenium-webdriver");
const chrome = require("selenium-webdriver/chrome");
let opts = new chrome.Options();
(async function () {
const driver = new Builder()
.forBrowser("chrome")
.setChromeOptions(opts.headless())
.build();
try {
await driver.get("https://bot.sannysoft.com/");
} catch (error) {
console.log(error, "捕获异常");
await driver.quit();
}
})();
|