使用Google Apps Script爬取网站遭Mod Security拦截,触发406错误求助
解决Google Apps Script爬取网站时的406错误
406错误提示明确是Mod Security拦截了请求,下面是针对性的修改方案:
核心问题分析
你的请求头配置不符合目标网站的预期:
- GET请求爬HTML页面,却设置了
Accept: application/json和Content-Type: application/json,这会让服务器认为你要请求JSON数据,但实际你要的是HTML,导致不匹配被拦截。 - 旧版User-Agent容易被识别为非正常浏览器请求。
- 多余的
Authorization头可能画蛇添足(如果目标网站不需要Bearer验证的话)。
修改后的代码示例
var ss = SpreadsheetApp.getActiveSpreadsheet(); // 调整请求头,模拟正常浏览器访问 var options = { 'method': 'get', 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36', 'muteHttpExceptions': true, 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8', 'Accept-Language': 'zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3', 'Referer': 'https://www.xxxxxxx/' // 替换为目标网站的首页地址 }; function scrapeJobs() { var result = []; for(var i = 1; i <= 2; i++) { var url = 'https://www.xxxxxxx/page/' + i; // 添加随机延迟,避免触发频率限制 Utilities.sleep(Math.floor(Math.random() * 2000) + 1000); var resp = UrlFetchApp.fetch(url, options).getContentText(); var $ = Cheerio.load(resp); var jobList = $("#titlo > strong > a"); var urls = jobList.map(function() { return $(this).attr('href'); }).toArray(); console.log(urls); for (let j = 0; j < urls.length; j++) { // 注意变量名不要和外层循环的i重复,避免冲突 Utilities.sleep(Math.floor(Math.random() * 1500) + 500); var data = scrapeJobDetails(urls[j]); if (data != null) { result.push(...data); } } } }
关键改动说明
- 移除了
Authorization和Content-Type:GET请求不需要Content-Type,如果目标网站不是API接口,Bearer验证完全多余。 - 更新
Accept头:设置为浏览器默认的接受格式,让服务器返回HTML内容。 - 添加
Accept-Language和Referer:模拟正常用户的访问环境,减少被拦截概率。 - 替换为新版User-Agent:使用当前主流Chrome版本的标识,避免被识别为老旧或非浏览器请求。
- 添加随机延迟:通过
Utilities.sleep()在请求之间加入随机等待,降低请求频率,避免触发反爬机制。 - 修正循环变量名:内层循环用
j代替i,避免变量覆盖导致逻辑错误。
额外排查方向
如果还是被拦截,可以尝试:
- 抓包查看正常浏览器访问该网站时的完整请求头,全部复制到
options中(注意不要包含Cookie里的敏感信息,但可以保留空的Cookie头)。 - 检查目标网站是否有Cloudflare等CDN防护,这类防护可能需要额外处理(比如解析页面中的验证参数,但Google Apps Script处理这类验证难度较高)。
内容的提问来源于stack exchange,提问作者lily
相关产品推荐
相关产品推荐

