《一個簡單的開源PHP爬蟲框架——Phpfetcher》要點:
本文介紹了一個簡單的開源PHP爬蟲框架——Phpfetcher,希望對您有用。如果有疑問,可以聯(lián)系我們。
我就是在頭條號湊個熱鬧,歡迎大家到http://blog.reetsee.com/archives/366查看原文.
轉(zhuǎn)載請注明:吹水小鎮(zhèn) | reetsee.com
原文鏈接地址:http://blog.reetsee.com/archives/366
—————————————————
好久不見了!我終于又寫一篇日志了,本來有很多流水帳想發(fā)但是感覺沒營養(yǎng),就作罷了.
今天我主要分享一個簡單的PHP爬蟲框架,名字叫:Phpfetcher
項目的地址是:https://github.com/fanfank/phpfetcher
這個框架的作者是:reetsee.xu,即吹水.
把整個項目下載下來后,在Linux下的終端直接執(zhí)行demo文件夾下的single_page.php即可看到效果.不過在執(zhí)行demo文件前,先設(shè)置一下你的終端編碼為UTF-8以免顯示亂碼:
export.UTF-8
—————————————————
0 背景
背景是這樣的目前吹水新聞(http://news.reetsee.com)下的內(nèi)容全部由Python的爬蟲抓取,使用的框架是Python的Scrapy,而吹水新聞目前是運行在BAE(百度應(yīng)用引擎)下的,每個月還需要交錢.目前我的想法是把吹水新聞完全遷移到目前這臺阿里云主機上,并且原本的新聞我每天都手動執(zhí)行一次腳本來抓取再更新到網(wǎng)站,等遷移到這里后就能直接使用Crontab定時腳本自動更新新聞了!
最近工作都在用PHP,開發(fā)網(wǎng)站的新頁面要PHP,直接讀寫數(shù)據(jù)庫也能用PHP,那么就直接用PHP重構(gòu)新聞網(wǎng)站好了.
準(zhǔn)備開干的時候卻發(fā)現(xiàn)沒找到一個好的PHP爬蟲框架(可能是我沒仔細(xì)找),于是就打算自己寫一個,因此就有了這個Phpfetcher.
名字起得略好……但是代碼寫得略搓……不管怎么樣,目前基本可以用,而且應(yīng)該能滿足不少簡單的需求,下面就是使用示例.
—————————————————
1 基本概念
在Phpfetcher中有四個主要的對象,依次是:Dom,Page,Crawler,Manager.
Dom對象用來解析html,能夠訪問html里的dom;
Page對象對應(yīng)到一個具體的html頁面,能夠取得整個網(wǎng)頁的內(nèi)容,Page對象中有一個Dom對象的成員;
Crawler對象可以理解為就是爬蟲對象,用來設(shè)置要爬取頁面的規(guī)則;
Manager對象原本是用來管理Crawler對象的,以后或許能用來在多進程環(huán)境下使用,但目前沒有實現(xiàn),所以暫時沒有用;
大致概念就是這樣了,實際使用主要是操作Crawler對象.在Phpfetcher中,你可以實現(xiàn)自己的Dom,Page和Crawler,只要符合基類的要求即可.
要說明的是Phpfetcher的默認(rèn)Page對象中的Dom對象使用的是simple_html_dom,沒有使用PHP提供的DOMDocument類,因為我發(fā)現(xiàn)DOMDocument對HTML格式的內(nèi)容兼容性比較差,有時網(wǎng)頁中混入其它內(nèi)容時可能解析不出dom.
下面這張是圖是Phpfetcher的目錄結(jié)構(gòu):
你可以根據(jù)自己的需要定制想要的Crawler,Page,Dom類,默認(rèn)情況下我提供了Crawler的默認(rèn)類是Phpfetcher_Crawler_Default,Page的默認(rèn)類是Phpfetcher_Page_Default,Dom的默認(rèn)類是Phpfetcher_Dom_SimpleHtmlDom.類名和它們所在的路徑有對應(yīng)關(guān)系.要注意的是,在使用默認(rèn)的Page對象時需要PHP的curl庫,使用默認(rèn)的Crawler對象時需要使用PHP的mb_string庫,沒有的需要裝一下.
為了便于理解,我畫了幾張圖,第一張是Phpfetcher的三個主要對象之間的關(guān)系:
圖里表示的是Crawler里面有Page的對象,Page里面有Dom的對象.
在使用Phpfetcher時,最重要的是完成下圖中兩個綠色矩形框要求的事情:
即你要寫一個類繼承Phpfetcher提供的Crawler類,然后在你自己的類中實現(xiàn)一個名為handlePage($page)的函數(shù).其中$page參數(shù)是一個Phpfetcher的Page類對象.
最后這里給出一個基本的流程圖:
上面說的東西有點虛,那還是直接看實例吧!
—————————————————
2 簡單例子
****** 實例1:single_page.php ******
例如我們要抓取這個網(wǎng)站的內(nèi)容:http://news.qq.com/a/20140927/026557.htm
里面有很多超鏈接,有標(biāo)題,有新聞詳細(xì)內(nèi)容,或者其它我們關(guān)心的內(nèi)容.
先看一下下面的例子:
<?php
require_once('phpfetcher.php');
class mycrawler extends Phpfetcher_Crawler_Default {
public function handlePage($page) {
//打印處當(dāng)前頁面的title
$res = $page->sel('//title');
for ($i = 0; $i < count($res); ++$i) {
echo $res[$i]->plaintext;
echo "\n";
}
}
}
$crawler = new mycrawler();
$arrJobs = array(
//任務(wù)的名字隨便起,這里把名字叫qqnews
//the key is the name of a job, here names it qqnews
'qqnews' => array(
'start_page' => 'http://news.qq.com/a/20140927/026557.htm', //起始網(wǎng)頁
'link_rules' => array(
/*
* 所有在這里列出的正則規(guī)則,只要能匹配到超鏈接,那么那條爬蟲就會爬到那條超鏈接
* Regex rules are listed here, the crawler will follow any hyperlinks once the regex matches
*/
),
//爬蟲從開始頁面算起,最多爬取的深度,設(shè)置為1表示只爬取起始頁面
//Crawler's max following depth, 1 stands for only crawl the start page
'max_depth' => 1,
) ,
);
//$crawler->setFetchJobs($arrJobs)->run(); 這一行的效果和下面兩行的效果一樣
$crawler->setFetchJobs($arrJobs);
$crawler->run();
將這個腳本和“phpfetcher.php”以及“Phpfetcher”文件夾放在同一個目錄下(或者將“phpfetcher.php”和“Phpfetcher”放到你的PHP環(huán)境默認(rèn)include的查找路徑),執(zhí)行這個腳本,得到的輸出如下:
[root@reetsee demo]# php single_page.php
王思聰回應(yīng)遭警方調(diào)查:帶弓箭不犯法 我是綠箭俠_新聞_騰訊網(wǎng)
查看一下我們抓取的網(wǎng)頁源代碼,可以發(fā)現(xiàn)是下面這幾行中的title標(biāo)簽內(nèi)容提取出來了:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312"></meta>
<meta charset="gb2312"></meta>
<title>
王思聰回應(yīng)遭警方調(diào)查:帶弓箭不犯法 我是綠箭俠_新聞_騰訊網(wǎng)
</title>
上面就是一個最簡單的例子.
****** 實例2:multi_page.php ******
接下來就是另外一個簡單的例子,例如說騰訊新聞的主頁,上面有各種新聞,我們這次的目標(biāo)是把騰訊新聞主頁(http://news.qq.com)顯示的部分新聞標(biāo)題抓下來,直接先上例程:
<?php
//下面兩行使得這個項目被下載下來后本文件能直接運行
$demo_include_path = dirname(__FILE__) . '/../';
set_include_path(get_include_path() . PATH_SEPARATOR . $demo_include_path);
require_once('phpfetcher.php');
class mycrawler extends Phpfetcher_Crawler_Default {
public function handlePage($page) {
//打印處當(dāng)前頁面的第1個h1標(biāo)題內(nèi)榮(下標(biāo)從0開始)
$strFirstH1 = trim($page->sel('//h1', 0)->plaintext);
if (!empty($strFirstH1)) {
echo $page->sel('//h1', 0)->plaintext;
echo "\n";
}
}
}
$crawler = new mycrawler();
$arrJobs = array(
//任務(wù)的名字隨便起,這里把名字叫qqnews
//the key is the name of a job, here names it qqnews
'qqnews' => array(
'start_page' => 'http://news.qq.com', //起始網(wǎng)頁
'link_rules' => array(
/*
* 所有在這里列出的正則規(guī)則,只要能匹配到超鏈接,那么那條爬蟲就會爬到那條超鏈接
* Regex rules are listed here, the crawler will follow any hyperlinks once the regex matches
*/
'#news\.qq\.com/a/\d+/\d+\.htm$#',
),
//爬蟲從開始頁面算起,最多爬取的深度,設(shè)置為2表示爬取深度為1
//Crawler's max following depth, 1 stands for only crawl the start page
'max_depth' => 2,
) ,
);
$crawler->setFetchJobs($arrJobs)->run(); //這一行的效果和下面兩行的效果一樣
//$crawler->setFetchJobs($arrJobs);
//$crawler->run();
相比于第1個例子,變化的地方有幾個:首先這次我們增加了一條爬蟲跟蹤的規(guī)則“#news\.qq\.com/a/\d+/\d+\.htm$#”(注:PHP使用pcre正則表達(dá)式,可以到PHP關(guān)于正則表達(dá)式的頁面看一下),這是一個正則表達(dá)式,例如這種超鏈接“news.qq.com/a/12345678/00234.htm”那么爬蟲就會跟蹤;然后是我們把爬蟲的最大跟蹤深度設(shè)置為2,這樣爬蟲會跟蹤1次起始頁面上符合要求的超級鏈接;最后是我把原本的Dom選擇從“//title”改為了“//h1”,意思就是抓取h1標(biāo)簽的內(nèi)容而不是像之前那樣抓取title標(biāo)簽,想知道這種Dom選擇器的選擇規(guī)則,需要了解一下xpath.
運行這個文件,能夠看到大致效果如下:
這樣第二個例子就結(jié)束了.
暫時我就介紹這兩個例子吧,Phpfetcher的源代碼在這里:https://github.com/fanfank/phpfetcher
把代碼下載下來后,demo內(nèi)的東西就可以直接運行了(當(dāng)然你需要一個有curl和mb_string擴展的php,可以使用“php -m”命令來看一下你的PHP有沒有裝這兩個擴展).
—————————————————
3 后話
實際上這個phpfetcher目前還有很多問題,性能應(yīng)該是比較差的,不過畢竟也是我寫的第一個框架.
另外是關(guān)于phpfetcher我有很多東西還沒有提到,例如Page對象的一些設(shè)置,Crawler對象的設(shè)置等,主要是目前太過懶不想寫文檔,也不知道有沒有必要寫.我感覺這個框架還是蠻簡單的,里面主要的函數(shù)我都做了詳細(xì)的注釋,歡迎閱讀批評指正給建議!
最后就是,如果你想寫個爬蟲,又想用PHP來寫,不妨試一下phpfetcher.
轉(zhuǎn)載請注明:吹水小鎮(zhèn) | reetsee.com
原文鏈接地址:http://blog.reetsee.com/archives/366
維易PHP培訓(xùn)學(xué)院每天發(fā)布《一個簡單的開源PHP爬蟲框架——Phpfetcher》等實戰(zhàn)技能,PHP、MYSQL、LINUX、APP、JS,CSS全面培養(yǎng)人才。
轉(zhuǎn)載請注明本頁網(wǎng)址:
http://www.snjht.com/jiaocheng/9363.html