簡化日常工作系列之二 ----- 定時采集小說


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點采集之。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM