Selenium ChromeDriver:增加获取 WebElement 文本的时间
我有一个代码可以遍历表的行和列,我想将它的值添加到列表中.
I have a code in which I traverse table rows and columns, and I'd like to add it's values to a list.
这需要我大量的时间.
所以我添加了一个时间测量,我注意到由于某种原因,时间逐行增加.
So I added a time measurement, and I noticed that for some reason the time increases from row to row.
我不明白为什么.
你能建议吗?
private void buildTableDataMap() {
WebElement table = chromeWebDriver.findElement(By.id("table-type-1"));
List<WebElement> rows = table.findElements(By.tagName("tr"));
theMap.getInstance().clear();
String item;
for (WebElement row : rows) {
ArrayList<String> values = new ArrayList<>();
List<WebElement> tds = row.findElements(By.tagName("td"));
if(tds.size() > 0){
WebElement last = tds.get(tds.size() - 1);
long time = System.currentTimeMillis();
values.addAll(tds.stream().map(e->e.getText()).collect(Collectors.toList()));
System.out.println(System.currentTimeMillis() - time);
//remove redundant last entry:
values.remove(tds.size() - 1);
callSomeFunc(values, last);
item = tds.get(TABLE_COLUMNS.NAME_COL.getNumVal()).getText();
item = item.replaceAll("[^.\- /'&A-Za-z0-9]", "").trim();//remove redundant chars
theMap.getInstance().getMap().put(item, values);
}
}
}
<小时>
伙计们,我继续研究.首先,弗洛伦特的友好回答对我没有帮助,因为至少据我了解,它返回了我必须解析的字符串数组列表,我不太喜欢这种解决方案......
Guys, I continued researching. First of all, Florent's kind answer did not help me because, at lease as I understand, It returned me an array list of strings which I had to parse, and I don't like this kind of solution too much...
所以我发现 e.getText() 调用在每次调用之间的时间都在增加,从而解决了这个问题!!!我也尝试了 e.getAttribute("innerText") 但没有改变.无法理解为什么.有什么想法可以解决吗?
So I nailed the problem in finding that the e.getText() call was increasing in time from call to call!!! I also tried e.getAttribute("innerText") instead but no change. Can't understand why. Any idea to solve?
WebElement last = null;
for (WebElement e : tds){
last = e;
long tm1 = 0, tm2 = 0;
if(Settings.verboseYN) {
tm1 = System.currentTimeMillis();
}
s = e.getText(); //This action increases in time!!!
if(Settings.verboseYN) {
tm2 = System.currentTimeMillis();
}
values.add(s); //a 0 ms action!!!
if(Settings.verboseYN) {
System.out.println("e.getText()) took " + (tm2 - tm1) + " ms...");
}
}
这是 getText 所用时间的图表...
That is an graph of the time getText took...
18 年 5 月 8 日增加执行时间的另一个来源是:
08-May-18 Another source of growing execution time is this one:
void func(WebElement anchorsElement){
List<WebElement> anchors = anchorsElement.findElements(By.tagName("a"));
for (WebElement a : anchors) {
if (a.getAttribute("class").indexOf("a") > 0)
values.add("A");
else if (a.getAttribute("class").indexOf("b") > 0)
values.add("B");
else if (a.getAttribute("class").indexOf("c") > 0)
values.add("C");
}
}
每个函数只有 5 次迭代,但每次调用该函数仍会增加其执行时间.这个也有解决办法吗?
Every functions has 5 iterations only, but still each call to the function increases its execution time. Is there a solution for this one as well?
推荐答案
您面临的问题是因为 Selenium 的设计方式.让我们看看 JavaScript get 是如何执行的或操作是如何执行的
The problem you are facing is because of the way Selenium works by design. Let's look at how a JavaScript get's executed or a operation is performed
tds.get(TABLE_COLUMNS.NAME_COL.getNumVal()).getText();
你有一个对象的集合.selenium 驱动程序在浏览器端为每个对象分配一个唯一 ID
You have a collection of objects. Each object is assigned a unique ID on the browser side by the selenium driver
所以当你执行 getText()
时会发生以下情况
So when you do a getText()
below is what happens
Your code -> HTTP Request -> Browser Driver -> Browser ->
|
<---------------------------------------------
现在,如果您有一个 400rx10c 的表,那么它会占用 4000
个 HTTP 调用,即使一个调用需要 10 毫秒,我们正在查看一个 40000ms~=40sec
,这是读取表格的一个不错的延迟
Now if you have a table of 400rx10c then it accounts to 4000
HTTP calls, even if one call takes 10ms, we are looking at a 40000ms~=40sec
, which is a decent delay to read a table
所以你想要做的是通过执行一个返回二维数组的 javascript 来一次性获取所有数据.这很简单,我在下面的网站上找到了一个代码
So what you want to do is to get all the data in single go by executing a javascript which give you 2d array back. It is quite simple, I found a code on below site
http://cwestblog.com/2016/08/21/javascript-snippet-convert-html-table-to-2d-array/
function tableToArray(tbl, opt_cellValueGetter) {
opt_cellValueGetter = opt_cellValueGetter || function(td) { return td.textContent || td.innerText; };
var twoD = [];
for (var rowCount = tbl.rows.length, rowIndex = 0; rowIndex < rowCount; rowIndex++) {
twoD.push([]);
}
for (var rowIndex = 0, tr; rowIndex < rowCount; rowIndex++) {
var tr = tbl.rows[rowIndex];
for (var colIndex = 0, colCount = tr.cells.length, offset = 0; colIndex < colCount; colIndex++) {
var td = tr.cells[colIndex], text = opt_cellValueGetter(td, colIndex, rowIndex, tbl);
while (twoD[rowIndex].hasOwnProperty(colIndex + offset)) {
offset++;
}
for (var i = 0, colSpan = parseInt(td.colSpan, 10) || 1; i < colSpan; i++) {
for (var j = 0, rowSpan = parseInt(td.rowSpan, 10) || 1; j < rowSpan; j++) {
twoD[rowIndex + j][colIndex + offset + i] = text;
}
}
}
}
return twoD;
}
我假设您将上述脚本存储在 SCRIPT
变量中,然后您可以像下面这样运行它
I assume you store the above script in a SCRIPT
variable and then you can run it like below
WebDriver driver = ((RemoteWebElement)table).getWrappedDriver();
Object result = ((JavascriptExecutor)driver).executeScript(SCRIPT + "
return tableToArray(arguments[0]);" , table);
这将为您提供一个二维数据数组,然后您可以按照自己喜欢的方式处理它
This will get you a 2D array of the data and you can then process it the way you like it
相关文章