Ошибка: ресурс в содержимом URL превысил максимальный размер. - Можно ли воспроизвести IMPORT XML по сценарию, чтобы избежать подобных проблем? - PullRequest
0 голосов
/ 22 февраля 2020
=IF(ARRAYFORMULA(JOIN("-",TRIM(IMPORTXML("http://old.statarea.com/","//tr[3]/th[2]/b | //tr[3]/th[3]/b | //tr[3]/th[7]/b | //tr[3]/th[8]/b | //tr[3]/th[9]/b | //tr[3]/th[16]/b"))))="Host-Guest-1-X-2-2.5",
{IMPORTXML(IMPORTXML("http://old.statarea.com/","//tr/td/a[4]/@href"),"//tr/td[2]/a"),
IMPORTXML(IMPORTXML("http://old.statarea.com/","//tr/td/a[4]/@href"),"//tr/td[3]/a"),
ARRAYFORMULA(VALUE(TEXT(1/QUERY(SUBSTITUTE(IMPORTXML(IMPORTXML("http://old.statarea.com/","//tr/td/a[4]/@href"),"//tr/td[7]"),"HX",""),"Where Col1 is not null"),"0.00"))),
ARRAYFORMULA(VALUE(TEXT(1/QUERY(SUBSTITUTE(IMPORTXML(IMPORTXML("http://old.statarea.com/","//tr/td/a[4]/@href"),"//tr/td[8]"),"H2",""),"Where Col1 is not null"),"0.00"))),
ARRAYFORMULA(VALUE(TEXT(1/QUERY(SUBSTITUTE(IMPORTXML(IMPORTXML("http://old.statarea.com/","//tr/td/a[4]/@href"),"//tr/td[9]"),"HX",""),"Where Col1 is not null"),"0.00"))),
ARRAYFORMULA(VALUE(TEXT(1/QUERY(SUBSTITUTE(IMPORTXML(IMPORTXML("http://old.statarea.com/","//tr/td/a[4]/@href"),"//tr/td[16]"),"hc2",""),"Where Col1 is not null"),"0.00")))},
"Off")

Еще раньше сегодня он работал отлично, показывая все данные. Но теперь эта ошибка всегда появляется, даже если я пытаюсь импортировать что-то очень простое, например:

=IMPORTXML("http://old.statarea.com/","//tr/td/a[4]/@href")

Я хотел бы знать, возможно ли воспроизвести это (полный импорт, который я поставил в начале вопроса) импортируйте через Google App Script (GAS), и если кто-то сможет показать мне, как это будет выглядеть, проблем с лимитом больше не будет.

1 Ответ

2 голосов
/ 23 февраля 2020
  • Вы хотите преобразовать формулу в своем вопросе в Google Apps Script.
  • Базовый URL-адрес http://old.statarea.com/.
  • . Вы хотите получить значения, изменив данные. URL с IMPORTXML("http://old.statarea.com/","//tr/td/a[4]/@href") и IMPORTXML("http://old.statarea.com/","//tr/td/a[5]/@href").
  • В качестве значений вы хотите получить td[7], td[8], td[9] и td[16].
  • Например, вы хотите вычислить полученное значение 50% как 1 / 0.5 и хотите использовать его в качестве значения для размещения в электронной таблице.

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

Поток:

В этом случае я получаю нужные вам значения за 3 шага.

  1. Получить часть значений из HTML с использованием Parser, который является библиотекой скриптов Служб Google.
  2. Выполните синтаксический анализ полученных HTML с помощью XmlService, удалив ненужные значения.
  3. Извлеките значения результатов, используя XmlService.

Использование:

1. Установите "Parser"

Пожалуйста, установите библиотеку скриптов Служб Google "Parser" .

2. Пример сценария 1:

Это пример сценария. В этом сценарии вы можете использовать это как пользовательскую функцию. Поэтому, пожалуйста, поместите формулу =sample(5) в ячейку.

function sample(placeOfUrl) {
  // Retrieve URL.
  var baseUrl = "http://old.statarea.com/";
  var res1 = UrlFetchApp.fetch(baseUrl);
  if (res1.getResponseCode() != 200) throw new Erro("URL cannot be used.");
  const from = '<td style="padding-top: 10px; text-align: center;">';
  const to = '&nbsp;&nbsp;</td>';
  const htmlData1 = (from + Parser.data(res1.getContentText()).from(from).to(to).build() + to).replace(/\&nbsp;/g, "");
  const xmlRoot = XmlService.parse(htmlData1).getRootElement();
  const c = xmlRoot.getChildren()[placeOfUrl - 1];
  if (!c) return;
  const url = c.getAttribute("href").getValue();

  // Parse HTML data.
  const res2 = UrlFetchApp.fetch(url);
  if (res2.getResponseCode() != 200) throw new Erro("URL for retrieving data cannot be used.");
  const htmlData2 = res2.getContentText();
  const parsedData1 = Parser.data(htmlData2).from('<table class="style_1" cellspacing="0" cellpadding="0" width="918" border="0">').to('</table>').build();
  const parsedData2 = Parser.data(parsedData1).from("<tr>").to("</tr>").iterate();
  const data = parsedData2
    .filter(function(e) {return /^<td width="35" align="center">/.test(e)})
    .map(function(e) {return "<content>" + e.match(/<td.+?\/td>/g).map(function(f) {return f.replace(/\&nbsp\;|<div.+?>|<\/div>|<img.+?>|<input.+?>|\&team_guest|<\/h.+?>|\&/g, "")}).join("") + "</content>"})
    .join("");
  const xmlRootContent = XmlService.parse("<root>" + data + "</root>").getRootElement();

  // Retrieve result values.
  const content = xmlRootContent.getChildren();
  const values = content.reduce((ar1, e) => {
    const temp = e.getChildren().reduce((ar2, f, j) => {
      if (f) {
        if (f.getChild("a")) {
          const t = f.getChild("a").getValue()
          if (t) ar2.push(t);
        } else {
          if (f.getAttribute("style")) {
            const v = f.getValue();
            if (v && [6, 7, 8, 15].includes(j)) {
              ar2.push(Math.round((1 / (parseInt(v, 10) / 100)) * 100) / 100);
            }
          }
        }
      }
      return ar2;
    }, []);
    ar1.push(temp);
    return ar1;
  }, []);

  return values;
}
Результат:

