Java Selenium ChromeDriver:增加获取Web元素文本的时间

Java Selenium ChromeDriver:增加获取Web元素文本的时间,java,selenium,selenium-webdriver,selenium-chromedriver,Java,Selenium,Selenium Webdriver,Selenium Chromedriver,我有一个代码,在其中我遍历表的行和列,我想把它的值添加到一个列表中 这花了我很多时间 所以我添加了一个时间度量,我注意到由于某种原因,时间从一行增加到另一行 我不明白为什么 你能给个建议吗 private void buildTableDataMap() { WebElement table = chromeWebDriver.findElement(By.id("table-type-1")); List<WebElement> rows = table.fin

我有一个代码,在其中我遍历表的行和列,我想把它的值添加到一个列表中

这花了我很多时间

所以我添加了一个时间度量,我注意到由于某种原因,时间从一行增加到另一行

我不明白为什么

你能给个建议吗

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);
        }
    }
}
这是getText所用时间的图表


2018年5月8日 执行时间增长的另一个原因是:

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");

    }
}
void func(WebElement主播元素){
列表锚点=锚点元素.findelelements(按.tagName(“a”));
for(WebElement a:锚定){
如果(a.getAttribute(“类”).indexOf(“a”)>0)
价值。添加(“A”);
else if(a.getAttribute(“类”).indexOf(“b”)>0)
价值。添加(“B”);
else if(a.getAttribute(“class”).indexOf(“c”)>0)
价值。添加(“C”);
}
}
每个函数只有5次迭代,但每次调用函数都会增加其执行时间。
还有解决这个问题的方法吗?

调用驱动程序是一项昂贵的操作。要显著缩短执行时间,请使用带有
executeScript
的JavaScript注入在一次调用中读取整个表。然后使用Java在客户端处理/过滤数据

public ArrayList<?> readTable(WebElement table)
{
    final String JS_READ_CELLS = 
        "var table = arguments[0]; " +
        "return map(table.querySelectorAll('tr'), readRow); " +
        "function readRow(row) { return map(row.querySelectorAll('td'), readCell) }; " +
        "function readCell(cell) { return cell.innerText }; " +
        "function map(items, fn) { return Array.prototype.map.call(items, fn) }; " ;

    WebDriver driver = ((RemoteWebElement)table).getWrappedDriver();
    Object result = ((JavascriptExecutor)driver).executeScript(JS_READ_CELLS, table);
    return (ArrayList<?>)result;
}
publicArrayList可读表(WebElement表)
{
最终字符串JS_READ_CELLS=
“变量表=参数[0];”+
返回映射(table.querySelectorAll('tr'),readRow)+
函数readRow(row){返回映射(row.querySelectorAll('td'),readCell)}+
“函数readCell(cell){return cell.innerText};”+
函数映射(items,fn){returnarray.prototype.map.call(items,fn)};
WebDriver驱动程序=((RemoteWebElement)表).getWrappedDriver();
对象结果=((JavascriptExecutor)驱动程序).executeScript(JS_读取_单元格,表);
返回(ArrayList)结果;
}

调用驱动程序是一项昂贵的操作。要显著缩短执行时间,请使用带有
executeScript
的JavaScript注入在一次调用中读取整个表。然后使用Java在客户端处理/过滤数据

public ArrayList<?> readTable(WebElement table)
{
    final String JS_READ_CELLS = 
        "var table = arguments[0]; " +
        "return map(table.querySelectorAll('tr'), readRow); " +
        "function readRow(row) { return map(row.querySelectorAll('td'), readCell) }; " +
        "function readCell(cell) { return cell.innerText }; " +
        "function map(items, fn) { return Array.prototype.map.call(items, fn) }; " ;

    WebDriver driver = ((RemoteWebElement)table).getWrappedDriver();
    Object result = ((JavascriptExecutor)driver).executeScript(JS_READ_CELLS, table);
    return (ArrayList<?>)result;
}
publicArrayList可读表(WebElement表)
{
最终字符串JS_READ_CELLS=
“变量表=参数[0];”+
返回映射(table.querySelectorAll('tr'),readRow)+
函数readRow(row){返回映射(row.querySelectorAll('td'),readCell)}+
“函数readCell(cell){return cell.innerText};”+
函数映射(items,fn){returnarray.prototype.map.call(items,fn)};
WebDriver驱动程序=((RemoteWebElement)表).getWrappedDriver();
对象结果=((JavascriptExecutor)驱动程序).executeScript(JS_读取_单元格,表);
返回(ArrayList)结果;
}

