axios / fetch POST 请求变成 GET 请求问题

过程

这几天有个爬虫项目突然炸了,具体情况就是由标题所说的,明明写的是 POST 请求却成了 GET 这让我百思不得其解

code_and_log

让我 debug 了差不多半个小时,已经用了好几个月的代码突然不能用了,还以为是 Node.js 或者依赖更新了,降级回去还是一样,最后放弃 debug,对目标网站重新写爬虫代码(这玩意无法控制变量,重写一遍反而是更快)
最终发现了问题所在:目标网站最近上 https 了 然后把 http 请求都 redirect 成了 https

实际上就是 Header 加了个 Location: https://example.com
浏览器(爬虫)会跟过去,然后用 GET 请求请求 Location 头里的新的地址,所以爬虫就炸了,不会在跳转后的链接里面再 POST 一次。

解决方案

Q1: 那么要怎么解决这个问题呢?
A1: 叫站长再改回去 不强制 https
A1: 把链接替换成 https://
realA1: 把 301/302换成 307 / 308

在 HTTP 协议中, 308 Permanent Redirect(永久重定向)是表示重定向的响应状态码,说明请求的资源已经被永久的移动到了由 Location 首部指定的 URL 上。浏览器会进行重定向,同时搜索引擎也会更新其链接(用 SEO 的行话来说,意思是“链接汁”(link juice)被传递到了新的 URL)。
在重定向过程中,请求方法和消息主体不会发生改变,然而在返回 301 状态码的情况下,请求方法有时候会被客户端错误地修改为 GET 方法。

Q2: 如何在以后的爬虫里面发现或者避免这个问题?
A2: 督促站长上 https,现在就解决这个问题
A2: 判断跳转次数,大于0就报错(提早预防),比如我用的是 axios ,那么有变量可以追踪一共跳转了多少次。
A2: 把请求再封装一遍,处理掉 带 Location header 的 POST 请求 (axios 设置 maxRedirects:0 之类的参数不让请求库自动跳转)

总结

记录一下这个坑点,说不定哪天又碰到了((