數據采集,大部分是用正則表達式,我簡單地介紹下如何實現采集的思路.這裡說的是php的實現.一般是本機運行,放到空間上是不明智的,因為不但很耗資源還需要支持遠程抓取函數,比如file_get_contents($urls)file($url)等.
1,文章列表頁面的自動切換,以及文章路徑的獲得.
2,獲得:標題,內容
3,入庫
4,問題
1,文章列表頁面的自動切換,以及文章路徑的獲得.
a,列表頁面的自動切換一般依賴動態頁面來實現.比如
http://www.phpfirst.com/foru ... d=1&page=$i
可以在後面利用$i的自動增加或范圍來實現,比如$i++;
也可以像penzi演示的那個一樣,要從第幾頁到第幾頁,代碼方面控制$i的范圍就可以.
b,文章路徑的獲得分需要填正則和無需填正則2種:
1)無需填正則就是獲得上面的文章列表頁面的所有連接
但是最好對連接進行過濾,處理---判斷重復連接,只留一個,處理相對路徑,變成絕對路徑.比如../ 和./等.
以下是我寫的亂七八糟的實現函數:
PHP:
--------------------------------------------------------------------------------
//$e=clinchgeturl("http://phpfirst.com/forumdisplay.php?fid=1");
//var_dump($e);
function clinchgeturl($url)
{
//$url="http://127.0.0.1/1.htm";
//$rootpath="http://fsrootpathfsfsf/yyyyyy/";
//var_dump($rrr);
if(eregi((.)*[.](.)*,$url)){
$roopath=split("/",$url);
$rootpath="http://".$roopath[2]."/";
$nnn=count($roopath)-1;for($yu=3;$yu<$nnn;$yu++){$rootpath.=$roopath[$yu]."/";}
// var_dump($rootpath); //http: ,,127.0.0.1,xnml,index.php
}
else{$rootpath=$url; //var_dump($rootpath);
}
if(isset($url)){
echo "$url 有下列裢接:
";
$fcontents = file($url);
while(list(,$line)=each($fcontents)){
while(eregi((href[[:space:]]*=[[:space:]]*"?[[:alnum:]:@/._-]+[?]?[^"]*"?),$line,$regs)){
//$regs[1] = eregi_replace((href[[:space:]]*=[[:space:]]*"?)([[:alnum:]:@/._-]+)("?),"\2",$regs[1]);
$regs[1] = eregi_replace((href[[:space:]]*=[[:space:]]*["]?)([[:alnum:]:@/._-]+[?]?[^"]*)(.*)[^"/]*(["]?),"\2",$regs[1]);
if(!eregi(^http://,$regs[1])){
if(eregi(^..,$regs[1])){
// $roopath=eregi_replace((http://)?([[:alnum:]:@/._-]+)[[:alnum:]+](.*)[[:alnum:]+],"http://\2",$url);
$roopath=split("/",$rootpath);
$rootpath="http://".$roopath[2]."/";
//echo "這是根本d :"." ";
$nnn=count($roopath)-1;for($yu=3;$yu<$nnn;$yu++){$rootpath.=$roopath[$yu]."/";}
//var_dump($rootpath);
if(eregi(^..[/[:alnum:]],$regs[1])){
//echo "這是../目錄/ :"." ";
//$regs[1]="../xx/xxxxxx.xx";
// $rr=split("/",$regs[1]);
//for($oooi=1;$oooi
$rrr=$regs[1];
// {$rrr.="/".$rr[$oooi];
$rrr = eregi_replace("^[.][.][/]",,$rrr); //}
$regs[1]=$rootpath.$rrr;
}
}else{
if(eregi(^[[:alnum:]],$regs[1])){ $regs[1]=$rootpath.$regs[1]; }
else{ $regs[1] = eregi_replace("^[/]",,$regs[1]); $regs[1]=$rootpath.$regs[1]; }
}
}
$line = $regs[2];
if(eregi((.)*[.](htm|shtm|html|asp|aspx|php|jsp|cgi)(.)*,$regs[1])){
$out[0][]=$regs[1]; }
}
}
}for ($ouou=0;$ouou
{
if($out[0][$ouou]==$out[0][$ouou+1]){
$sameurlsum=1;
//echo "sameurlsum=1:";
for($sameurl=1;$sameurl
if($out[0][$ouou+$sameurl]==$out[0][$ouou+$sameurl+1]){$sameurlsum++;}
else{break;}
}
for($p=$ouou;$p
{ $out[0][$p]=$out[0][$p+$sameurlsum];}
}
}
$i=0;
while($out[0][++$i]) {
//echo $root.$out[0][$i]." ";
$outed[0][$i]=$out[0][$i];
}
unset($out);
$out=$outed; return $out;
}
?>
上面的東西只能zend,不然有礙市容:(
得到所有唯一的連接後,放到數組
2)需要填正則的處理
如果要准確地獲得需要的文章連接,就用這個辦法
按照ketle的思路
用
PHP:
--------------------------------------------------------------------------------
function cut($file,$from,$end){
$message=explode($from,$file);
$message=explode($end,$message[1]);
return $message[0];
}
$from是列表前面的html代碼
$end是列表後面的html代碼
以上可以通過表單提交參數.
對列表頁面不是列表的部分去除,剩下的是需要的連接,
只要再通過下面正則得到:
PHP:
--------------------------------------------------------------------------------
preg_match("/^(http://)?(.*)/i",
$url, $matches);
return $matches[2];
2,獲得:標題,內容
a首先,利用得到的文章路徑,讀取目標路徑
可以通過以下函數:
PHP:
--------------------------------------------------------------------------------
function getcontent($url) {
if($handle = fopen ($url, "rb")){
$contents = "";
do {
$data = fread($handle, 2048);
if (strlen($data) == 0) {
break;
}
$contents .= $data;
} while(true);
fclose ($handle);
}
else
exit("........");
return $contents;
}
或者直接
PHP:
--------------------------------------------------------------------------------
file_get_contents($urls);
後者比較方便,但是缺點對比上面的就知道.
b,接下來得到標題:
一般用這個實現:
PHP:
--------------------------------------------------------------------------------
preg_match("||",$allcontent,$title);
裡面的部分通過提交表單得到.
也可以通過一系列的cut函數
比如上面提過的function cut($file,$from,$end),具體的字符串切割可以通過字符處理函數切割實現,後面"取得內容"詳細講.
c,取得內容
取得內容方面和取得標題思路一樣但情況比較復雜,因為內容附近不會是這麼簡單.
1)內容附近的特征字符串有雙引號,空格,換行符號等是大障礙
雙引號需要變成 " 可以通過addslashes()處理
換行符號要去掉 可以通過
PHP:
--------------------------------------------------------------------------------
$a=ereg_replace(" ", , $a);
$a=ereg_replace("", , $a);
去掉.
2)思路2,利用一大堆切割相關的函數對內容提取,需要大量的實踐,調試,我正在弄這裡,沒有獲得什麼突破~~~~~~~~
3,入庫
a,切保你的數據庫可以插入
比如我的可以這樣直接插入:
PHP:
--------------------------------------------------------------------------------
$sql="INSERT INTO $articles VALUES (, $title, , $article,, , clinch, from, 關鍵詞, 1, $欄目id, $time, 1); ";
其中
PHP:
--------------------------------------------------------------------------------
(,
是自動升序的