您面临的问题是因为Selenium的设计工作方式。让我们看看JavaScript get是如何执行的或操作是如何执行的

tds.get(TABLE_COLUMNS.NAME_COL.getNumVal()).getText();
您有一个对象集合。selenium驱动程序在浏览器端为每个对象指定了一个唯一的ID

因此,当您执行一个
getText()
时,会发生以下情况

Your code -> HTTP Request -> Browser Driver -> Browser ->
                                                        |
           <---------------------------------------------
我假设您将上述脚本存储在
script
变量中,然后可以像下面那样运行它

WebDriver driver = ((RemoteWebElement)table).getWrappedDriver();
Object result = ((JavascriptExecutor)driver).executeScript(SCRIPT + "\n return tableToArray(arguments[0]);" , table);

这将获得一个2D数据数组,然后您可以按自己喜欢的方式处理它

您所面临的问题是因为Selenium的设计工作方式。让我们看看JavaScript get是如何执行的或操作是如何执行的

tds.get(TABLE_COLUMNS.NAME_COL.getNumVal()).getText();
您有一个对象集合。selenium驱动程序在浏览器端为每个对象指定了一个唯一的ID

因此,当您执行一个
getText()
时,会发生以下情况

Your code -> HTTP Request -> Browser Driver -> Browser ->
                                                        |
           <---------------------------------------------
我假设您将上述脚本存储在
script
变量中,然后可以像下面那样运行它

WebDriver driver = ((RemoteWebElement)table).getWrappedDriver();
Object result = ((JavascriptExecutor)driver).executeScript(SCRIPT + "\n return tableToArray(arguments[0]);" , table);

这将为您提供一个2D数据数组,然后您可以按照自己喜欢的方式处理它

使用您试图自动执行的手动步骤以及相关的HTML@DebanjanB没有具体的手动步骤。我试图做的是从一些站点表中提取数据。所有的表都具有相同的结构。您是否发现网站本身花费时间返回数据或selenium代码是造成这种情况的原因?@HelpingHands我不确定问题是在网站、selenium基础设施还是java中。注意,我只测量了以下各项的计时:values.addAll(tds.stream().map(e->e.getText()).collect(Collectors.toList());这是一个不断增加的测量。也许这是合乎逻辑的,取决于初始值列表大小?@dushkin-页面中有多少行是您试图与之交互并存储到数组中的?请使用您试图自动执行的手动步骤以及相关的HTML@DebanjanB没有具体的手动步骤。我试图做的是从一些站点表中提取数据。所有的表都具有相同的结构。您是否发现网站本身花费时间返回数据或selenium代码是造成这种情况的原因?@HelpingHands我不确定问题是在网站、selenium基础设施还是java中。注意,我只测量了以下各项的计时:values.addAll(tds.stream().map(e->e.getText()).collect(Collectors.toList());这是一个不断增加的测量。也许这是合乎逻辑的,取决于初始值列表的大小?@dushkin-页面中有多少行您试图与之交互并存储到数组中?我会检查它。ThanksI看到正在读取该表,但当尝试将其强制转换为Object[]时,我得到了java.lang.ClassCastException:java.util.ArrayList不能强制转换为[Ljava.lang.Object;我最初是为C#编写的,因此返回的类型可能不同。仅供参考,脚本返回一个锯齿状数组。尝试将该对象强制转换为
(ArrayList)结果
。我非常感谢您的努力