Selenium ChromeDriver:增加获取WebElement Text的时间

我有一个代码,我遍历表行和列,我想将它的值添加到列表中。

这花了我很多时间。

所以我添加了时间测量,我注意到由于某种原因,时间从行到行增加。

我不明白为什么。

你能告诉我吗?

private void buildTableDataMap() { WebElement table = chromeWebDriver.findElement(By.id("table-type-1")); List rows = table.findElements(By.tagName("tr")); theMap.getInstance().clear(); String item; for (WebElement row : rows) { ArrayList values = new ArrayList(); List 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); } } } 

伙计们,我继续研究。 首先,Florent的回答对我没有帮助,因为据我所知,它至少给了我一个字符串列表,我不得不解析,我不太喜欢这种解决方案……

所以我找到了e.getText()调用从调用到调用的时间增加的问题! 我也尝试过e.getAttribute(“innerText”),但没有改变。 无法理解为什么。 有什么想法要解决?

  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拍摄时间的图表…

在此处输入图像描述


08年5月18日这个增长执行时间的另一个来源是:

 void func(WebElement anchorsElement){ List 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次迭代,但每次调用函数都会增加执行时间。 这个也有解决方案吗?

您面临的问题是由于Selenium的设计方式。 让我们来看看如何执行JavaScript或执行操作

 tds.get(TABLE_COLUMNS.NAME_COL.getNumVal()).getText(); 

你有一组对象。 selenium驱动程序在浏览器端为每个对象分配一个唯一的ID

所以,当你执行下面的getText()时会发生什么

 Your code -> HTTP Request -> Browser Driver -> Browser -> | <--------------------------------------------- 

现在,如果你有一个400rx10c的表,那么它会占用4000 HTTP调用,即使一个调用需要10ms,我们正在查看40000ms~=40sec ,这是读取表的一个不错的延迟

所以你要做的就是通过执行一个可以返回2d数组的javascript来获取所有数据。 这很简单,我在网站下面找到了一个代码

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变量中,然后您可以像下面一样运行它

 WebDriver driver = ((RemoteWebElement)table).getWrappedDriver(); Object result = ((JavascriptExecutor)driver).executeScript(SCRIPT + "\n return tableToArray(arguments[0]);" , table); 

这将为您提供数据的2D数组,然后您可以按照自己喜欢的方式处理它

调用驱动程序是一项昂贵的操作。 要显着缩短执行时间,请使用带有executeScript的JavaScript注入来在单个调用中读取整个表。 然后使用Java处理/过滤客户端上的数据。

 public ArrayList readTable(WebElement table) { final String JS_READ_CELLS = "var table = arguments[0]; " + "return map(table.querySelectorAll('tr'), readRow); " + "function readRow(row) { return map(row.querySelectorAll('td'), readCell) }; " + "function readCell(cell) { return cell.innerText }; " + "function map(items, fn) { return Array.prototype.map.call(items, fn) }; " ; WebDriver driver = ((RemoteWebElement)table).getWrappedDriver(); Object result = ((JavascriptExecutor)driver).executeScript(JS_READ_CELLS, table); return (ArrayList)result; }