最近用PHP写了一个爬虫,抓取某个接口返回的json数据,过程中遇到不少问题,在此整理一下。
用浏览器一直都可以正常获取,所以记录curl模拟浏览器请求失败的原因和解决思路。
-
【问题】GET请求方式,和浏览器一样的url、header(但无cookie),却一直请求失败
【原因】接口返回的是一个空responseHeader、responseBody的HTML页面,其中body内仅有一对<noscript></noscript>声明,真正的js放在head内的<script></script>,里面定义了2个变量和1个方法,由这三者计算出第3个变量值;再拿3个值POST请求当前url,得到cookie;再拿cookie重新发起GET请求。
【解决办法】浏览器F12打开调试,选择Network面板,勾上Preserve log,查看完整的请求过程,有时接口为了防止爬虫,不是直接返回数据,而是需要有js运行环境的浏览器运行js脚本后再返回数据。
-
【问题】GET请求方式,和浏览器一样的url、header(包括cookie),请求200成功,却没有返回数据
【原因】编码问题,需要将curl设置curl_setopt(CURLOPT_ENCODING, '');。这个问题就比较诡异了,按照PHP官方的说法,CURLOPT_ENCODING是HTTP请求头中"Accept-Encoding: "的值。 这使得能够解码响应的内容。 支持的编码有"identity","deflate"和"gzip"。如果为空字符串"",会发送所有支持的编码类型。,但我的header已经和浏览器一样,声明了Accept-Encoding为gzip, deflate,不应该出现与浏览器不一样的结果。目前只能推测,因为浏览器为了兼容多编码,自动发送全部编码,调试面板中的Accept-Encoding实际上没有失效,故curl模拟请求中的header中Accept-Encoding反而成了限制,需要设置CURLOPT_ENCODING为空来转换所有返回的数据编码。
【解决办法】将curl设置curl_setopt(CURLOPT_ENCODING, '');
-
【问题】(看到很多人在问,这里顺便记录一下)和浏览器一样的url,却一直请求失败
【原因】1、没有带上与浏览器一样的header,特别是其中的User-Agent、cookie(如果需要的话);2、curl没有设置curl_setopt(CURLOPT_RETURNTRANSFER, true);
【解决办法】request的header、body等参数和浏览器比较,缺啥补啥;设置好curl_setopt各个参数。
以上就是写爬虫时,浏览器可以正常访问,但PHP curl模拟请求失败的原因,欢迎交流补充。