簡體   English   中英

Google Apps 腳本在后端工作,但不在工作表上

[英]Google Apps Script Working on backend but not on sheets

我正在嘗試創建一個從硬幣市值 API 中提取並顯示當前價格的腳本。 當我為變量賦值時,腳本在后端運行良好。 但是,當我嘗試在工作表上運行 function 時,返回的值為 null。

function marketview(ticker) {
  var url = "https://pro-api.coinmarketcap.com/v1/cryptocurrency/quotes/latest?CMC_PRO_API_KEY=XXX&symbol=" + ticker;
  var data = UrlFetchApp.fetch(url);
  const jsondata = JSON.parse(data);

  Logger.log(jsondata.data[ticker].quote['USD'].price)
  
}

我的執行日志顯示腳本正在運行,但是當我使用 function 並嘗試引用 ETH 時,腳本正在為 BTC 運行。

當我在后端執行此操作並分配 ETH 時,腳本可以正常工作並返回正確的報價。 關於我所缺少的任何想法?

我對 coingecko API 做了同樣的事情,並添加了一個問題,即我的所有請求都因配額超出錯誤而被拒絕。

我知道 Google 表格服務器的 IP 地址已經在向 coingecko 服務器發送垃圾郵件。 (我顯然不是唯一一個嘗試這個的人)。

這就是為什么我使用像 apify.com 這樣的外部服務來提取數據並在其 API 上重新公開數據。

這是我的 AppScripts coingecko.gs

/**
 * get latest coingecko market prices dataset
 */
async function GET_COINGECKO_PRICES(key, actor) {
  const coinGeckoUrl = `https://api.apify.com/v2/acts/${actor}/runs/last/dataset/items?token=${key}&status=SUCCEEDED`
  return ImportJSON(coinGeckoUrl);
}

您需要ImportJSON function,可在此處獲得: https://github.com/bradjasper/ImportJSON/blob/master/ImportJSON.gs

然后在我寫的單元格中: =GET_COINGECKO_PRICES(APIFY_API_KEY,APIFY_COINGECKO_MARKET_PRICES) ,您必須創建兩個名為APIFY_API_KEYAPIFY_COINGECKO_MARKET_PRICES的字段才能使其正常工作。

然后在 apify.com 上注冊,然后你必須通過 fork apify-webscraper actor 創建一個 actor。

我將StartURLs設置為https://api.coingecko.com/api/v3/coins/list ,這將為我提供現有加密的總數(截至今天約為 11000)和頁數,以便我可以運行並發請求(在 coingecko 上的速率限制是 10 個並發請求),然后我只需將/list替換為/market並設置適當的限制以獲取我需要的所有頁面。

我對任務頁面 function 使用以下內容:

async function pageFunction(context) {
    let marketPrices = [];
    const ENABLE_CONCURRENCY_BATCH = true;
    const PRICE_CHANGE_PERCENTAGE = ['1h', '24h', '7d'];
    const MAX_PAGE_TO_SCRAP = 10;
    const MAX_PER_PAGE = 250;
    const MAX_CONCURRENCY_BATCH_LIMIT = 10;
    await context.WaitFor(5000);
    const cryptoList = readJson();
    const totalPage = Math.ceil(cryptoList.length / MAX_PER_PAGE);

    context.log.info(`[Coingecko total cryptos count: ${cryptoList.length} (${totalPage} pages)]`)
    
    function readJson() {
        try {
            const preEl = document.querySelector('body > pre');
            return JSON.parse(preEl.innerText);
        } catch (error) {
            throw Error(`Failed to read JSON: ${error.message}`)
        }
    }


    async function loadPage($page) {
        try {
            const params = {
                vs_currency: 'usd',
                page: $page,
                per_page: MAX_PER_PAGE,
                price_change_percentage: PRICE_CHANGE_PERCENTAGE.join(','),
                sparkline: true,
            }
            
            let pageUrl = `${context.request.url.replace(/\/list$/, '/markets')}?`;
            pageUrl += [
                `vs_currency=${params.vs_currency}`,
                `page=${params.page}`,
                `per_page=${params.per_page}`,
                `price_change_percentage=${params.price_change_percentage}`,
            ].join('&');
                        
            context.log.info(`GET page ${params.page} URL: ${pageUrl}`);
            const page = await fetch(pageUrl).then((response) => response.json());
            context.log.info(`Done GET page ${params.page} size ${page.length}`);
            marketPrices = [...marketPrices, ...page];
            return page
        } catch (error) {
            throw Error(`Fail to load page ${$page}: ${error.message}`)
        }
    }

    try {
        if (ENABLE_CONCURRENCY_BATCH) {
            const fetchers = Array.from({ length: totalPage }).map((_, i) => {
                const pageIndex = i + 1;
                if (pageIndex > MAX_PAGE_TO_SCRAP) {
                    return null;
                }
                return () => loadPage(pageIndex);
            }).filter(Boolean);
            while (fetchers.length) {   
                await Promise.all(
                    fetchers.splice(0, MAX_CONCURRENCY_BATCH_LIMIT).map((f) => f())
                );
            }
        } else {
            let pageIndex = 1
            let page = await loadPage(pageIndex)
            while (page.length !== 0 && page <= MAX_PAGE_TO_SCRAP) {
                pageIndex += 1
                page = await loadPage(pageIndex)
            }
        }
    } catch (error) {
        context.log.info(`Fetchers failed: ${error.message}`);
    }

    context.log.info(`End: Updated ${marketPrices.length} prices for ${cryptoList.length} cryptos`);
    const data = marketPrices.sort((a, b) => a.id.toLowerCase() > b.id.toLowerCase() ? 1 : -1);
    context.log.info(JSON.stringify(data.find((item) => item.id.toLowerCase() === 'bitcoin')));

    function sanitizer(item) {
        item.symbol = item.symbol.toUpperCase()
        return item;
    }
    return data.map(sanitizer)
}

我認為您遇到了與 coinmarketcap 相同的問題,並且您可以對它做同樣的事情。

您不會將任何內容return到工作表,而只是將其記錄下來。 把它返還:

return jsondata.data[ticker].quote['USD'].price

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM