Как получить таблицу с сайта github.com с помощью скрипта приложения Google Cheerio

Я пытаюсь получить таблицу с этого сайта, используя Cheerio lib в скрипте приложения Google. Я ввожу код ниже этот ответ, но получаю только [] in console.info()

Вот мой код

function test2() {
  const url = 'https://github.com/labnol/apps-script-starter/blob/master/scopes.md';
  const res = UrlFetchApp.fetch(url, { muteHttpExceptions: true }).getContentText();
  const $ = Cheerio.load(res);
  var data = $('tbody').find('td').toArray().map((x) => { return $(x).text() });
  console.info(data);
}

Я также вижу некоторые ответы:

  1. один

  2. два

    Но они не дали мне никакой подсказки, как получить желаемый результат.

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
0
104
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Для начала вы можете использовать API GitHub, избегая ошибок, связанных с парсингом веб-страниц.

Если вы хотите придерживаться GAS и избегать API, проблема, похоже, в том, что обслуживаемая страница отличается от страницы в браузере. Я определил это, добавив DriveApp.createFile("test.html", res); для обхода усечения журнала (по-видимому, лучшего способа по мнению TheMaster, видимо, не существует). Из этого выходного HTML-кода видно, что данные доступны только в строке React JSON внутри тега сценария, которую можно извлечь с помощью Cheerio, проанализировать с помощью JSON.parse() и просмотреть.

Однако более простой вариант — запросить необработанную уценку и либо преобразовать ее в HTML с пометкой и продолжить работу с Cheerio, либо проанализировать таблицу вручную. Я воспользуюсь последним вариантом, так как я не слишком знаком с экосистемой пакетов GAS:

