我有一个代码可以遍历表的行和列,我想将它的值添加到列表中.
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模板网!