You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用AppScript带Cookie从动态接口取数据到Google Sheets并持久化

解决Google Script循环获取分页交易数据并写入Sheet的问题

问题背景

作为新手开发者,我用Google Script从网站接口获取交易数据,但现有代码只能单次请求。接口URL末尾的数字串(如示例中的63549969)每次请求都会变化——它是上一次请求返回数据最后一条的id,网站前端通过循环调用loadMoreTrades加载全部数据,现在需要实现自动获取完整交易数据并持久化到Google Sheets指定工作表。

现有单次请求代码:

function testFunction() {
var url = 'https://trader.xxx.app/api/data/trade/20058760/63549969';

var map = {

"cookie": ".AspNetCore.Antiforgery.DvnwCO4RNgs=CfDJ8Lq5zSRi6AVFv2yxRTgHigNGdKZPKdG-c7U33EUIYc-90Mb0y3YYAH7ntiRp9hRygngVce88wIsQq3XSCgA7DYPWxVPKSHZLxKx6Q6R3Q826ulDmwvsoX_N7pESn3TFRWe2_u0Krl0c74_Z4UIeiOWc; .AspNetCore.Cookies=CfDJ8Lq5zSRi6AVFv2yxRTgHigNoZOuFxznxPef2Z2wMA5vKVkuq3rGG6mcmbvh77X3As3at5-Piq3tl79DuzF78LOfEaROXbojr_QJ0n3781h9ohTC_dvVMxfUupSmIAuJCVGP5g56ix_1U1PaWNn7Tj2GYZuVuQ6__xbfIsC58y0aJ8DqLYU9EU62bOVGGIts6Cic-pEfnaNLomkPj-J3qsAvZHliSXt3f2n5JLr4CoYS1FYg9vGYpw7upXyY9FgBC6bXdtjEqIISnirLa3ird1OXeAK7fO9Onk8r2EonGXK1FgDcHMkb0bE4ZtAWzkKvMQGZq07y0iVZL4VFCHuLEAPZ0-ccndGZVvvneUsejS-iT"
}

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


var json = JSON.parse(response.getContentText());
//Logger.log(json);

// Use Spreadsheet
var ss = SpreadsheetApp.getActiveSpreadsheet();
var balancesSheet = ss.getSheetByName("test");
var values = json.map(({ id, ticket, side, openTime, closeTime, symbol, lots, profit }) => [id, ticket, side, openTime, closeTime, symbol, lots, profit]);
Logger.log(values)
balancesSheet.getRange(balancesSheet.getLastRow(), 1, values.length, 
values[0].length).setValues(values);


}

网站前端加载数据的核心逻辑:

function loadMoreTrades()
     {
         $.get("/api/data/trade/20058760/"+tradeId, function(data, status){
             if(data.length==0){
                 $('#btnMore').css('display','none');
             }
             else {
                 for(i=0; i<data.length;i++){
                     tradeId = data[i].id;
                     $('#tradeList > tbody:last-child').append(`<tr> <td>${data[i].ticket}</td> <td>${data[i].side}</td> <td>${data[i].openTime}</td> <td>${data[i].closeTime}</td> <td>${data[i].symbol}</td> <td>${data[i].lots}</td> <td>${data[i].profit}</td> </tr>`);
                 }
                 numLoadedTrades += data.length;
                 if (numLoadedTrades == 248) {
                     $('#btnMore').css('display', 'none');
                 }
             }
         });
        }

解决方案代码

