php 經(jīng)常被抱怨沒有多線程,做爬蟲很吃力,其實(shí)一直一個誤解,curl_multi_init 就是一個很好的多線程發(fā)方法。
配合 domDocment 類可以很完美的實(shí)現(xiàn)爬蟲功能,下面是例子代碼,并不包含解析html
<?php
set_time_limit(0);
ob_start();
$urls = array(
'http://www.sina.com.cn/',
'http://www.sohu.com/',
'http://www.163.com/',
'http://www.zhihu.com/',
'http://www.xunlei.com/',
'http://www.xiachufang.com/',
'http://www.163.com/',
'http://www.gelonghui.com/',
'http://www.itdecent.cn/',
'http://www.sina.com.cn/',
'http://www.sohu.com/',
'http://www.163.com/',
'http://www.zhihu.com/',
'http://www.xunlei.com/',
'http://www.xiachufang.com/',
'http://www.163.com/',
'http://www.gelonghui.com/',
'http://www.itdecent.cn/',
'http://www.sina.com.cn/',
'http://www.sohu.com/',
'http://www.163.com/',
'http://www.zhihu.com/',
'http://www.xunlei.com/',
'http://www.xiachufang.com/',
'http://www.163.com/',
'http://www.gelonghui.com/',
'http://www.itdecent.cn/',
'http://www.sina.com.cn/',
'http://www.sohu.com/',
'http://www.163.com/',
'http://www.zhihu.com/',
'http://www.xunlei.com/',
'http://www.xiachufang.com/',
'http://www.163.com/',
'http://www.gelonghui.com/',
'http://www.itdecent.cn/',
'http://www.xiachufang.com/',
'http://www.163.com/',
'http://www.gelonghui.com/',
'http://www.itdecent.cn/',
'http://www.sina.com.cn/',
'http://www.sohu.com/',
'http://www.163.com/',
'http://www.zhihu.com/',
'http://www.xunlei.com/',
'http://www.xiachufang.com/',
'http://www.163.com/',
'http://www.gelonghui.com/',
'http://www.itdecent.cn/',
'http://www.sina.com.cn/',
'http://www.sohu.com/',
'http://www.163.com/',
'http://www.zhihu.com/',
'http://www.xunlei.com/',
'http://www.xiachufang.com/',
'http://www.163.com/',
'http://www.gelonghui.com/',
'http://www.itdecent.cn/',
'http://www.xiachufang.com/',
'http://www.163.com/',
'http://www.gelonghui.com/',
'http://www.itdecent.cn/',
'http://www.sina.com.cn/',
'http://www.sohu.com/',
'http://www.163.com/',
'http://www.zhihu.com/',
'http://www.xunlei.com/',
'http://www.xiachufang.com/',
'http://www.163.com/',
'http://www.gelonghui.com/',
'http://www.itdecent.cn/',
'http://www.sina.com.cn/',
'http://www.sohu.com/',
'http://www.163.com/',
'http://www.zhihu.com/',
'http://www.xunlei.com/',
'http://www.xiachufang.com/',
'http://www.163.com/',
'http://www.gelonghui.com/',
'http://www.itdecent.cn/',
'http://www.xiachufang.com/',
'http://www.163.com/',
'http://www.gelonghui.com/',
'http://www.itdecent.cn/',
'http://www.sina.com.cn/',
'http://www.sohu.com/',
'http://www.163.com/',
'http://www.zhihu.com/',
'http://www.xunlei.com/',
'http://www.xiachufang.com/',
'http://www.163.com/',
'http://www.gelonghui.com/',
'http://www.itdecent.cn/',
'http://www.sina.com.cn/',
'http://www.sohu.com/',
'http://www.163.com/',
'http://www.zhihu.com/',
'http://www.xunlei.com/',
'http://www.xiachufang.com/',
'http://www.163.com/',
'http://www.gelonghui.com/',
'http://www.itdecent.cn/',
'http://www.itdecent.cn/',
'http://www.xiachufang.com/',
'http://www.163.com/',
'http://www.gelonghui.com/',
'http://www.itdecent.cn/',
'http://www.sina.com.cn/'
);
//生命一個計算腳本運(yùn)行時間的類
class Timer{
private $startTime = 0; //保存腳本開始執(zhí)行時的時間(以微秒的形式保存)
private $stopTime = 0; //保存腳本結(jié)束執(zhí)行時的時間(以微秒的形式保存)
//在腳本開始處調(diào)用獲取腳本開始時間的微秒值
function start(){
$this->startTime = microtime(true); //將獲取的時間賦值給成員屬性$startTime
}
//腳本結(jié)束處嗲用腳本結(jié)束的時間微秒值
function stop(){
$this->stopTime = microtime(true); //將獲取的時間賦給成員屬性$stopTime
}
//返回同一腳本中兩次獲取時間的差值
function spent(){
//計算后4舍5入保留4位返回
return round(($this->stopTime-$this->startTime),4);
}
}
$timer= new Timer();
$timer->start(); //在腳本文件開始執(zhí)行時調(diào)用這個方法
ob_end_clean();
//$save_to='./test.txt'; // 把抓取的代碼寫入該文件
//$st = fopen($save_to,"a");
$mh = curl_multi_init();
foreach ($urls as $i => $url) {
$conn[$i] = curl_init($url);
curl_setopt($conn[$i], CURLOPT_USERAGENT, "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0)");
curl_setopt($conn[$i], CURLOPT_HEADER ,0);
curl_setopt($conn[$i], CURLOPT_CONNECTTIMEOUT,60);
curl_setopt($conn[$i],CURLOPT_RETURNTRANSFER,true); // 設(shè)置不將爬取代碼寫到瀏覽器,而是轉(zhuǎn)化為字符串
echo $i;
curl_multi_add_handle ($mh,$conn[$i]);
}
do {
curl_multi_exec($mh,$active);
} while ($active);
foreach ($urls as $i => $url) {
$data = curl_multi_getcontent($conn[$i]); // 獲得爬取的代碼字符串
//fwrite($st,$data.$i); // 將字符串寫入文件。當(dāng)然,也可以不寫入文件,比如存入數(shù)據(jù)庫
file_put_contents("file/".$i.".txt",$data);
echo $url."<br/>";
ob_flush();
flush();
//usleep(200000);
} // 獲得數(shù)據(jù)變量,并寫入文件
foreach ($urls as $i => $url) {
curl_multi_remove_handle($mh,$conn[$i]);
curl_close($conn[$i]);
}
curl_multi_close($mh);
//fclose($st);
$timer->stop(); //在腳本文件結(jié)束處調(diào)用這個方法
echo "run time -> ".$timer->spent()."</b>";
?>