如何用Google Apps Script抓取指定网页近12个月的表格数据?
解决方案:使用Google Apps Script抓取指定日期范围的表格数据
核心思路
目标页面是ASPX动态页面,需模拟表单提交获取指定日期的表格数据。步骤如下:
- 获取ASPX页面必需的验证参数(VIEWSTATE等)
- 遍历过去12个月的日期,构造POST请求
- 解析响应中的表格数据并写入Google Sheets
完整代码实现
function fetchPast12MonthsData() { const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet(); const baseUrl = "https://www.scstrade.com/stockscreening/SS_CompanySnapShotHP.aspx?symbol=ABOT"; const userAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36"; // 1. 获取初始页面的ASPX验证参数 const initialResponse = UrlFetchApp.fetch(baseUrl, { headers: { "User-Agent": userAgent } }); const initialHtml = initialResponse.getContentText(); const viewState = extractAspxParam(initialHtml, "__VIEWSTATE"); const viewStateGenerator = extractAspxParam(initialHtml, "__VIEWSTATEGENERATOR"); const eventValidation = extractAspxParam(initialHtml, "__EVENTVALIDATION"); if (!viewState || !viewStateGenerator || !eventValidation) { throw new Error("无法获取ASPX验证参数,页面结构可能已变更"); } // 2. 生成过去12个月的日期(格式:MM/YYYY) const dateList = []; const now = new Date(); for (let i = 0; i < 12; i++) { const year = now.getFullYear() - (i > now.getMonth() ? 1 : 0); const month = (now.getMonth() - i + 12) % 12 + 1; // 转换为1-12的月份 dateList.push(`${month.toString().padStart(2, '0')}/${year}`); } // 3. 遍历日期请求数据并写入表格 sheet.clearContents(); let rowIndex = 1; for (const date of dateList) { // 构造POST请求参数 const payload = { "__VIEWSTATE": viewState, "__VIEWSTATEGENERATOR": viewStateGenerator, "__EVENTVALIDATION": eventValidation, // 需确认日期下拉框的name属性,此处为页面实际控件名示例 "ctl00$ContentPlaceHolder1$ddlMonthYear": date, // 触发提交的按钮控件名,此处为示例 "ctl00$ContentPlaceHolder1$btnSubmit": "Submit" }; const options = { method: "POST", headers: { "User-Agent": userAgent, "Content-Type": "application/x-www-form-urlencoded" }, payload: payload, followRedirects: true }; try { const response = UrlFetchApp.fetch(baseUrl, options); const html = response.getContentText(); // 解析目标表格,此处表格id为页面实际元素id示例 const table = parseTable(html, "ctl00_ContentPlaceHolder1_gvFinancials"); if (table.length === 0) continue; // 写入日期标题 sheet.getRange(rowIndex, 1).setValue(`日期: ${date}`); rowIndex++; // 写入表格数据 sheet.getRange(rowIndex, 1, table.length, table[0].length).setValues(table); rowIndex += table.length + 1; // 留空行分隔不同日期的数据 } catch (e) { sheet.getRange(rowIndex, 1).setValue(`获取${date}数据失败: ${e.message}`); rowIndex++; } } SpreadsheetApp.getUi().alert("数据抓取完成"); } // 提取ASPX页面的隐藏域参数 function extractAspxParam(html, paramName) { const regex = new RegExp(`<input type="hidden" name="${paramName}" id="${paramName}" value="([^"]+)" />`); const match = html.match(regex); return match ? match[1] : null; } // 解析HTML中的表格数据 function parseTable(html, tableId) { const doc = XmlService.parse(html); const root = doc.getRootElement(); const table = root.getDescendants().find(elem => elem.getAttribute("id")?.getValue() === tableId ); if (!table) return []; const rows = table.getChildren("tr"); const data = []; rows.forEach(row => { const cells = row.getChildren("td").map(cell => { // 清理单元格文本,去除多余空格和换行 return cell.getText().trim().replace(/\s+/g, " "); }); if (cells.length > 0) data.push(cells); }); return data; }
关键注意事项
- 控件参数确认:代码中假设的表单控件名称(如
ctl00$ContentPlaceHolder1$ddlMonthYear)和表格id(ctl00_ContentPlaceHolder1_gvFinancials)需自行验证。可通过浏览器开发者工具查看页面源代码,确认实际的控件名称和表格id。 - User-Agent设置:添加浏览器UA模拟真实访问,避免被服务器拦截。
- 错误处理:代码包含基础错误捕获,若某日期数据获取失败会记录错误信息。
- 权限授权:首次运行脚本时需完成授权,允许脚本访问Google Sheets和发送网络请求。
使用说明
- 打开目标Google Sheet,点击「扩展程序」→「Apps Script」打开脚本编辑器。
- 将上述代码粘贴到编辑器中,替换默认内容。
- 根据页面实际元素调整代码中的表单参数和表格id。
- 保存脚本并运行
fetchPast12MonthsData函数,按提示完成授权。
内容的提问来源于stack exchange,提问作者Huma Wakani
相关产品推荐
相关产品推荐

