問題描述
我有一個代碼可以遍歷表的行和列,我想將它的值添加到列表中.
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
這篇關于Selenium ChromeDriver:增加獲取 WebElement 文本的時間的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!