Selenium ChromeDriver: увеличивается время получения текста WebElement - PullRequest
0 голосов
/ 30 апреля 2018

У меня есть код, в котором я просматриваю строки и столбцы таблицы, и я хотел бы добавить его значения в список.

Это занимает у меня много времени.

Поэтому я добавил измерение времени и заметил, что по некоторым причинам время увеличивается от строки к строке.

Я не могу понять, почему.

Можете ли вы посоветовать, пожалуйста?

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

Ребята, я продолжил исследования. Прежде всего, добрый ответ Флорента мне не помог, потому что, как я понимаю, он дал мне список массивов строк, которые мне пришлось проанализировать, и мне не очень нравится решение такого рода ...

Так что я прибил проблему, обнаружив, что вызов e.getText () увеличивается во времени от вызова к вызову !!! Я также попробовал e.getAttribute ("innerText") , но без изменений. Не могу понять почему. Любая идея, чтобы решить?

            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 ...

enter image description here


08-Май-18 Вот еще один источник растущего времени выполнения:

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 итераций, но каждый вызов функции увеличивает время ее выполнения. Есть ли решение для этого?

Ответы [ 2 ]

0 голосов
/ 05 мая 2018

Проблема, с которой вы сталкиваетесь, заключается в том, как Selenium работает по своему замыслу. Давайте посмотрим, как выполняется JavaScript get или выполняется операция

tds.get(TABLE_COLUMNS.NAME_COL.getNumVal()).getText();

У вас есть коллекция предметов. Каждому объекту присваивается уникальный идентификатор на стороне браузера драйвером селена

Так что, когда вы делаете getText() ниже, вот что происходит

Your code -> HTTP Request -> Browser Driver -> Browser ->
                                                        |
           <---------------------------------------------

Теперь, если у вас есть таблица 400rx10c, тогда она учитывает 4000 HTTP-вызовов, даже если один вызов занимает 10 мс, мы смотрим 40000ms~=40sec, что является приемлемой задержкой для чтения таблицы

Итак, вы хотите получить все данные за один раз, выполнив javascript, который вернет вам 2d массив. Это довольно просто, я нашел код на сайте ниже

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, а затем можете запустить его, как показано ниже

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

Это даст вам двумерный массив данных, и вы сможете обрабатывать его так, как вам нравится

0 голосов
/ 30 апреля 2018

Вызов водителя - дорогая операция. Чтобы значительно сократить время выполнения, используйте JavaScript-инъекцию с executeScript для чтения всей таблицы за один вызов. Затем обработайте / отфильтруйте данные на стороне клиента с помощью 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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...