enter image description here

3. Пример сценария 2:

Скопируйте и вставьте следующий сценарий в редактор сценариев. В этом случае используется связанный с контейнером скрипт. При запуске сценария в редакторе сценариев значения помещаются в электронную таблицу.

function myFunction() {
  var placeOfUrl = "5";  // Here, you can change the URL for retrieving values.

  // Retrieve URL.
  var baseUrl = "http://old.statarea.com/";
  var res1 = UrlFetchApp.fetch(baseUrl);
  if (res1.getResponseCode() != 200) throw new Erro("URL cannot be used.");
  const from = '<td style="padding-top: 10px; text-align: center;">';
  const to = '&nbsp;&nbsp;</td>';
  const htmlData1 = (from + Parser.data(res1.getContentText()).from(from).to(to).build() + to).replace(/\&nbsp;/g, "");
  const xmlRoot = XmlService.parse(htmlData1).getRootElement();
  const c = xmlRoot.getChildren()[placeOfUrl - 1];
  if (!c) return;
  const url = c.getAttribute("href").getValue();

  // Parse HTML data.
  const res2 = UrlFetchApp.fetch(url);
  if (res2.getResponseCode() != 200) throw new Erro("URL for retrieving data cannot be used.");
  const htmlData2 = res2.getContentText();
  const parsedData1 = Parser.data(htmlData2).from('<table class="style_1" cellspacing="0" cellpadding="0" width="918" border="0">').to('</table>').build();
  const parsedData2 = Parser.data(parsedData1).from("<tr>").to("</tr>").iterate();
  const data = parsedData2
    .filter(function(e) {return /^<td width="35" align="center">/.test(e)})
    .map(function(e) {return "<content>" + e.match(/<td.+?\/td>/g).map(function(f) {return f.replace(/\&nbsp\;|<div.+?>|<\/div>|<img.+?>|<input.+?>|\&team_guest|<\/h.+?>|\&/g, "")}).join("") + "</content>"})
    .join("");
  const xmlRootContent = XmlService.parse("<root>" + data + "</root>").getRootElement();

  // Retrieve result values.
  const content = xmlRootContent.getChildren();
  const values = content.reduce((ar1, e) => {
    const temp = e.getChildren().reduce((ar2, f, j) => {
      if (f) {
        if (f.getChild("a")) {
          const t = f.getChild("a").getValue()
          if (t) ar2.push(t);
        } else {
          if (f.getAttribute("style")) {
            const v = f.getValue();
            if (v && [6, 7, 8, 15].includes(j)) {
              ar2.push(Math.round((1 / (parseInt(v, 10) / 100)) * 100) / 100);
            }
          }
        }
      }
      return ar2;
    }, []);
    ar1.push(temp);
    return ar1;
  }, []);

  // Put values to Spreadsheet.
  var sheetname = "Sheet5";
  var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(sheetname);
  sheet.getRange(sheet.getLastRow() + 1, 1, values.length, values[0].length).setValues(values);
}

Примечание:

  • Я подтвердил, что в Проект GAS в вашей общей электронной таблице используется V8. Так выше сценарий также использовал V8. Пожалуйста, будьте осторожны.

  • Когда размер HTML данных из "http://old.statarea.com/" составляет около 1 МБ, можно использовать вашу формулу. Но когда размер HTML данных из «http://old.statarea.com/» приближается к 2 МБ, возникает ошибка. Это уже упоминалось в вашем вопросе.

    • В этом случае кажется, что URL-адрес изменился. Если размер HTML данных из «http://old.statarea.com/» составляет около 1 МБ, var placeOfUrl = "4" - это тот же URL-адрес, что и у IMPORTXML("http://old.statarea.com/","//tr/td/a[4]/@href"). Но когда размер HTML данных из "http://old.statarea.com/" приближается к 2 МБ, var placeOfUrl = "5" - это тот же URL-адрес, что и IMPORTXML("http://old.statarea.com/","//tr/td/a[4]/@href"). Но в этой ситуации я не уверен, всегда ли это происходит. Я прошу прощения за это.
  • Когда спецификация страницы URL изменяется, скрипт не может быть использован. Поэтому, пожалуйста, будьте осторожны.

Ссылки:

Если я неправильно понял ваш вопрос, и это не то направление, которое вы хотите, я прошу прощения.

...