function myFunction() { // default GAS function name
  const url = "https://raw.githubusercontent.com/labnol/apps-script-starter/master/scopes.md";
  const res = UrlFetchApp.fetch(url).getContentText();
  const data = [];
  
  for (const line of res.split("\n")) {
    const chunks = line
      .replace(/[*`]/g, "")
      .split("|")
      .slice(1, 3)
      .filter(e => e !== " -- ")
      .map(e => e.trim());

    if (chunks.length) {
      data.push(chunks);
    }
  }
  
  console.info(data);
}

Выход:

Logging output too large. Truncating output. [
  [ 'Google OAuth API Scope', 'Scope Description' ],
  [ 'Cloud SQL Admin API v1beta4', '' ],
  [ 'View and manage your data across Google Cloud Platform services',
    'https://www.googleapis.com/auth/cloud-platform' ],
  [ 'Manage your Google SQL Service instances',
    'https://www.googleapis.com/auth/sqlservice.admin' ],
  [ '', '' ],
  [ 'Android Management API v1', '' ],
  // ...

Анализ необработанной уценки немного сложнее, но должен быть достаточно надежным. Если это не так, попробуйте один из других вариантов.


Если вы не хотите использовать GAS, ваш исходный код работает для меня в Node 20.11.1:

const cheerio = require("cheerio"); // ^1.0.0-rc.12 or rc.10

const url = "https://github.com/labnol/apps-script-starter/blob/master/scopes.md";

fetch(url)
  .then(res => {
    if (!res.ok) {
      throw Error(res.statusText);
    }

    return res.text();
  })
  .then(html => {
    const $ = cheerio.load(html);
    const data = $("tbody")
      .find("td")
      .toArray()
      .map(x => $(x).text());
    console.info(data);
  })
  .catch(err => console.error(err));

Выход:

[
  'Cloud SQL Admin API v1beta4',
  '',
  'View and manage your data across Google Cloud Platform services',
  'https://www.googleapis.com/auth/cloud-platform',
  'Manage your Google SQL Service instances',
  'https://www.googleapis.com/auth/sqlservice.admin',
  '',
  '',
  'Android Management API v1',
  // ... 1360 total items ...
]

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

// ...
const $ = cheerio.load(html);
const data = [...$("tr")].map(e =>
  [...$(e).find("td, th")].map(e => $(e).text().slice(0, 25))
);
console.table(data.slice(0, 10));
// ...

Вот результат, аналогичный выводу сценария GAS (удалите вызовы срезов, чтобы увидеть все данные без усечения):

┌─────────┬─────────────────────────────┬─────────────────────────────┐
│ (index) │ 0                           │ 1                           │
├─────────┼─────────────────────────────┼─────────────────────────────┤
│ 0       │ 'Google OAuth API Scope'    │ 'Scope Description'         │
│ 1       │ 'Cloud SQL Admin API v1bet' │ ''                          │
│ 2       │ 'View and manage your data' │ 'https://www.googleapis.co' │
│ 3       │ 'Manage your Google SQL Se' │ 'https://www.googleapis.co' │
│ 4       │ ''                          │ ''                          │
│ 5       │ 'Android Management API v1' │ ''                          │
│ 6       │ 'Manage Android devices an' │ 'https://www.googleapis.co' │
│ 7       │ ''                          │ ''                          │
│ 8       │ 'YouTube Data API v3'       │ ''                          │
│ 9       │ 'Manage your YouTube accou' │ 'https://www.googleapis.co' │
└─────────┴─────────────────────────────┴─────────────────────────────┘

Вы можете обработать это дальше, чтобы сгруппировать по подкатегориям. Строки с двумя пустыми ячейками являются разделителем между категориями области (я думаю, я не эксперт в предметной области), а строки с пустой правой ячейкой являются заголовками категорий. Вот пример группировки по подкатегориям и прикрепления заголовков к каждой ячейке:

const grouped = [];
const headers = data[0];

for (const row of data.slice(1)) {
  if (row.every(e => e === "")) {
    continue;
  } else if (row[1] === "") {
    grouped.push({title: row[0], items: []});
  } else {
    grouped
      .at(-1)
      .items.push(
        Object.fromEntries(
          row.map((e, i) => [headers[i], e])
        )
      );
  }
}

console.info(JSON.stringify(grouped, null, 2));

Я протестировал этот пример кода обработки как в GAS, так и в Node.

Кажется, единственная разница в 1.0.0-rc.10 ГАЗе и 1.0.0-rc.12. Запрос, похоже, не заблокирован. Однако, если ua действительно является проблемой, его невозможно изменить в GAS

TheMaster 16.03.2024 17:12

Спасибо за это. Я попробовал 1.0.0-rc.10, и результат у меня тот же, так что проблема, вероятно, не в Cheerio. OP может распечатать свой HTML-код, полученный при выборке, чтобы увидеть, соответствует ли он странице, или он каким-либо образом заблокирован или изменен. Использование API должно обходить любые блокировки, если это происходит.

ggorlen 16.03.2024 17:22

@TheMaster Думаю, у меня это работает в GAS.

ggorlen 16.03.2024 19:17

Круто 👍👍👍👍(PS: нет лучшего способа, чем DriveApp.createFile)

TheMaster 17.03.2024 01:48

Спасибо всем за помощь, я тоже нашел решение своего вопроса, выложу позже.

Antonio 17.03.2024 10:40

Мой способ решения этой проблемы немного груб, но вот чего мне удалось достичь. Я пока еще начинающий разработчик-самоучка)

Вот мой код:

    function myFunction() {
  var [c, arr] = [[], []];
  UrlFetchApp.fetch("https://raw.githubusercontent.com/labnol/apps-script-starter/master/scopes.md")
    .getContentText()
    .split("\n")
    .forEach((item, i) => {
      c.push(item.replace(/[*`|]/g, " ").trim().split("|||"))
    });
  var v = c.splice(19);
  v.forEach((item, i) => {
    if (item.length == 2 && item[0] == '' && item[1] == '') {
      v.splice(i, 1);
    }
  })
  v.forEach((item, i) => {
    if (item[0].indexOf("API") == -1) {
      arr[arr.length - 1].push(item[0]);
    } else { arr.push(item); }
  })
  var g = tesssst(arr);
  console.info(g);
}

     function tesssst(inputArray) {
          var outputArray = [];
          inputArray.forEach((row, i) => {
            var newRow = [];
            newRow.push(row[0]);
            newRow.push(row.slice(1).join(','));
            outputArray.push(newRow);
          });
          return outputArray;
        }

