使用云函数在GCP上调度Node.js脚本
我已经创建了一个脚本,它可以从网页中抓取信息并将其写入Google工作表。这在我的本地机器上运行得很好,但我想在GCP上安排 听起来云函数是一条可行之路,但当我部署我的函数时,我会遇到以下错误: 加载用户代码时函数失败。错误消息:文件working.js定义的Node.js模块需要导出名为run的函数 我不确定应该使用什么作为“要执行的函数”。以下是我上传的函数:使用云函数在GCP上调度Node.js脚本,node.js,google-cloud-platform,google-cloud-functions,puppeteer,Node.js,Google Cloud Platform,Google Cloud Functions,Puppeteer,我已经创建了一个脚本,它可以从网页中抓取信息并将其写入Google工作表。这在我的本地机器上运行得很好,但我想在GCP上安排 听起来云函数是一条可行之路,但当我部署我的函数时,我会遇到以下错误: 加载用户代码时函数失败。错误消息:文件working.js定义的Node.js模块需要导出名为run的函数 我不确定应该使用什么作为“要执行的函数”。以下是我上传的函数: const puppeteer = require('puppeteer'); const jsonexport = require
const puppeteer = require('puppeteer');
const jsonexport = require('jsonexport');
const GoogleSpreadsheet = require('google-spreadsheet');
const creds = require('./google-generated-creds.json');
const fs = require('fs');
var doc = new GoogleSpreadsheet('1qaFi0xnhaCZEduylUvGXWpyMJv00Rz6Y9qqyFR1E9oI');
function run() {
return new Promise(async (resolve, reject) => {
try {
const browser = await puppeteer.launch({args: ['--no-sandbox', '--disable-setuid-sandbox']});
const page = await browser.newPage();
const urls = [
"https://www.marksandspencer.com/pure-cotton-long-sleeve-jumpsuit/p/p60258655?image=SD_01_T42_6701_XB_X_EC_90&color=INDIGO&prevPage=plp",
"https://www.marksandspencer.com/cotton-rich-striped-3-4-sleeve-t-shirt/p/p60210598?prevPage=plp",
"https://www.marksandspencer.com/high-neck-long-sleeve-blouse/p/p60260040?image=SD_01_T43_5168_HD_X_EC_90&color=LIGHTDENIM&prevPage=plp",
"https://www.marksandspencer.com/pure-cotton-printed-short-sleeve-t-shirt/p/p60263529?image=SD_01_T41_8030Z_Z4_X_EC_90&color=WHITEMIX&prevPage=plp",
"https://www.marksandspencer.com/pure-cotton-button-detailed-denim-mini-skirt/p/p60260145?image=SD_01_T57_4004_QP_X_EC_90&color=DARKINDIGO&prevPage=plp",
"https://www.marksandspencer.com/pure-cotton-long-sleeve-shirt-midi-dress/p/p60258654?image=SD_01_T42_6703_HP_X_EC_90&color=DENIM&prevPage=plp",
"https://www.marksandspencer.com/mid-rise-skinny-leg-ankle-grazer-jeans/p/p60220155?prevPage=plp",
"https://www.marksandspencer.com/pure-cotton-long-sleeve-shirt/p/p60260208?image=SD_01_T43_5181_HP_X_EC_90&color=DENIM&prevPage=plp",
"https://www.marksandspencer.com/long-sleeve-shirt-mini-dress/p/p60258652?image=SD_01_T42_6704_HP_X_EC_90&color=DENIM&prevPage=plp",
"https://www.marksandspencer.com/wide-fit-suede-lace-up-trainers/p/p60216277?prevPage=plp",
"https://www.marksandspencer.com/suede-ankle-boots/p/p60226911?prevPage=plp",
"https://www.marksandspencer.com/leather-buckle-hip-belt/p/p60186701?prevPage=plp",
"https://www.marksandspencer.com/cross-body-bag/p/p60215352?prevPage=plp"
];
const productsList = [];
for (let i = 0; i < urls.length; i++) {
const url = urls[i];
await page.goto(url);
let products = await page.evaluate(() => {
let product = document.querySelector('h1[itemprop=name]').innerText;
let results = [];
let items = document.querySelectorAll('[data-ttip-id=sizeGridTooltip] tbody tr td label');
items.forEach((element) => {
let size = element.getAttribute('for');
let stockLevel = "";
let nearest_td = element.closest('td');
if (nearest_td.classList.contains('low-stock')) {
stockLevel = "Low stock"
} else if (nearest_td.classList.contains('out-of-stock')) {
stockLevel = "Out of stock"
} else {
stockLevel = "In stock"
}
results.push({
product: product,
size: size,
stock: stockLevel
})
});
return results
})
productsList.push(products)
}
browser.close();
function flatten(arr) {
return arr.reduce(function(flat, toFlatten) {
return flat.concat(Array.isArray(toFlatten) ? flatten(toFlatten) : toFlatten);
}, []);
}
var flatProducts = flatten(productsList)
flatProducts.forEach(function(row) {
// Authenticate with the Google Spreadsheets API.
doc.useServiceAccountAuth(creds, function(err) {
// Get all of the rows from the spreadsheet.
doc.addRow(1, row, function(err, rows) {
console.log(row);
});
});
});
} catch (e) {
return reject(e);
}
})
}
run().then(console.log).catch(console.error);
const puppeter=require('puppeter');
const jsonexport=require('jsonexport');
const GoogleSpreadsheet=require('google-spreadsheet');
const creds=require('./google生成的creds.json');
常数fs=要求('fs');
var doc=新的谷歌电子表格(“1QAFI0xNHACZEDUYLUVGXWPYMJV00RZ6Y9QYFR1E9OI”);
函数运行(){
返回新承诺(异步(解析、拒绝)=>{
试一试{
const browser=wait puppeter.launch({args:['--no sandbox','--disable setuid sandbox']});
const page=wait browser.newPage();
常量URL=[
"https://www.marksandspencer.com/pure-cotton-long-sleeve-jumpsuit/p/p60258655?image=SD_01_T42_6701_XB_X_EC_90&color=INDIGO&prevPage=plp",
"https://www.marksandspencer.com/cotton-rich-striped-3-4-sleeve-t-shirt/p/p60210598?prevPage=plp",
"https://www.marksandspencer.com/high-neck-long-sleeve-blouse/p/p60260040?image=SD_01_T43_5168_HD_X_EC_90&color=LIGHTDENIM&prevPage=plp",
"https://www.marksandspencer.com/pure-cotton-printed-short-sleeve-t-shirt/p/p60263529?image=SD_01_T41_8030Z_Z4_X_EC_90&color=WHITEMIX&prevPage=plp",
"https://www.marksandspencer.com/pure-cotton-button-detailed-denim-mini-skirt/p/p60260145?image=SD_01_T57_4004_QP_X_EC_90&color=DARKINDIGO&prevPage=plp",
"https://www.marksandspencer.com/pure-cotton-long-sleeve-shirt-midi-dress/p/p60258654?image=SD_01_T42_6703_HP_X_EC_90&color=DENIM&prevPage=plp",
"https://www.marksandspencer.com/mid-rise-skinny-leg-ankle-grazer-jeans/p/p60220155?prevPage=plp",
"https://www.marksandspencer.com/pure-cotton-long-sleeve-shirt/p/p60260208?image=SD_01_T43_5181_HP_X_EC_90&color=DENIM&prevPage=plp",
"https://www.marksandspencer.com/long-sleeve-shirt-mini-dress/p/p60258652?image=SD_01_T42_6704_HP_X_EC_90&color=DENIM&prevPage=plp",
"https://www.marksandspencer.com/wide-fit-suede-lace-up-trainers/p/p60216277?prevPage=plp",
"https://www.marksandspencer.com/suede-ankle-boots/p/p60226911?prevPage=plp",
"https://www.marksandspencer.com/leather-buckle-hip-belt/p/p60186701?prevPage=plp",
"https://www.marksandspencer.com/cross-body-bag/p/p60215352?prevPage=plp"
];
const productsList=[];
for(设i=0;i{
让product=document.querySelector('h1[itemprop=name]')。innerText;
让结果=[];
让items=document.querySelectorAll(“[data ttip id=sizeGridTooltip]tbody tr td label”);
items.forEach((元素)=>{
让size=element.getAttribute('for');
让stockLevel=“”;
设最近的_td=元素。最近的('td');
if(最近的类列表包含('low-stock')){
stockLevel=“低库存”
}else if(最近的类列表包含('缺货')){
stockLevel=“缺货”
}否则{
stockLevel=“库存中”
}
结果:推({
产品:产品,,
尺寸:尺寸,
库存:库存水平
})
});
返回结果
})
productsList.push(产品)
}
browser.close();
函数展平(arr){
返回arr.reduce(功能(平坦、平坦){
返回平坦.concat(数组.isArray(toFlatten)?平坦(toFlatten):toFlatten;
}, []);
}
var flatProducts=扁平化(productsList)
扁平产品.forEach(功能(行){
//使用Google电子表格API进行身份验证。
doc.useServiceAccountAuth(凭证、函数(错误){
//从电子表格中获取所有行。
doc.addRow(1,行,函数(err,行){
控制台日志(行);
});
});
});
}捕获(e){
退货拒收(e);
}
})
}
run().then(console.log).catch(console.error);
我以前从未使用过云函数,所以不确定需要修改多少脚本。你不能只上传任何脚本来运行。必须使用或定义函数。您还必须弄清楚如何触发它。当函数被触发时,您可以安排执行代码
我想说的是,将现有脚本移植到云函数是非常重要的。您必须花时间了解系统的工作原理,以便有效地利用它。您不能只上传任何脚本即可运行。必须使用或定义函数。您还必须弄清楚如何触发它。当函数被触发时,您可以安排执行代码 我想说的是,将现有脚本移植到云函数是非常重要的。
exports.run = (event, callback) => {
callback(null, `Hello ${event.data.name || 'World'}!`);
};