转载

PHP爬虫技术(一)

摘要:本篇文章介绍 PHP 抓取网页内容技术,利用 PHP cURL 扩展获取网页内容,还可以抓取网页头部,设置 cookie ,处理 302 跳转。

一、cURL安装

采用源码安装 PHP 时,需要在 configure 时添加配置项,

cd php

./configure --with-curl

安装完毕,可以利用 php -m 命令查看,是否已经支持 cURL 扩展。

php -m | grep curl

也可以利用 phpinfo 查看,是否已经支持 cURL 扩展。

PHP爬虫技术(一)

二、获取网页内容

cURL 支持很多网络协议,如 HTTP 、 HTTPS 、 FTP 等。普通网页采用 HTTP 协议,一些安全性高的网页采用 HTTPS ( HTTPS 协议采用数据加密技术,通过公钥技术交换密钥,加密传输内容。因此采用 HTTPS 协议的网页,在整个链路上传输的都是加密后的数据。例如 Baidu 采用 HTTPS 协议,你输入的关键字被网络传输协议加密,即使是运营商可以获得全部数据,也无法获得数据的内容。 HTTPS 协议也有缺点,就是加解密需要耗费计算时间,因此 HTTPS 网站会慢一些,而大多数网站都是采用 HTTP 协议)。 HTTP 协议中,定义了两种方法 GET 和 POST 。 POST 方法通常用于表单提交,能够提交文件等大数据。 GET 方法用来获取网页数据,也可以提交少量数据。本文主要介绍利用 GET 协议获取网页数据,将来再详细讲解 cURL POST 技术。

我们先看一些浏览器是怎么工作的,打开 chrome 浏览器, F12 进入开发者模式,将工具栏切换到 network ,如下图,利用 chrome 工具可以查看每个文件的传输信息。

PHP爬虫技术(一)

浏览器要加载一个网页,首先下载 html 文件,再下载 js 、 css 、图片等资源文件再进行渲染加载。通常数据抓取只需要抓取 html 文件,下图是 chrome 工具显示下载 http 文件的内容。

PHP爬虫技术(一)

三、PHP 实现

<?php $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, "www.qq.com"); curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); $html = curl_exec($ch); curl_close($ch); var_dump($html); ?>

基本设置,返回网页内容。

四、获得HTTP头部设置cookie

有些网站,会采用 cookie 技术。当采集程序没带有相关 cookie 时,很容易被网站认定是“机器人”,拒绝对其服务。通过 chrome 调试 www.sogou.com ,发现 cookie 是包含在网页头信息中的。因此,我们需要两个步骤( 1 ) HTTP 头信息中获取 cookie ( 2 )发送请求时添加 cookie 。

头信息包含设置c ookie ,

PHP爬虫技术(一)

刷新网页,查看头信息,请求包含 cookie 信息

PHP爬虫技术(一)

获取 cookie

<?php     $url = "www.sogou.com";     $ch = curl_init();     curl_setopt($ch, CURLOPT_URL, $url);     curl_setopt($ch, CURLOPT_NOBODY, true);     curl_setopt($ch, CURLOPT_HEADERFUNCTION, function ($ch, $str) use(&$setcookie) {       // 第一个参数是curl资源,第二个参数是每一行独立的header!       list ($name, $value) = array_map('trim', explode(':', $str, 2));       $name = strtolower($name);       if('set-cookie'==$name)       {         $setcookie[]=$value;       }       return strlen($str);     });     curl_exec($ch);     curl_close($ch);     $cookie = array();     foreach($setcookie as $c)     {       $tmp = explode(";",$c);       $cookie[] = $tmp[0];     }     $cookiestr = "Cookie:".implode(";", $cookie);     echo $cookiestr; ?>

返回结果

Cookie:ABTEST=0|1433425917|v17;IPLOC=CN1100;SUID=3295CB6F1220920A00000000557057FD

设置cookie

<?php  $url = "www.sogou.com";  $ch = curl_init();  curl_setopt($ch, CURLOPT_URL, $url);  curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);  $headers[] = $cookie;  curl_setopt($ci, CURLOPT_HTTPHEADER, $headers);  $html = curl_exec($ch);  curl_close($ch);  var_dump($html);  ?>

五、抓取302跳转

在Baidu中搜索关键词,返回的结果链接是一个Baidu加密过的链接,通过二次跳转才是真正的网址。(Baidu为了防止360抓取,把结果都加密了)。

我们可以抓取头部中的location信息找到真实地址,

<?php     $url = "https://www.baidu.com/link?url=b34APzBjz-cGLoxsG4-nviHmtVS0tCvEftS6ApCAsojT1a0h9oFFPprwK4JpNYgGaQE29QPUtRdPUeu3lIz2M7GW7dqLMi5ytlHLOVa3v_VY23dOoRiUSyV9zr_cI8Rg&wd=&eqid=c89cf372000002cc0000000255705961&ie=utf-8";     $ch = curl_init();     curl_setopt($ch, CURLOPT_URL, $url);     curl_setopt($ch, CURLOPT_NOBODY, true);     curl_setopt($ch, CURLOPT_HEADERFUNCTION, function ($ch, $str) use(&$location) {       // 第一个参数是curl资源,第二个参数是每一行独立的header!         list ($name, $value) = array_map('trim', explode(':', $str, 2));         $name = strtolower($name);         if('location'==$name)         {           $location = $value;           return 0;         }         return strlen($str);     });     curl_exec($ch);     curl_close($ch);     echo $location; ?>

抓取302跳转还有另外一种方式,利用ob重定向流的方式,并且设置允许curl跳转到新地址。代码如下

<?php  function getContents($url){   $header = array("Referer: http://www.baidu.com/");   $ch = curl_init();   curl_setopt($ch, CURLOPT_URL, $url);   curl_setopt($ch, CURLOPT_TIMEOUT, 30);   curl_setopt($ch, CURLOPT_HTTPHEADER,$header);   curl_setopt($ch, CURLOPT_FOLLOWLOCATION,1);  //能无法 抓取跳转后的页面  ob_start();   curl_exec($ch);   $contents = ob_get_contents();   ob_end_clean();   curl_close($ch);   return $contents;   }   $url = "https://www.baidu.com/link?url=b34APzBjz-cGLoxsG4-nviHmtVS0tCvEftS6ApCAsojT1a0h9oFFPprwK4JpNYgGaQE29QPUtRdPUeu3lIz2M7GW7dqLMi5ytlHLOVa3v_VY23dOoRiUSyV9zr_cI8Rg&wd=&eqid=c89cf372000002cc0000000255705961&ie=utf-8";  $contents = getContents($url);  echo $contents;  ?> 
正文到此结束
Loading...