И снова парсинг: в этот раз программа спортивных каналов через importxml, arrayformula и filter

Есть у меня на Android TV несколько спортивных каналов . Я — хоккейный фанат и слежу за играми на доступных КХЛ ТВ и Viju sports.

Встал вопрос — как бы получать программы по времени в виде таблицы телепередач с этих двух каналов.

Поиск сетки передач для сбора

Тут всё просто. Спасибо мэйл.ру и их программе телепередач.

Вероятно, есть и другие сервисы, но этот первым попался под руку.

Как обычно проваливаюсь в ссылку и смотрю возможности получить данные со страницы:

Из стандартных формул подходит importxml — про нее было много написано на этом сайте, потому рассказ не про нее.

Как обычно, лист, ссылка и xpath

Получаю данные в строку. Дальше транспонирую =TRANSPOSE(A4:Z4)

Далее все это раскладываю в столбцы:

  1. Канал — =ARRAYFORMULA(IF(A7:A<>"";"KHL";""))
  2. Время — =ARRAYFORMULA(LEFT(A7:A;5))
  3. Содержание программы — =IFERROR(ARRAYFORMULA(RIGHT(A7:A;(LEN(A7:A)-5)));"")

получая следующую таблицу:

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

Ровно такую же историю делаю по каналу Viju sports на которой показывают шведскую хоккейную лигу 🙂

Как результат у меня есть 2 отдельных листа на которых есть все необходимое для сведение в одно целое.

Консолидация разных ТВ-программ

Создаю лист «AllSports» на который вывожу программу передач с листов «КХЛ» и «Viju» через формулу

={FILTER(Viju!F7:H1000;Viju!G7:G<>"");FILTER(KHL!F7:H1000;KHL!G7:G<>"")}

затем сортирую их по времени

=SORT(H1:J;TO_DATE(I1:I);true)

в результате получая данные, подходящие для вывода в интернет:

Скриптовая часть

Так как в том или ином виде этот скрипт расписывался в блоге уже много раз (массив в API), поэтому просто код:

function getAllSports() {
  const ss = SpreadsheetApp.getActiveSpreadsheet();
  const ws = ss.getSheetByName("AllSports");
  const allSportsArray = ws.getRange(1, 1, ws.getLastRow(), 3).getValues();

  return allSportsArray
}

function doGet() {
  
  const webArr = getAllSports()
  const contService = ContentService.createTextOutput((JSON.stringify(webArr)))
  contService.setMimeType(ContentService.MimeType.JSON)

  return contService
}

Frontend через Vue

HTML

<div id="app">
        <div class="container">

            <table class="table">
                <thead>
                    <tr>
                        <th scope="col">Канал</th>
                        <th scope="col">Время</th>
                        <th scope="col">Программа</th>
                    </tr>
                </thead>
                <tbody>
                    <tr v-for="(event, index) in events " :key="index">
                        <td>{{event[0]}}</td>
                        <td>{{event[1]}}</td>
                        <td>{{event[2]}}</td>
                    </tr>
                </tbody>
            </table>

        </div>
    </div>

JS

const vueApp = {
  data() {
    return {
      events: [],
    };
  },

  methods: {
    async getData() {
      const link ="https://script.google.com/macros/s/AKfycbwWtYVgL2gHmT86bKBPVpok4QW40_fyDPEpx54TM1vc2GC2ODAPgI2EQ7-Vi2TDUdwh/exec";
      const res = await fetch(link);
      this.events = await res.json();
    },
  },

  mounted() {
    this.getData();
  },
};

const app = Vue.createApp(vueApp);
app.mount("#app");

В конечном виде получая следующий результат — https://codepen.io/DmitriiBeattle/full/GRPyXgp

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

={FILTER(Viju!F7:H1000;Viju!G7:G<>"");FILTER(KHL!F7:H1000;KHL!G7:G<>"";FILTER("Еще канал и так далее"!F7:H1000;KHL!G7:G<>"")}

Обновление спустя месяц

  • Добавлен KHL Prime — в своей основе он дублирует сетку KHL, но когда в одно и то же время идут разные матчи, Прайм показывает другую игру.
  • До этого макрос выводил данные абсолютно все программы начина с 00-00 по Московскому времени, что было несколько неудобно в части навигации — если сейчас 16-00, то надо скроллить половину страницы, что на телефоне делать лениво 🙂 В связи с этим была добавлена следующая функциональность:
  1. Получение текущего времени «минус два часа» — для того, чтобы выводить программу с учетом уже идущих передач, начавшихся ранее.

function getCurrentTime() {
  const currentDate = new Date();
  return currentDate.getHours() - 2;
}

2. Вывод не всего массива с телепередачами, а той части, которая идет «сейчас и далее»:

const currentTime = getCurrentTime();
  const filteredArray = allSportsArray.filter(row => Number(row[1].slice(0, 2)) > currentTime)

  return filteredArray

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

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

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