2.去跑一遍采集小說的腳本任務
為了減少依賴,之前采集小說的實現是兩部分:
第一部分:nodejs去目錄頁抓取章節的url,寫入txt文件存儲。
第二部分:php利用封裝的curl類和分析解析類去分別獲取標題內容,寫入HTML文件。
這樣不僅要讓進行定時任務的物理機或docker上要有php環境也要有nodejs環境。由於我擅長php,所以改為兩部分全部由php完成。采集的完整代碼可以見前面寫過的采集類等博客。
curl封裝類beta版的博客記錄: http://www.cnblogs.com/freephp/p/4962591.html.
優化curl封裝類的博客記錄: http://www.cnblogs.com/freephp/p/5112135.html.
如果不熟悉的朋友,可以先看這部分博客后再閱讀本文。
代碼關鍵部分:
$menuUrl = 'http://www.zhuaji.org/read/2531/'; $menuContents = MyCurl::send($menuUrl, 'get'); $analyzer = new Analyzer(); $urls = $analyzer->getLinks($menuContents);
后面再循環去curl每個章節頁面,抓取和解析內容並寫入文件即可。
代碼簡潔和可讀性已經比較好了。現在我們考慮效率和性能問題。這個代碼都是一次性下載完所有文件,唯一做去重判斷都是在每次get到章節內容之后對比文件名是否存在。但已經做了一些無用費時的網絡請求。目前該小說有578章,加上目錄被爬一次,一共要發起578+1次get請求,以后小說還會不斷增加章節,那么執行時間會更長。
這個腳本最大的瓶頸就在網絡消耗上。
此腳本效率不高,每次都是把所有章節的頁面都去爬一次,網絡消耗很大。如果是第一次下載還好,畢竟要下載全部。如果是每天都執行,那么其實我是想增量地去下載前一天新增的章節。
又有幾個思路可以考慮:
1.我們要考慮每次執行之后最后一個被存下來的頁面的id要記錄下來。然后下一次就從這個id開始繼續下載。
2.中間斷掉也可以反復重新跑。(遵從第一條最后一句)
這樣就能從新增的頁面去爬,減少了網絡請求量,執行效率大幅提高。
其實這個問題就變成想辦法記錄執行成功的最后一個章節id的問題了。
我們可以把這個id寫入數據庫,也可以寫入文件。為了簡單和少依賴,我決定還是寫文件。
單獨封裝一個獲取最大id的函數,然后過濾掉已經下載的文件。完整代碼如下:
function getMaxId() { $idLogFiles = './biggestId.txt'; $biggestId = 0; if (file_exists($idLogFiles)) { $fp = fopen($idLogFiles, 'r'); $biggestId = trim(fread($fp, 1024)); fclose($fp); } return $biggestId; } /** * client to run */ set_time_limit(0); require 'Analyzer.php'; $start = microtime(true); $menuUrl = 'http://www.zhuaji.org/read/2531/'; $menuContents = MyCurl::send($menuUrl, 'get'); $biggestId = getMaxId() + 0; $analyzer =new Analyzer(); $urls = $analyzer->getLinks($menuContents); $ids = array(); foreach ($urls as $url) { $parts = explode('.', $url); array_push($ids, $parts[0]); } sort($ids, SORT_NUMERIC); $newIds = array(); foreach ($ids as &$id) { if ((int)$id > $biggestId) array_push($newIds, $id); } if (empty($newIds)) exit('nothing to download!'); foreach ($newIds as $id) { $url = $id . '.html'; $res = MyCurl::send('http://www.zhuaji.org/read/2531/' . $url, 'get'); $title = $analyzer->getTitle($res)[1]; $content = $analyzer->getContent('div', 'content', $res)[0]; $allContents = $title . "<br/>". $content; $filePath = 'D:/www/tempscript/juewangjiaoshi/' . $title . '.html'; if(!file_exists($filePath)) { $analyzer->storeToFile($filePath, $allContents); $idfp = fopen('biggestId.txt', 'w'); fwrite($idfp, $id); fclose($idfp); } else { continue; } echo 'down the url:' , $url , "\r\n"; } $end = microtime(true); $cost = $end - $start; echo "total cost time:" . round($cost, 3) . " seconds\r\n";
加在windows定時任務或linux下的cron即可每天享受小說的樂趣,而不用每次手動去瀏覽網頁浪費流量,解析后的html文件存文字版更舒服。不過這段代碼在低版本的php下會報錯,數組簡化寫法[44,3323,443]是在php5.4之后才出現的。
之前下載完所有小說需要大概2分多鍾。改進最終結果為:

效果顯著,我在/etc/crontab里面設置如下:
0 3 * * * root /usr/bin/php /data/scripts/tempscript/MyCurl.php >> /tmp/downNovel.log
這個作者的小說真心不錯,雖然后期寫得很后宮和文字匱乏,常到12點還在更新,所以把每天定時任務放在凌晨3點采集之。
