如何使用Google-apps脚本从(通过API)延迟加载的网页上抓取数据?

时间:2019-07-16 09:25:09

标签: google-apps-script web-scraping xmlhttprequest

我正在尝试使用Google-apps-script创建一个自动过程,以从此类页面中抓取价格数据:

https://www.barchart.com/stocks/quotes/$AVVN/price-history/historical

最具挑战性的部分是,网页上的数据是“延迟加载”的,因此,我在其他网页上使用的“传统”转义方法在这里无效。

我已经考虑了解决此问题的其他方法-但是:

  • Barchart不提供例如$ AVVN通过http: //marketdata.websol.barchart.com/getHistory
  • 我不想使用“下载”按钮-因为这需要 自动登录。
  • ImportXML()不起作用(它适用于网页上的其他表, 但不适合我想要的那个。)

我在以下帖子中发现了类似的问题-收到了来自omegastripes的非常详细和有益的答复: Open webpage, select all, copy into sheet

-但是当我运行我的代码时:

function test(){
  var url = 'https://www.barchart.com/proxies/core-api/v1/historical/get?symbol=%24AVVN&fields=tradeTime.format(m%2Fd%2Fy)%2CopenPrice%2ChighPrice%2ClowPrice%2ClastPrice%2CpriceChange%2Cvolume%2CsymbolCode%2CsymbolType&startDate=2019-04-15&endDate=2019-07-15&type=eod&orderBy=tradeTime&orderDir=desc&limit=2000&meta=field.shortName%2Cfield.type%2Cfield.description&raw=1'; 
  var options = {
     "muteHttpExceptions": false
  };
  var response   = UrlFetchApp.fetch(url, options);   
  Logger.log(response);
}

-然后出现以下错误:

Request failed for https://www.barchart.com/proxies/core-api/v1/historical/get?symbol=%24AVVN&fields=tradeTime.format(m%2Fd%2Fy)%2CopenPrice%2ChighPrice%2ClowPrice%2ClastPrice%2CpriceChange%2Cvolume%2CsymbolCode%2CsymbolType&startDate=2019-04-15&endDate=2019-07-15&type=eod&orderBy=tradeTime&orderDir=desc&limit=2000&meta=field.shortName%2Cfield.type%2Cfield.description&raw=1 returned code 500. Truncated server response: <!doctype html> <html itemscope itemtype="http://schema.org/WebPage" lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="wi... (use muteHttpExceptions option to examine full response) (line 57, file "DS#1")

基本上是“ 糟糕,出了点问题。很抱歉,此页面似乎有问题。” ...如果将地址粘贴到浏览器中。

我的问题是:如何从该页面抓取数据,或者Barchart现在成功阻止了此抓取选项?

2 个答案:

答案 0 :(得分:1)

我发现获取数据的唯一方法是使用变通方法,即从控制台获取请求URL,但是当发生以下情况时,还必须在选项中添加“ x-xsrf-token”和“ cookie”标头使用fetch()方法[1]。

您也可以从控制台获取“ x-xsrf-token”和“ cookie”请求标头。唯一的问题是cookie和xsrf令牌最多可以使用2个小时,这是因为它们实现了跨站点请求伪造保护[2]:

enter image description here

这是我测试并工作的代码:

function testFunction() {
  var url = 'https://www.barchart.com/proxies/core-api/v1/historical/get?symbol=%24AVVN&fields=tradeTime.format(m%2Fd%2Fy)%2CopenPrice%2ChighPrice%2ClowPrice%2ClastPrice%2CpriceChange%2Cvolume%2CsymbolCode%2CsymbolType&startDate=2019-04-16&endDate=2019-07-16&type=eod&orderBy=tradeTime&orderDir=desc&limit=2000&meta=field.shortName%2Cfield.type%2Cfield.description&raw=1';

  var map = {
    "x-xsrf-token": "XXXXX",
    "cookie": "XXXXX"
  }

  var options = {
     "method": "get", 
     "muteHttpExceptions": false,
     "headers": map
  };
  var response = UrlFetchApp.fetch(url, options);   
  Logger.log(response);

  var json = JSON.parse(response);
  Logger.log(json.data[0]);
}

[1] https://developers.google.com/apps-script/reference/url-fetch/url-fetch-app

[2] Difference between CSRF and X-CSRF-Token

答案 1 :(得分:0)

您不能使用Google Apps脚本延迟加载网页,因为它们仅返回网页的HTML内容,并且不等待JavaScript加载后再返回内容。

一种可能的解决方案是将Google Cloud Functions与Puppeteer结合使用,以加载页面。 Cloud Function提供了一个HTTP API,可以使用URLFetch服务从Apps脚本直接调用该API。