Вывод будет такой:

[ [ 'Cloud SQL Admin API v1beta4',
    'View and manage your data across Google Cloud Platform services  https://www.googleapis.com/auth/cloud-platform,Manage your Google SQL Service instances  https://www.googleapis.com/auth/sqlservice.admin,' ],
  [ 'Android Management API v1',
    'Manage Android devices and apps for your customers  https://www.googleapis.com/auth/androidmanagement,' ],
  [ 'YouTube Data API v3',
    'Manage your YouTube account  https://www.googleapis.com/auth/youtube,See, edit, and permanently delete your YouTube videos, ratings, comments and captions  https://www.googleapis.com/auth/youtube.force-ssl,View your YouTube account  https://www.googleapis.com/auth/youtube.readonly,Manage your YouTube videos  https://www.googleapis.com/auth/youtube.upload,View and manage your assets and associated content on YouTube  https://www.googleapis.com/auth/youtubepartner,View private information of your YouTube channel relevant during the audit process with a YouTube partner  https://www.googleapis.com/auth/youtubepartner-channel-audit,' ],
  [ 'Cloud Testing API v1',
    'View and manage your data across Google Cloud Platform services  https://www.googleapis.com/auth/cloud-platform,View your data across Google Cloud Platform services  https://www.googleapis.com/auth/cloud-platform.read-only,' ],
  [ 'DoubleClick Search API v2',
    'View and manage your advertising data in DoubleClick Search  https://www.googleapis.com/auth/doubleclicksearch,' ],
  [ 'Tasks API v1',
    'Create, edit, organize, and delete all your tasks  https://www.googleapis.com/auth/tasks,View your tasks  https://www.googleapis.com/auth/tasks.readonly,' ],
  [ 'Calendar API v3',
    'See, edit, share, and permanently delete all the calendars you can access using Google Calendar  https://www.googleapis.com/auth/calendar,View and edit events on all your calendars  https://www.googleapis.com/auth/calendar.events,View events on all your calendars  https://www.googleapis.com/auth/calendar.events.readonly,View your calendars  https://www.googleapis.com/auth/calendar.readonly,View your Calendar settings  https://www.googleapis.com/auth/calendar.settings.readonly,' ],
  [ 'Google Play Custom App Publishing API v1',
    'View and manage your Google Play Developer account  https://www.googleapis.com/auth/androidpublisher,' ],
  [ 'YouTube Analytics API v2',
    'Manage your YouTube account  https://www.googleapis.com/auth/youtube,View your YouTube account  https://www.googleapis.com/auth/youtube.readonly,View and manage your assets and associated content on YouTube  https://www.googleapis.com/auth/youtubepartner,View monetary and non-monetary YouTube Analytics reports for your YouTube content  https://www.googleapis.com/auth/yt-analytics-monetary.readonly,View YouTube Analytics reports for your YouTube content  https://www.googleapis.com/auth/yt-analytics.readonly,' ],
  [ 'Cloud Healthcare API v1alpha2',
    'View and manage your data across Google Cloud Platform services  https://www.googleapis.com/auth/cloud-platform,' ],
  [ 'Cloud Shell API v1',
    'View and manage your data across Google Cloud Platform services  https://www.googleapis.com/auth/cloud-platform,' ],
  [ 'Content API for Shopping v2.1',
    'Manage your product listings and accounts for Google Shopping  https://www.googleapis.com/auth/content,' ]]

Другие вопросы по теме