function fetchAllTrades() {
  // 基础URL,替换固定用户ID(20058760)为你的实际ID
  const baseUrl = 'https://trader.xxx.app/api/data/trade/20058760/';
  // 初始请求的ID,第一次请求用你当前的起始ID
  let currentTradeId = '63549969';
  // 请求头,保持你的Cookie
  const headers = {
    "cookie": ".AspNetCore.Antiforgery.DvnwCO4RNgs=CfDJ8Lq5zSRi6AVFv2yxRTgHigNGdKZPKdG-c7U33EUIYc-90Mb0y3YYAH7ntiRp9hRygngVce88wIsQq3XSCgA7DYPWxVPKSHZLxKx6Q6R3Q826ulDmwvsoX_N7pESn3TFRWe2_u0Krl0c74_Z4UIeiOWc; .AspNetCore.Cookies=CfDJ8Lq5zSRi6AVFv2yxRTgHigNoZOuFxznxPef2Z2wMA5vKVkuq3rGG6mcmbvh77X3As3at5-Piq3tl79DuzF78LOfEaROXbojr_QJ0n3781h9ohTC_dvVMxfUupSmIAuJCVGP5g56ix_1U1PaWNn7Tj2GYZuVuQ6__xbfIsC58y0aJ8DqLYU9EU62bOVGGIts6Cic-pEfnaNLomkPj-J3qsAvZHliSXt3f2n5JLr4CoYS1FYg9vGYpw7upXyY9FgBC6bXdtjEqIISnirLa3ird1OXeAK7fO9Onk8r2EonGXK1FgDcHMkb0bE4ZtAWzkKvMQGZq07y0iVZL4VFCHuLEAPZ0-ccndGZVvvneUsejS-iT"
  };
  const options = {
    method: "get",
    muteHttpExceptions: true, // 开启后避免请求失败直接中断脚本
    headers: headers
  };

  let allTrades = [];
  let hasMoreData = true;

  while (hasMoreData) {
    try {
      const url = baseUrl + currentTradeId;
      const response = UrlFetchApp.fetch(url, options);
      const json = JSON.parse(response.getContentText());

      if (json.length === 0) {
        hasMoreData = false;
        break;
      }

      // 合并本次请求的交易数据到总列表
      allTrades = allTrades.concat(json);
      // 更新下一次请求的ID为本次最后一条数据的id
      currentTradeId = json[json.length - 1].id;

      // 添加1秒延迟,避免请求过于频繁被网站限流
      Utilities.sleep(1000);
    } catch (error) {
      Logger.log(`请求出错: ${error.message}`);
      hasMoreData = false;
    }
  }

  // 写入Google Sheet
  const ss = SpreadsheetApp.getActiveSpreadsheet();
  const balancesSheet = ss.getSheetByName("test");
  if (!balancesSheet) {
    Logger.log("找不到名为'test'的工作表");
    return;
  }

  // 清空原有数据(如需保留历史数据可注释此行)
  balancesSheet.clearContents();
  // 添加表头
  const sheetHeaders = ["ID", "Ticket", "Side", "Open Time", "Close Time", "Symbol", "Lots", "Profit"];
  balancesSheet.getRange(1, 1, 1, sheetHeaders.length).setValues([sheetHeaders]);

  // 转换数据格式为Sheet可接受的二维数组
  const values = allTrades.map(({ id, ticket, side, openTime, closeTime, symbol, lots, profit }) => 
    [id, ticket, side, openTime, closeTime, symbol, lots, profit]
  );

  // 批量写入数据
  if (values.length > 0) {
    balancesSheet.getRange(2, 1, values.length, values[0].length).setValues(values);
    Logger.log(`共写入 ${values.length} 条交易数据`);
  } else {
    Logger.log("未获取到任何交易数据");
  }
}

核心优化点说明

  • 循环分页请求:通过while循环持续请求,直到接口返回空数组,确保获取完整数据
  • 动态参数更新:每次请求后自动提取返回数据最后一条的id,作为下一次请求的URL参数,完全复刻前端逻辑
  • 错误防护:开启muteHttpExceptions并添加try-catch,避免单次请求失败导致脚本终止
  • Sheet写入优化:
    • 支持清空旧数据后写入完整数据集,或注释清空代码实现增量添加
    • 添加表头提升表格可读性
    • 批量写入数据,比逐条写入效率更高
  • 限流处理:添加1秒延迟,降低被网站拦截的风险

注意事项

  • Cookie存在有效期,过期后需要从浏览器重新获取
  • 如果交易数据量极大,需注意Google Script最长执行时间限制(6分钟),可考虑拆分请求或分批写入
  • 如需增量更新而非全量覆盖,可比对Sheet中已有数据的ID,只写入未存在的记录

内容的提问来源于stack exchange,提问作者Minh Chiến Hoà

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 00:46:04