[英]Selenium ChromeDriver: increasing time of getting WebElement Text
我有一個代碼,在其中遍歷表的行和列,我想將其值添加到列表中。
我花了很多時間。
因此,我添加了一個時間度量,並且我注意到由於某種原因,時間逐行增加。
我不明白為什么。
你能告訴我嗎?
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);
}
}
}
伙計們,我繼續研究。 首先,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花費時間的圖表...
18年5月8日,另一個增加執行時間的來源是:
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次迭代,但是每次調用該函數都會增加其執行時間。 是否也有解決方案?
調用驅動程序是一項昂貴的操作。 為了顯着減少執行時間,請結合使用JavaScript注入和executeScript
在單個調用中讀取整個表。 然后使用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;
}
您面臨的問題是因為Selenium的設計工作方式。 讓我們看一下如何執行JavaScript獲取或執行操作
tds.get(TABLE_COLUMNS.NAME_COL.getNumVal()).getText();
您有一組對象。 硒驅動程序在瀏覽器端為每個對象分配了唯一的ID
所以當您在下面執行getText()
時會發生什么
Your code -> HTTP Request -> Browser Driver -> Browser ->
|
<---------------------------------------------
現在,如果您有一個400rx10c的表,那么它將處理4000
HTTP調用,即使一個調用花費10ms,我們正在查看40000ms~=40sec
,這是讀取表的一個不錯的延遲
因此,您想要執行的是通過執行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);
這將為您提供一個二維數據數組,然后您可以按照自己喜歡的方式對其進行處理
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.