這篇文章首發在吹水小鎮:http://blog.reetsee.com/archives/366php
要在手機或者電腦看到更好的圖片或代碼歡迎到博文原地址。也歡迎到博文原地址批評指正。html
轉載請註明: 吹水小鎮 | reetsee.com
原文連接地址: http://blog.reetsee.com/archives/366
git
——————————————————————————————github
我最終又寫一篇日誌了,原本有很是多流水賬想發但是感受沒養分,就做罷了。今天我主要分享一個簡單的PHP爬蟲框架。名字叫:Phpfetcher項目的地址是:https://github.com/fanfank/phpfetcher這個框架的做者是:reetsee.xu。即吹水。數據庫
把整個項目下載下來後,在Linux下的終端直接運行demo目錄下的single_page.php就能夠看到效果。bash
只是在運行demo文件前,先設置一下你的終端編碼爲UTF-8以避免顯示亂碼: 框架
export LANG=en_US.UTF-8————————————————————————————————
近期工做都在用PHP,開發站點的新頁面要PHP,直接讀寫數據庫也能用PHP,那麼就直接用PHP重構新聞站點好了。dom
準備開乾的時候卻發現沒找到一個好的PHP爬蟲框架(多是我沒細緻找)。因而就打算本身寫一個,所以就有了這個Phpfetcher。名字起得略好……但是代碼寫得略搓……不管怎麼樣。眼下基本可以用,而且應該能知足很多簡單的需求,如下就是使用演示樣例。curl
要說明的是Phpfetcher的默認Page對象中的Dom對象使用的是simple_html_dom,沒有使用PHP提供的DOMDocument類,因爲我發現DOMDocument對HTML格式的內容兼容性比較差。有時網頁中混入其餘內容時可能解析不出dom。如下這張是圖是Phpfetcher的文件夾結構:你可以依據本身的需要定製想要的Crawler,Page,Dom類。默認狀況下我提供了Crawler的默認類是Phpfetcher_Crawler_Default。Page的默認類是Phpfetcher_Page_Default。Dom的默認類是Phpfetcher_Dom_SimpleHtmlDom。類名和它們所在的路徑有相應關係。要注意的是,在使用默認的Page對象時需要PHP的curl庫,使用默認的Crawler對象時需要使用PHP的mb_string庫,沒有的需要裝一下。爲了便於理解。我畫了幾張圖,第一張是Phpfetcher的三個主要對象之間的關係:
圖裏表示的是Crawler裏面有Page的對象,Page裏面有Dom的對象。scrapy
在使用Phpfetcher時,最重要的是完畢下圖中兩個綠色矩形框要求的事情:即你要寫一個類繼承Phpfetcher提供的Crawler類,而後在你本身的類中實現一個名爲handlePage($page)的函數。
當中$page參數是一個Phpfetcher的Page類對象。最後這裏給出一個主要的流程圖: 上面說的東西有點虛,那仍是直接看實例吧!
先看一下如下的樣例:
<?將這個腳本和「phpfetcher.php」以及「Phpfetcher」文件夾放在同一個文件夾下(或者將「phpfetcher.php」和「Phpfetcher」放到你的PHP環境默認include的查找路徑),運行這個腳本,獲得的輸出例如如下:php require_once('phpfetcher.php'); class mycrawler extends Phpfetcher_Crawler_Default { public function handlePage($page) { //打印處當前頁面的title $res = $page->sel('//title'); for ($i = 0; $i < count($res); ++$i) { echo $res[$i]->plaintext; echo "\n"; } } } $crawler = new mycrawler(); $arrJobs = array( //任務的名字隨便起,這裏把名字叫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', //起始網頁 'link_rules' => array( /* * 所有在這裏列出的正則規則,僅僅要能匹配到超連接,那麼那條爬蟲就會爬到那條超連接 * Regex rules are listed here, the crawler will follow any hyperlinks once the regex matches */ ), //爬蟲從開始頁面算起。最多爬取的深度,設置爲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();
[root@reetsee demo]# php single_page.php 王思聰迴應遭警方調查:帶弓箭不犯法 我是綠箭俠_新聞_騰訊網查看一下咱們抓取的網頁源碼。可以發現是如下這幾行中的title標籤內容提取出來了:
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta http-equiv="Content-Type" content="text/html; charset=gb2312"></meta> <meta charset="gb2312"></meta> <title> 王思聰迴應遭警方調查:帶弓箭不犯法 我是綠箭俠_新聞_騰訊網 </title>上面就是一個最簡單的樣例。 ****** 實例2:multi_page.php ******接下來就是另一個簡單的樣例,好比說騰訊新聞的主頁,上面有各類新聞,咱們此次的目標是把騰訊新聞主頁( http://news.qq.com)顯示的部分新聞標題抓下來。直接先上例程:
<?相比於第1個樣例,變化的地方有幾個:首先此次咱們添加了一條爬蟲跟蹤的規則「#news\.qq\.com/a/\d+/\d+\.htm$#」(注:PHP使用pcre正則表達式,可以到 PHP關於正則表達式的頁面看一下)。這是一個正則表達式。好比這樣的超連接「news.qq.com/a/12345678/00234.htm」那麼爬蟲就會跟蹤。而後是咱們把爬蟲的最大跟蹤深度設置爲2,這樣爬蟲會跟蹤1次起始頁面上符合要求的超級連接;最後是我把本來的Dom選擇從「//title」改成了「//h1」。意思就是抓取h1標籤的內容而不是像以前那樣抓取title標籤,想知道這樣的Dom選擇器的選擇規則,需要了解一下 xpath。執行這個文件,可以看到大體效果例如如下: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) { //打印處當前頁面的第1個h1標題內榮(下標從0開始) $strFirstH1 = trim($page->sel('//h1', 0)->plaintext); if (!empty($strFirstH1)) { echo $page->sel('//h1', 0)->plaintext; echo "\n"; } } } $crawler = new mycrawler(); $arrJobs = array( //任務的名字隨便起。這裏把名字叫qqnews //the key is the name of a job, here names it qqnews 'qqnews' => array( 'start_page' => 'http://news.qq.com', //起始網頁 'link_rules' => array( /* * 所有在這裏列出的正則規則,僅僅要能匹配到超連接,那麼那條爬蟲就會爬到那條超連接 * Regex rules are listed here, the crawler will follow any hyperlinks once the regex matches */ '#news\.qq\.com/a/\d+/\d+\.htm$#', ), //爬蟲從開始頁面算起,最多爬取的深度,設置爲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();
臨時我就介紹這兩個樣例吧,Phpfetcher的源碼在這裏:https://github.com/fanfank/phpfetcher把代碼下載下來後。demo內的東西就可以直接執行了(固然你需要一個有curl和mb_string擴展的php,可以使用「php -m」命令來看一下你的PHP有沒有裝這兩個擴展)。