【问题标题】:Not able to scrape data无法抓取数据
【发布时间】:2019-04-01 03:08:28
【问题描述】:

我刚刚开始使用 Google Apps 脚本。由于最佳编码实践建议使用尽可能少的表格公式,因此我尝试使用 GAS Parser 进行网络抓取,然后将数据推送到我的电子表格中。

在我的工作表中,使用以下公式返回一个数据表,这正是我从 GAS 中寻找的数据。

=IMPORTHTML("https://finance.yahoo.com/quote/BOO.L/history?p=BOO.L", "table", 1)

herehere 这两个问题很相似,但尝试这些方法也失败了。似乎我没有得到完整的页面内容,因为当我在下面的代码之后查看 Logger.log() 中的数据时,我没有得到任何类似于我需要的页面的内容。

UrlFetchApp.fetch(url).getContentText();

由于运行公式似乎可以完美地获取数据,我只能假设我自己的代码存在问题,但无法确定问题出在哪里。这是我迄今为止尝试过的代码;

function scrapeData() {
var url = "https://finance.yahoo.com/quote/BARC.L/history?p=BARC.L";
var fromText = '<td class="Py(10px) Ta(start) Pend(10px)"><span>';
var toText = '</span></td>';
var content = UrlFetchApp.fetch(url).getContentText();
var scraped = Parser
          .data(content)
          .from(fromText)
          .to(toText)
          .iterate();

Logger.log(scraped)
}

非常感谢任何指导。

【问题讨论】:

  • 为什么不直接使用 =GOOGLEFINANCE()?
  • 根据问题,我想使用尽可能少的电子表格函数。
  • Parser 不是内置的 Google Apps 脚本类。你在使用图书馆吗?
  • 最佳编码实践?为什么要使用 js 代码,而您可以使用单个公式代码来做到这一点?
  • 我曾经使用java从雅虎财经获取历史数据。然后在 2017 年被 Verizon 收购时,它不再起作用了。而且我想不出办法让它发挥作用,所以我开始使用 GOOGLEFINANCE。我现在像蛤蜊一样快乐。

标签: google-apps-script web-scraping html-parsing


【解决方案1】:
  • 您希望使用 Google Apps 脚本检索 URL 中的值并将其放入电子表格。

如果我的理解是正确的,那么这个修改呢?我认为您的情况有几个答案。因此,请将此视为其中之一。

修改点:

  • 为了检索表,我使用了ParserXmlService
    1. 使用Parser检索表作为字符串值。
    2. 使用XmlService 解析表。我认为XmlService 让我们可以轻松解析表格。

XmlService是强大的XML解析工具。因此,当它可以用于 HTML 时,它使我们更容易从 HTML 中检索值。但是最近大部分的HTML都不能直接被XmlService解析。所以我总是使用这个流程。

修改脚本:

function scrapeData() {
  // Retrieve table as a string using Parser.
  var url = "https://finance.yahoo.com/quote/BOO.L/history?p=BOO.L";
  // var url = "https://finance.yahoo.com/quote/BARC.L/history?p=BARC.L";
  var fromText = '<div class="Pb(10px) Ovx(a) W(100%)" data-reactid="30">';
  var toText = '<div class="Mstart(30px) Pt(10px)"';
  var content = UrlFetchApp.fetch(url).getContentText();
  var scraped = Parser.data(content).from(fromText).to(toText).build();

  // Parse table using XmlService.
  var root = XmlService.parse(scraped).getRootElement();
  // Retrieve header
  var headerTr = root.getChild("thead").getChildren();
  var res = headerTr.map(function(e) {return e.getChildren().map(function(f) {return f.getValue()})});
  var len = res[0].length;
  // Retrieve values
  var valuesTr = root.getChild("tbody").getChildren();
  var values = valuesTr.map(function(e) {return e.getChildren().map(function(f) {return f.getValue()})})
  .map(function(e) {return e.length == len ? e : e.concat(Array.apply(null, new Array(len - e.length)).map(String.prototype.valueOf,""))});
  Array.prototype.push.apply(res, values);

  // Put the result to the active spreadsheet.
  var ss = SpreadsheetApp.getActiveSheet();
  ss.getRange(1, 1, res.length, res[0].length).setValues(res);
}

注意:

  • 在运行这个修改后的脚本之前,请安装Parser的GAS库。
  • 在我的环境中,我可以确认修改后的脚本适用于p=BOO.Lp=BARC.L。我无法确认其他人。所以当你尝试其他的时候,如果出现错误,请修改脚本。

参考:

如果这不是你想要的,我很抱歉。

【讨论】:

  • 这在 Parser 中完美运行 - XmlService 无疑是一个强大的组合。正如你提到的,这个问题有几个答案。在我使用过的其他语言(Python 和 R)中,内置了用于直接使用 html 表进行密封的函数。你知道在 GAS 或 JS 中是否存在类似的东西吗?非常感谢您的帮助。
  • @redbaron1981 感谢您的回复。我很高兴你的问题得到了解决。在 GAS,没有针对这种情况的方法。所以我使用了 Parser 和 XmlService。在 Javascript 中,这个怎么样? developer.mozilla.org/en-US/docs/Web/API/DOMParser如果没有你想要的,对不起。
  • 我也在尝试以类似的方式从这里抓取数据; stooq.com/q/d/?s=boo.uk。您知道为什么我会收到“第 1 行错误:序言中不允许内容。”吗?谢谢。
  • @redbaron1981 我认为这是一个新问题。并且由于 URL 与这个问题不同,这个脚本不能用于它。我也不确定你想要的结果。那么您可以将其发布为新问题吗?当您发布它时,请包含详细信息。这样,它将帮助包括我在内的用户思考您的解决方案。
  • 我听取了您的建议并在此处发布了一个新问题。 stackoverflow.com/questions/53081241/…
猜你喜欢
  • 1970-01-01
  • 2017-06-18
  • 2018-07-31
  • 2016-03-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多