И снова парсим Tinkoff инвестиции через скрипты

Почти год назад я опубликовал запись по тому, как можно было легко и в целом просто парсить данные с сайта https://www.tinkoff.ru/invest/ стандартными способами через importxml

Ссылка на запись здесь.

С тех пор утекло много воды и парсить указанным выше способом стало невозможно. Ну а может и возможно, но у меня не вышло. Вообще я заметил такую тенденцию, что много кто меняет код, ставит блокировки и importxml перестает работать. Защита данных и все такое…. Ну что ж! 🙂

Здравствуй tinkoff.ru/invest

Как обычно иду на сайт — https://www.tinkoff.ru/invest/etfs/TGLD/

Нужно что? Правильно, цена ETF — 0.0712

tinkoff etf gold

Далее в консоль. Сразу на 0.0712 она не открывается. Проваливаюсь в тег body и начинаю идти ниже, ища в отображении нужный класс (или еще раз щелкаю просмотр кода на цене):

tinkoff etf gold console price

проваливаюсь через F2 в:

<span class="SecurityInvitingScreen__priceValue_c1Ah9" data-qa-file="SecurityInvitingScreen"><span data-qa-type="uikit/money" class="Money-module__money_UZBbh">0<span data-qa-file="Money">,0712&nbsp;$</span></span></span>

необходимый кусок — >0<span data-qa-file="Money">,0712&nbsp;$<

Script Editor

Пишу код:

function getSpecificPrice() {
  url = "https://www.tinkoff.ru/invest/etfs/TGLD/"
  expr = /class="Money-module__money_UZBbh">(.*?)\$</g

  const urlText = UrlFetchApp.fetch(url, { muteHttpExceptions: true }).getContentText();

  const testExpr = expr.test(urlText)
  console.log(testExpr)

  const array = [...urlText.matchAll(expr)];
  console.log(array[0][1])
  
  const value = array[0][1].replace('<span data-qa-file="Money">', "").split("<")
  console.log(value[0])

  return value[0]

url = "https://www.tinkoff.ru/invest/etfs/TGLD/" — откуда фетчим данные

expr = /class="Money-module__money_UZBbh">(.*?)\$</g — регулярное выражение для ETF, обязательно с ключом /g потому что далее будет идти matchAll

Важно!!! Выражение /class="Money-module__money_UZBbh">(.*?) работает для ETF. Для акций, облигаций надо собирать своё регулярное выражение.

const urlText = UrlFetchApp.fetch(url, { muteHttpExceptions: true }).getContentText(); — получаю все с сайта

const testExpr = expr.test(urlText) и console.log(testExpr) — проверяю вообще есть ли совпадения по регулярному выражению.

regular expression test

Получаю результат в виде true — значит что-то есть.

const array = [...urlText.matchAll(expr)]; и console.log(array[0][1]) — мэтчу всё, что есть по данной регулярке и методом проб и ошибок нахожу, что стоимость хранится в array[0][1]

tinkoff etf gold price array

далее, не претендуя на красоту и изящность кода (на 100% уверен, что можно и красивее, но мне не хочется), убираю span , затем разделяю через < элементы в массив

const value = array[0][1].replace('<span data-qa-file="Money">', "").split("<")

первый элемент массива будет ни что иное как цена.

console.log(value[0])

tinkoff etf gold price array result

return value[0] — возвращаю результат работы функции.

Табличная часть

Создаю лист с именем «Log», делаю шапку

google sheets template for etf

Возвращаюсь в редактор скриптов, пишу простой код:

function logValue(){
  const ss = SpreadsheetApp.getActiveSpreadsheet()
  const ws = ss.getSheetByName("Log");
  const date = new Date()
  ws.appendRow([date, getSpecificPrice()])
}

Пару раз запускаю функцию logValue() , проверяю работу:

tinkoff etf gold google sheets result

Вот и всё. Далее можно завесить logValue() на триггер по времени и вести всю необходимую статистику.


Ваше мнение важно и может улучшить блог

Я хочу услышать ваше мнение и ваши идеи о том, как сделать этот сайт еще лучше. Примите участие в опросе, чтобы поделиться вашими пожеланиями, предложениями и замечаниями. Пройдите опрос сейчас и помогите сделать этот сайт более полезным для вас!

У этой записи 8 комментариев

  1. Илья

    Спасибо за прошлый ответ, насчёт appenRow
    А как мне извлечь так же, как в статье, цену с сайта https://www.coingecko.com/en/coins/terra-luna-classic ?
    Вопрос в том, Регулярка — это RegEx или можно брать Xpath как при importXml?
    Мне бы сам принцип понять, что вставлять в строку, где expr = **** (.*?)\$</g
    И на что мы меняем в const value = array[0][1].replace('********', "").split("<")
    И нужен ли switcher здесь, или интервал где-то заранее задан?

    PS/ Попробовал всё с Тиньковым как здесь, но получилась только одна запись, вместо тайминга.
    В коде не понимаю, мне для других задач нужно
    Спасибо

  2. Илья

    SyntaxError: Identifier ‘ss’ has already been declared
    (функция без названия) @ Switcher_Sheet — Log.gs:1

    Вот такая ошибка

  3. Илья

    Спасибо! Буду разбираться, и подбирать значения для аналогичного парсинга и на других сайтах!

  4. ILYA

    Добрый день, а как здесь можно получить данные не из функции, а из конкретной ячейки или области?

    function logValue(){
    const ss = SpreadsheetApp.getActiveSpreadsheet()
    const ws = ss.getSheetByName(«Log»);
    const date = new Date()
    ws.appendRow([date, getSpecificPrice()])
    }

    Вместо «getSpecificPrice()» что должно быть?

  5. Roman

    Привет, можешь пожалуйста помочь?
    В строке кода: expr = /class=»Money-module__money_UZBbh»>(.*?)\$(.*?) а эту часть оставлять не изменной?
    Или так же нужно изменять?
    Так же не до конца понял как ты пришел к тому в какой именно ячейки массива находится нужные нам данные?
    Сайт с данными этот хотел использовать https://p2p.binance.com/en/trade/TinkoffNew/USDT?fiat=RUB

    1. 1. Менять надо конечно, судя по тегам, там другие классы:
      div data-tutorial-id="trade_price_limit" class="css-1kj0ifu" div class="css-1m1f8hn"66.67
      2. По поводу массива — matchAll загоняет все совпадения в массив. Потом просто смотрю на все элементы массива и забираю нужные.

Добавить комментарий