curl采集设置CURLOPT_FOLLOWLOCATION不起作用的解决办法
curl抓取页面时,如果页面会发生301,302跳转,则需要对curl进行参数设置。
0 1 |
curl_setopt($ch, CURLOPT_MAXREDIRS,20); curl_setopt($ch, CURLOPT_FOLLOWLOCATION,1); |
CURLOPT_FOLLOWLOCATION即表示自动进行跳转抓取,CURLOPT_MAXREDIRS表示最多允许跳转多少次。
不过在使用时需要注意:CURLOPT_FOLLOWLOCATION需要在安全模式关闭未设置open_basedir的情况下才能使用。open_basedir是php.ini中的一项设置,功能是将用户可操作的文件限制在某目录下。
如果开户了安全模式,或者设置了open_basedir,则无法使用自动跳转抓取,此时可以采用连续抓取的办法来抓取最终页面。为加快速度和减少不必要的开销,可以在中间非目标页面的抓取过程中使用:
0 1 |
curl_setopt($rch, CURLOPT_HEADER, TRUE); curl_setopt($rch, CURLOPT_NOBODY, TRUE); |
只抓取头信息,不抓取页面内容,对header信息的状态码(301,302)进行判断。如需跳转,则从Location中获取到跳转的地址,再次进行抓取,直至状态码为200状态。最后再对目标页面进行抓取。
下面是在我项目是摘出来的静态方法,仅供参考:
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
/** * 以测试请求头信息开始,直到状态码返回200后才进行实际的采集工作 * @param string $url * @param array $options * @return array|bool|mixed */ public static function testCollect($url, $options=[]) { $curl = curl_init(); $index = 5; $headers = array( "User-Agent" => self::$ua ); if(!empty($options['headers'])){ $headers = $options['headers']; } while($index){ if(stripos($url,"https://")!==FALSE){ curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE); curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE); curl_setopt($curl, CURLOPT_SSLVERSION, 1); //CURL_SSLVERSION_TLSv1 } curl_setopt($curl, CURLOPT_URL, $url); curl_setopt($curl, CURLOPT_HEADER, TRUE); curl_setopt($curl, CURLOPT_NOBODY, TRUE); curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1 ); // 以文件流的形式返回 curl_setopt($curl, CURLOPT_HTTPHEADER, $headers); $content = curl_exec($curl); $info = curl_getinfo($curl); $code = $info['http_code']; $headers['Referer'] = $url; // 当前链接就是下一个请求的来路 if($code == 301 || $code == 302 || $code == 303 || $code == 307){ if(!empty($info['redirect_url'])){ $url = $info['redirect_url']; }else{ preg_match('/Location:(.*?)\n/', $content, $matches); $url = trim(array_pop($matches)); } $index--; continue; } $index = 0; } self::$httpCode = $code; if($code == 200){ $options['headers'] = $headers; return self::get($url, $options); // 采集页面信息 } curl_close($curl); return [$code, $content]; } |
如果想做采集,也可以换一种语言采集,比如使用我的另一篇文章写的关于Python的scrapy框架采集