MxL*_*evs 1 html-table html-parsing selenium-webdriver
我正在抓取一个最终将导出为CSV格式的表。我可能需要考虑几种情况,例如嵌套表,跨行/单元格等。但是现在,我将忽略这些情况,并假设我有一个非常简单的表。“简单”是指我们只有行和单元格,每行中单元格的数量可能不相等,但是它在结构上仍然是相当基本的。
<table>
<tr>
<td>text </td>
<td>text </td>
</tr>
<tr>
<td>text </td>
</tr>
</table>
Run Code Online (Sandbox Code Playgroud)
我的方法是简单地遍历行和列
String[] rowTxt;
WebElement table = driver.findElement(By.xpath(someLocator));
for (WebElement rowElmt : table.findElements(By.tagName("tr")))
{
List<WebElement> cols = rowElmt.findElements(By.tagName("td"));
rowTxt = new String[cols.size()];
for (int i = 0; i < rowTxt.length; i++)
{
rowTxt[i] = cols.get(i).getText();
}
}
Run Code Online (Sandbox Code Playgroud)
但是,这很慢。对于具有218行的CSV文件(这意味着我的表有218行),每行最多不超过5列,抓取该表花费了45秒。
我曾尝试通过getText在行元素上使用来避免对每个单元进行迭代,希望输出将由某些东西来分隔,但事实并非如此。
有没有更好的方法来刮桌子?
我不是使用selenium来解析HTML,而是使用Jsoup。尽管Selenium提供了遍历表的功能,但Jsoup效率更高。我决定仅将Selenium用于网页自动化,并将所有解析任务委托给Jsoup。
我的方法如下
我最终编写的代码与硒版本非常相似
String source = "<table>" + driver.findElement(By.xpath(locator)).getAttribute("innerHTML") + "<table>";
Document doc = Jsoup.parse(source, "UTF-8");
for (Element rowElmt : doc.getElementsByTag("tr"))
{
Elements cols = rowElmt.getElementsByTag("th");
if (cols.size() == 0 )
cols = rowElmt.getElementsByTag("td");
rowTxt = new String[cols.size()];
for (int i = 0; i < rowTxt.length; i++)
{
rowTxt[i] = cols.get(i).text();
}
csv.add(rowTxt);
}
Run Code Online (Sandbox Code Playgroud)
Selenium解析器需要5分钟才能读取1000行表,而Jsoup解析器则需要不到10秒。尽管我没有花太多时间进行基准测试,但我对结果感到非常满意。