使用SeleniumDriver提取给定表格元素的所有行和列

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在行元素上使用来避免对每个单元进行迭代,希望输出将由某些东西来分隔,但事实并非如此。

有没有更好的方法来刮桌子?

MxL*_*evs 5

我不是使用selenium来解析HTML,而是使用Jsoup。尽管Selenium提供了遍历表的功能,但Jsoup效率更高。我决定仅将Selenium用于网页自动化,并将所有解析任务委托给Jsoup。

我的方法如下

  1. 获取所需元素的HTML源
  2. 将其作为字符串传递给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秒。尽管我没有花太多时间进行基准测试,但我对结果感到非常满意。