当您成功装置XAMPP之后,我们就可以在PHP/MySQL环境生成PHP脚本索取网页源文件。PHP有很多函数库帮我们向伺服器发送请求及接收伺服器送回的文件,其中一个是我们将要用到的cURL。
现在我们先写一个间单的PHP/cURL类来协助我们向伺服器提出请求,之后我们才能向网页源文件“开刀”取出我们要的资料。我们也不时要改进我们的程序源码。
首先,在C:\xampp\htdocs下创建一个文件夹“scraper”,然后使用Notepad++在文件夹C:\xampp\htdocs\scraper创建一个文件httpcurl.php。
如要Notepad++高亮显示编程语法,选择"Language"->"P"->"PHP"。
在httpcurl.php文件里:
<?php class HttpCurl { private $_info, $_body, $_error; public function __construct() { if (!function_exists('curl_init')) { throw new Exception('cURL not enabled!'); } } public function get($url) { $this->request($url); } protected function request($url) { $ch = curl_init(); curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); curl_setopt($ch, CURLOPT_URL, $url); $this->_body = curl_exec($ch); $this->_info = curl_getinfo($ch); $this->_error = curl_error($ch); curl_close($ch); } public function getStatus() { return $this->_info[http_code]; } public function getHeader() { return $this->_info; } public function getBody() { return $this->_body; } public function __destruct() { } } ?>
如何现实
1. 首先我们创建cURL包装函式类HttpCurl,有三个私有变量,$_body,$_error 及$_info。
class HttpCurl { private $_info, $_body, $_error;
2. 我们在HttpCurl类构造方法检查cURL是否在PHP配置中启用。如未启用脚本将显示错误信息。您需在php.ini扩展中启用cURL,然后重启XAMPP就行了。
3. 我们创建了公共方法get(),这会执行受保护方法request().
4. 在受保护方法request(),我们执行cURL函数向伺服器请求网页源文件。
首先,我们需要通过curl_init()初始化cURL及存储返回的句柄$ch。
基本上我们需要设置两个选项以向伺服器请求网页源文件。
curl_setopt($ch, CURLOPT_URL, $url) 告诉cURL我们要的网址在$url。
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE) 告诉cURL将 curl_exec()获取的信息以文件流的形式返回,而不是直接输出。
5. 我们通过curl_exec($ch)执行cURL。函数执行成功时返回执行的结果将被存储在私有变量$_body中。
6. 采集资料前我们必须知道执行 curl_exec()的结果。我们可以执行 curl_getinfo() 然后存储在私有变量$_info。
7. 关闭cURL会话并且释放所有资源前,我们捡查是否有错误,可执行curl_error()然后存储在私有变量$_error。如无误则$_error为空。
8. 最后,执行curl_close()关闭cURL会话。在这阶段,我们已有网页源文件的资料。
接下来我们先试试这脚本,向伺服器发出请求。现在同一文件夹中再创建一个文件,test.php。 您可在视窗命令提示符执行test.php。不过这是个简单的程序,可在浏览器执行,只需输入以下网址:localhost/scraper/test.php.
<?php include 'httpcurl.php'; $target = "http://<domain name>"; $page = new HttpCurl(); $page->get($target); echo " Web Page Header<br>"; print_r($page->getHeader()); echo "<br>"; echo " Web Page Status<br>"; print_r($page->getStatus()); echo "<br>"; echo " Web Page Body<br>"; print_r($page->getBody()); ?>
首先,之前的文件httpcurl.php包含在test.php,然后用new创建了HttpCurl类的对象$page,然后执行函数get()发出请求。
伺服器输送回来资料中,有两部分是很重要的,一是报头,一是网页内容。
报头资料可从执行函数getHeader()取得。
将domain nam更换成google.com (您也可以试试别的网站域名), 结果是
Web Page Header Array ( [url] => http://www.google.com/ [content_type] => text/html; charset=ISO-8859-1 [http_code] => 200 [header_size] => 1114 [request_size] => 102 [filetime] => -1 [ssl_verify_result] => 0 [redirect_count] => 1 [total_time] => 0.686 [namelookup_time] => 0.031 [connect_time] => 0.046 [pretransfer_time] => 0.046 [size_upload] => 0 [size_download] => 51402 [speed_download] => 74930 [speed_upload] => 0 [download_content_length] => 219 [upload_content_length] => 0 [starttransfer_time] => 0.093 [redirect_time] => 0.094 [certinfo] => Array ( ) [redirect_url] => )
当中最重要的是http_code.
如果http_code数值是200,伺服器有回传完整网页源文件,我们就可开始采集资料。否则不能采集。
执行函数getStatus就可取得http_code数值。
Web Page Status 200
如果要知道回传的网页内容,可执行函数getBody()。如果您有浏览器在XAMPP环境下执行,您会看到内容和目标网站一样。这是因为浏览器试图翻译源文件的HTML标签。
google_httpcurl.jpg要查看实际的源文件,点击鼠标右键并选择“View Source”。
处理重定向
还有一件事情需先处里。
我们的目标网页可能设置重定向。更糟的是网站可能有意或无意间设下“蜘蛛陷阱”,如网页甲重定向去网页乙,网页乙又重定向去网页丙,那网页丙重定向回去网页甲,那我们的脚本尤如跌入“无间道”的无尽轮回。(当然PHP的最长执行时间会帮我们的脚本解套。)
再举个例子,将domain name更改为"php8legs.com",因为本站已设置重定向,视您的浏览器设置而定,网页重定向英文php8legs.com/en或中文php8legs.com/zh,这让脚本得不到网页源文件。
Web Page Header Array ( [url] => http://php8legs.com [content_type] => text/html; charset=utf-8 [http_code] => 301 [header_size] => 315 [request_size] => 51 [filetime] => -1 [ssl_verify_result] => 0 [redirect_count] => 0 [total_time] => 1.467 [namelookup_time] => 0 [connect_time] => 0.281 [pretransfer_time] => 0.281 [size_upload] => 0 [size_download] => 0 [speed_download] => 0 [speed_upload] => 0 [download_content_length] => 0 [upload_content_length] => 0 [starttransfer_time] => 1.467 [redirect_time] => 0 [certinfo] => Array ( ) [redirect_url] => http://php8legs.com/en/ ) Web Page Status 301 Web Page Body
我们可以添加 CURLOPT_FOLLOWLOCATION 为 TURE, 以及CURLOPT_MAXREDIRS 为一个小数目。
$this->_options['CURLOPT_FOLLOWLOCATION'] = TRUE;
$this->_options['CURLOPT_MAXREDIRS'] = 5;
如以上例子,最多五次重定向后就会脱离循环。
所以HttpCurl类最后改为:
<?php class HttpCurl { private $_info, $_body; public function __construct() { if (!function_exists('curl_init')) { throw new Exception('cURL not enabled!'); } } public function get($url) { $this->request($url); } protected function request($url) { $ch = curl_init(); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE); curl_setopt($ch, CURLOPT_MAXREDIRS, 5); curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); curl_setopt($ch, CURLOPT_URL, $url); $this->_body = curl_exec($ch); $this->_info = curl_getinfo($ch); $this->_error = curl_error($ch); curl_close($ch); } public function getStatus() { return $this->_info[http_code]; } public function getHeader() { return $this->_info; } public function getBody() { return $this->_body; } public function __destruct() { } } ?>
接下来我们就可以向网页源文件开刀啦!