我遇到了一个问题,它与Selenium webdriver的使用有关。
想象一下,我有一个HTML表,它有<head>
和<body>
,表体由200行组成。
我需要做的是将<th>
中的每个<head>
映射到与此tbody//tr//th
对应的单元格列表(<th>
)。
例如,如果我们有表:
<table>
<head>
<tr>
<th>Title 1</th>
<th>Title 2</th>
<th>Title 3</th>
</tr>
</head>
<body>
<tr>
<td>Cell 1</td>
<td>Cell 2</td>
<td>Cell 3</td>
</tr>
<tr>...199 more such rows...</tr>
</body>
</table>
我希望收到的结果是HashMap<WebElement, List<WebElement>>
,其中key是列标题,value是与列索引对应的单元格列表(body//tr//td
)。
我已经实现了这个,但是当表中有很多行时,我遇到了时间开销的问题。
以下是我如何做到这一点:
@FindBy(xpath = ".//table)
WebElement table;
@FindBy(xpath = ".//table//head")
WebElement tableHeader;
Map<WebElement, List<WebElement>> columnCells = new HashMap<>();
List<WebElement> tableTitles = tableHeader.findElements(By.xpath("./*"));
List<WebElement> tableRows = table.findElements(By.xpath(".//tbody/*"));
for (int i = 0; i < tableTitles.size(); i++) {
WebElement columnTitle = tableTitles.get(i);
List<WebElement> correspondingCells = new ArrayList<>();
for (WebElement tableRow : tableRows) {
List<WebElement> cells = tableRow.findElements(By.xpath("./*"));
correspondingCells.add(cells.get(i));
}
columnCells.put(columnTitle, chosenCells);
}
正如我所提到的,如果表包含~200行,则此初始化大约需要15秒。问题出在第二个for
循环中,因为访问WebDriver一次花费大约6-8毫秒。
有人可以帮我优化这个表的初始化吗?也许有一种方法根本不涉及WebDriver?
答案 0 :(得分:1)
您可以使用索引通过xpath以更简单的方式执行此操作。
假设您在表格中N columns
200 plus rows
。
获取所有元素并准确设置for循环。
使用带有来自for循环的索引的xpath(比如说i)来获取所有td - driver.findElements(By.xpath("//table/tbody/tr/td[i+1]"));
返回可以放入集合中的元素列表。
确保在查询之前执行加1逻辑,因为xpath索引从1开始。
答案 1 :(得分:1)
即使不关心它究竟是如何工作的,它几乎可以确定耗时的部分就是这条线
Map<WebElement, List<WebElement>> columnCells
你是否连续获得所有细胞并且除了一个之外扔掉所有细胞。切换循环肯定会快得多。您可以使用所有单元格并将它们分配到适当的列表中。
考虑从番石榴中用ListMultimap替换for (WebElement tableRow : tableRows) {
List<WebElement> cells = tableRow.findElements(By.xpath("./*"));
for (int i = 0; i < tableTitles.size(); i++) {
columnCells.put(tableTitles.get(i), cells.get(i)); // using Multimap
}
}
。仅这一点无助于提高速度,但它使代码更简单。
Multimap使优化的循环比原始循环更短:
select a.id, a.name, b.id, b.name, c.id, c.name from A a, B b, C c
where b.a=a and c.a=a