【问题标题】:To exceed the ImportXML limit on Google Spreadsheet超过 Google 电子表格的 ImportXML 限制
【发布时间】:2016-08-18 09:37:12
【问题描述】:

我现在陷入了一个“抓取问题”。特别是我想从网页中提取作者姓名到谷歌电子表格。实际上函数=IMPORTXML(A2,"//span[@class='author vcard meta-item']") 是有效的,但是在我增加链接数量后,它开始无限加载。

于是我研究了一下,发现这个问题是因为google有限制。

有没有人知道超出限制或脚本,我可以“轻松复制”? - 我真的没有编码的预感。

【问题讨论】:

标签: javascript google-apps-script web-scraping google-sheets custom-function


【解决方案1】:

我创建了一个自定义导入函数,它克服了 IMPORTXML 的所有限制。我有一张在大约 800 个单元格中使用它的表格,效果很好。

它利用 Google Sheet 的自定义脚本(工具 > 脚本编辑器...)并使用正则表达式而不是 xpath 搜索内容。

function importRegex(url, regexInput) {
  var output = '';
  var fetchedUrl = UrlFetchApp.fetch(url, {muteHttpExceptions: true});
  if (fetchedUrl) {
    var html = fetchedUrl.getContentText();
    if (html.length && regexInput.length) {
      output = html.match(new RegExp(regexInput, 'i'))[1];
    }
  }
  // Grace period to not overload
  Utilities.sleep(1000);
  return output;
}

然后您可以像使用任何函数一样使用此函数。

=importRegex("https://example.com", "<title>(.*)<\/title>")

当然,你也可以引用单元格。

=importRegex(A2, "<title>(.*)<\/title>")

如果您不想在输出中看到 HTML 实体,可以使用此功能。

var htmlEntities = {
  nbsp:  ' ',
  cent:  '¢',
  pound: '£',
  yen:   '¥',
  euro:  '€',
  copy:  '©',
  reg:   '®',
  lt:    '<',
  gt:    '>',
  mdash: '–',
  ndash: '-',
  quot:  '"',
  amp:   '&',
  apos:  '\''
};

function unescapeHTML(str) {
    return str.replace(/\&([^;]+);/g, function (entity, entityCode) {
        var match;

        if (entityCode in htmlEntities) {
            return htmlEntities[entityCode];
        } else if (match = entityCode.match(/^#x([\da-fA-F]+)$/)) {
            return String.fromCharCode(parseInt(match[1], 16));
        } else if (match = entityCode.match(/^#(\d+)$/)) {
            return String.fromCharCode(~~match[1]);
        } else {
            return entity;
        }
    });
};

大家一起……

function importRegex(url, regexInput) {
  var output = '';
  var fetchedUrl = UrlFetchApp.fetch(url, {muteHttpExceptions: true});
  if (fetchedUrl) {
    var html = fetchedUrl.getContentText();
    if (html.length && regexInput.length) {
      output = html.match(new RegExp(regexInput, 'i'))[1];
    }
  }
  // Grace period to not overload
  Utilities.sleep(1000);
  return unescapeHTML(output);
}

var htmlEntities = {
  nbsp:  ' ',
  cent:  '¢',
  pound: '£',
  yen:   '¥',
  euro:  '€',
  copy:  '©',
  reg:   '®',
  lt:    '<',
  gt:    '>',
  mdash: '–',
  ndash: '-',
  quot:  '"',
  amp:   '&',
  apos:  '\''
};

function unescapeHTML(str) {
    return str.replace(/\&([^;]+);/g, function (entity, entityCode) {
        var match;

        if (entityCode in htmlEntities) {
            return htmlEntities[entityCode];
        } else if (match = entityCode.match(/^#x([\da-fA-F]+)$/)) {
            return String.fromCharCode(parseInt(match[1], 16));
        } else if (match = entityCode.match(/^#(\d+)$/)) {
            return String.fromCharCode(~~match[1]);
        } else {
            return entity;
        }
    });
};

【讨论】:

  • 假设想在此页面上获得 2.49% 的年利率:actorsfcu.com/loans/auto 使用此功能,我将如何获得它?我尝试了正则表达式,但无法实现。
  • &gt;(.*?%\s+apr)
  • 我们如何通过您的函数传递正则表达式参数中的引号?例如"(.*?%\s+apr)
  • 我不确定您所说的“通过引号”是什么意思。你能打开一个新问题吗?
  • 为这个伟大的功能点赞...按照之前的例子如果A1="apr" 理论上可以像&gt;(.*?%\s+"&amp;A1&amp;") 这样的东西但是这个函数似乎格式不正确并返回错误.. . 你知道是否可以在正则表达式部分传递单元格值?
【解决方案2】:

没有这样的脚本超出限制。由于代码是在 Google 机器(服务器)上运行的,因此您不能作弊。 一些限制已绑定到您的电子表格,因此您可以尝试使用多个电子表格,如果有帮助的话。

【讨论】:

  • 谢谢,这是个好主意,但问题在于,我不知道将数据划分为不同电子表格的确切限制。 importxml 函数也需要很长时间才能提取 ?span 类?我在找。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-04-24
  • 2012-12-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多