如何使用Google Apps Script自动刷新请求中的验证令牌及Cookie以实现持续的表单提交与数据提取
你遇到的问题很常见——硬编码的验证令牌和Cookie都是会话绑定的,过一段时间或者服务器重启后就会失效,所以必须每次请求前先从目标页面获取最新的凭据。下面我给你一步步拆解解决方案,直接替换你现有的脚本就行:
核心思路
每次提交表单前,先GET请求目标页面,从响应里拿到两个关键信息:
- 服务器返回的Cookie(包含会话标识和临时令牌)
- 页面HTML里隐藏的
__RequestVerificationToken值
用这两个最新的信息构造POST请求,就能保证每次请求都是有效的。
完整代码实现
function submitForm() { const targetUrl = "https://taxdelinquent.cookcountyclerkil.gov/"; const pinToSubmit = "13-30-300-016-0000"; // 第一步:GET页面获取最新的Cookie和验证令牌 const getOptions = { method: "get", followRedirects: true }; const getResponse = UrlFetchApp.fetch(targetUrl, getOptions); // 提取Cookie:从响应头的Set-Cookie中获取,拼接成适合请求头的格式 const setCookieHeaders = getResponse.getHeaders()["Set-Cookie"]; if (!setCookieHeaders) { throw new Error("无法获取Cookie,请检查目标网站是否可访问"); } // 只提取每个Cookie的键值对部分(忽略expires、path等属性) const cookies = setCookieHeaders.map(cookie => cookie.split(";")[0]).join("; "); // 提取__RequestVerificationToken:从HTML中用正则匹配隐藏input的值 const htmlContent = getResponse.getContentText(); const tokenMatch = htmlContent.match(/<input name="__RequestVerificationToken" type="hidden" value="([^"]+)"/); if (!tokenMatch || tokenMatch.length < 2) { throw new Error("无法从页面中提取验证令牌,请检查页面结构是否变化"); } const verificationToken = tokenMatch[1]; // 第二步:构造POST请求的参数和请求头 const formData = { '__RequestVerificationToken': verificationToken, 'Pin': pinToSubmit }; // 编码表单数据 const encodedData = Object.keys(formData).map(key => encodeURIComponent(key) + '=' + encodeURIComponent(formData[key]) ).join('&'); const postHeaders = { "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "Cookie": cookies, "Content-Type": "application/x-www-form-urlencoded" // 这个头很重要,确保服务器正确解析表单数据 }; const postOptions = { method: "post", headers: postHeaders, payload: encodedData, followRedirects: true }; // 发送POST请求并处理响应 const postResponse = UrlFetchApp.fetch(targetUrl, postOptions); const responseText = postResponse.getContentText(); // 这里可以添加解析responseText提取数据到Google Sheet的逻辑 // 比如用正则或者HtmlService.parseHtml来提取你需要的信息 // 示例:假设要提取某个标签里的内容 // const doc = HtmlService.createHtmlOutput(responseText).getContent(); // const result = doc.querySelector('.some-result-class').innerText; // SpreadsheetApp.getActiveSpreadsheet().getActiveSheet().appendRow([new Date(), pinToSubmit, result]); }
关键细节说明
- Cookie提取:服务器返回的
Set-Cookie可能有多个,我们只需要每个Cookie的键值部分,所以用split(";")[0]截断后面的属性,再拼接成请求头需要的格式。 - 验证令牌提取:用正则表达式匹配页面中隐藏的input元素,如果你发现页面结构变化,需要调整正则表达式来匹配最新的HTML结构。
- 请求头补充:添加了
Content-Type头,确保服务器能正确识别表单编码格式,避免提交失败。 - 异常处理:添加了简单的错误判断,如果获取不到Cookie或令牌就抛出错误,方便你排查问题。
后续优化建议
- 如果需要批量提交多个PIN,可以把PIN放在Google Sheet里,循环读取并逐个提交。
- 可以添加重试逻辑,如果某次请求失败(比如令牌过期),自动重新获取凭据再尝试。
- 注意不要频繁发送请求,避免触发目标网站的反爬机制,最好添加适当的延迟(用
Utilities.sleep(1000))。
备注:内容来源于stack exchange,提问作者EagleEye
相关产品推荐
相关产品推荐

