Получение данных из Google Chart (svg)

Приходилось ли кому-либо вычитывать данные из прорисованного google-chart?
Проблемы с которыми я столкнулась:

  1. Изменяющиеся пропорции элементов, переносы и сокращения строк легенд - соответственно для сравнения со скриншотом эталонного чарта не получится
  2. Отсутствие реальных значений в структуре DOM до момента наведения курсора на определенные точки. Просчитать эти точки можно (громоздко, но реально), да вот наведение страдает, особенно если две точки находятся на расстоянии пары пикселей. Возникает эффект “мерцания”, когда попап с реальным значением появляется и исчезает с невообразимой скоростью без изменения положения мыши (что реальной, что в понятиях вебдрайвера)

Вопрос в следующем, какие могут быть еще варианты достать значения из такого чарта? Пример моего любимого чарта можно посмотреть здесь Visualization: Column Chart  |  Charts  |  Google Developers, там их реально много, но этот наиболее часто приносит проблемы.

При этом прошу заметить, что в фаерфоксе (естественно) такая проблема заметна менее всего. Чаще в хроме. Думаю не удивительно, что больше всего проблем приносит в этом плане IE и Opera

Ну я бы постарался, как взять не из самого графика данные. Насколько я помню, данные в google chart задаются через опции к урлу и потом на основании этой информации гугл генерирует необходимый график.

Я пошел по той ссылке, которая указана выше и если зайти в сам iframe где отображается график, то в javascript коде можно найти следующий код:

 var data = google.visualization.arrayToDataTable([
    ['Year', 'Sales', 'Expenses'],
    ['2004',  1000,      400],
    ['2005',  1170,      460],
    ['2006',  660,       1120],
    ['2007',  1030,      540]
  ]);

Вот вам и данные все сразу целиком, можно сохранять и парсить. Конечно надо только разобраться, где и как эти данные хранятся в разных графиках. Может быть по разному. Но это нужно проверять

В моем случае все эти параметры передаются в виде JSON асинхронным скриптом, но если пытаться поймать элемент script, то максимум это удастся уловить что он был, при попытке вытащить из него атрибут scr заканчиваются StaleElementReferenceException ибо живет эта нода очень недолго. Уменьшение таймаутов ни к чему не приводит.

не легко, согласен

а откуда подтягиваются данные? из базы данных?
может быть тогда просто от туда считать их

так мне именно и нужно проверить, что он нужные мне данные вытянул из базы)

ну тогда, тут или делать перехват, что тоже не получится просто.
или просто это проверять руками, ну не все же поддается автоматизации или может занять много времени, что не эффективно

Попробовал на этом чарте, куски ниже приведенного кода работают на Chrome 29 / FF 23 / IE9:


private String columns = "//*[@clip-path]/*[name()='g'][2]/*[name()='rect'][%]";

private By year = By.xpath("//*[name()='svg']/*[name()='g'][5]/*[name()='g']/*[name()='g'][1]/*[name()='text']");

private By salesText = By.xpath("//*[name()='svg']/*[name()='g'][5]/*[name()='g']/*[name()='g'][2]/*[name()='text'][1]");

private By salesValue = By.xpath("//*[name()='svg']/*[name()='g'][5]/*[name()='g']/*[name()='g'][2]/*[name()='text'][2]");

public void getDataFromChart(int column) {
    moveToElement(By.xpath(columns.replace("%", String.valueOf(column))));
    System.out.println("Year: " + getText(year));
    System.out.println("Sales text: " + getText(salesText));
    System.out.println("Sales value: " + getText(salesValue));
}

protected void moveToElement(By element) {
    actions.moveToElement(findElement(element)).perform();
}

protected String getText(By element) {
    return findElement(element).getText();
}

Правда на IE нужно либо 3 раза вызвать метод getDataFromChart для разных проверок, либо печатать в консоль только одно значение, иначе вываливается эксепшен. В хроме и лисе такой проблемы не было обнаружено. xpath конечно тоже кривой, но в приведенном чарте иначе никак не добраться до элементов, ибо у тегов вообще нет никаких идентификаторов. Без name() тоже не будет работать для svg объектов. Это что касается динамически появляющихся значений столбцов. Статические лейблы можно выгрести JSом:


var labels = $('g').find('text');
alert(labels[0].textContent);

1 лайк

есть несколько моментов в этом совете:

  1. Выгребать текстовые значения обычных элементов через джаваскриптовые алерты - не лучший вариант. Для этогго вполне подходит findElement(…).getAtribute(“textContent”);
  2. при наведении на столбец структура чарта изменяется и по локатору By.xpath(columns.replace("%", String.valueOf(column))), где номер столбца = 2, будет фактически найден не второй, а третий столбец. Поэтому нужно сразу после этого наводиться еще куда-нибудь, для того, чтобы привести чарт к прежнему виду.
  3. Изначально я уточнила, что больше всего проблем приносят IE и Opera. Признаю не уточнила какой ие использовала. У меня 10. но думаю это тоже не принципиально. В IE (*10) \часто, но не всегда и опере\практически всегда , при таком наведении попап со значением сразу исчезает. Соответственно по getText() ничего кропе эксепшена не получаешь

** Но ведь где-то должны храниться значения, которые он показывает при наведении

  1. Как бы пример был вставлен из консоли браузера. Не думал, что
    кому-то в принципе в голову может прийти идея вытягивать данные
    алертами. Это нонсенс. В коде естественно это выглядело бы иначе. А
    использовать getAttribute или JSExecutor - тут уже по-моему без
    разницы.
  2. Под номером 2 будет 3й столбец и без наведения, ибо rects в
    данной DOM модели отсортированы по цвету. Т.е., если хотите получить
    реальный второй столбец, он будет 5м в списке. Опять-таки, это лишь
    сухая реализация на скорую руку. Никто не мешает вам написать метод
    преобразования введенных данных к реальной модели. По поводу
    наведения вообще не понял. Попап с данными появляется всегда в 5м
    g относительно svg. И он никак не влияет на остальную структуру.
  3. Первым в вашем списке стоял хром. С него я и начал ресёч. Выше
    приведенный код отрабатывает на нем без эксепшенов. Относительно IE
    могу сказать лишь, что абсолютно во всех версиях присутствуют
    нюансы, для которых приходится городить workarounds. В 9м при
    определенных условиях с выше приведенным кодом можно добиться
    успеха, а ради 10го не хочется ставить виртуалку, но уверен, что и
    там проблема решаема. По поводу оперы вообще не вижу смысла даже
    что-то обсуждать, ибо считаю совершенно нецелесообразным
    осуществлять поддержку браузера, % использования которого по миру за
    последние 10 лет не поднялся выше 2х. За 4 года ни разу даже намека
    не было от клиентов не то чтобы автоматизировать, даже ручным
    тестированием заниматься под данный браузер.

Как я уже написал выше, они всегда при наведении отображаются по данным xpath:

 //*[name()='svg']/*[name()='g'][5]/*[name()='g']/*[name()='g'][1]/*[name()='text']
 //*[name()='svg']/*[name()='g'][5]/*[name()='g']/*[name()='g'][2]/*[name()='text'][1]
 //*[name()='svg']/*[name()='g'][5]/*[name()='g']/*[name()='g'][2]/*[name()='text'][2]

При попытке вытащить данные из вебэлементова часто вываливался StaleRefferenceElementException, обошла это подключение прокси и вытягиванием всех необходимых данных напрямую из коллбеков. Так что проблема решена)