NodeJS寫個爬蟲,把文章放到kindle中閱讀


這兩天看了好幾篇不錯的文章,有的時候想把好的文章 down 下來放到 kindle 上看,便寫了個爬蟲腳本,因為最近都在搞 node,所以就很自然的選擇 node 來爬咯~

本文地址:http://www.cnblogs.com/hustskyking/p/spider-with-node.html,轉載請注明源地址。

所謂爬蟲,可以簡單理解為利用程序操作文件,只是這些文件不在本地,需要我們拉取過來。

一. 爬蟲代碼解析

1. 拿到目標頁碼源碼

Node 提供了很多接口來獲取遠程地址代碼,就拿 AlloyTeam 的頁面舉例吧,把他首頁幾篇文章的信息爬取過來。因為 AlloyTeam 使用的協議是 http:// ,本文就不介紹 Node 中 https:// 的使用了。

var http = require("http");

var url = "http://www.alloyteam.com/";
var data = "";

// 創建一個請求
var req = http.request(url, function(res){
    // 設置顯示編碼
    res.setEncoding("utf8");
    // 數據是 chunked 發送,意思就是一段一段發送過來的
    // 我們使用 data 給他們串接起來
    res.on('data', function(chunk){
        data += chunk;
    });
    // 響應完畢時間出發,輸出 data
    res.on('end', function(){
        // dealData(data);
        console.log(data);
    });
});

// 發送請求
req.end();

上面短短七八行代碼,就拿到了 AlloyTeam 首頁的代碼,真的十分簡單,如果是 https:// 就得引用 https 模塊咯,都是差不多的。

2. 正則提取目標內容

先看下我們要抓取的內容: 

由於沒有使用其他庫,我們沒辦法像操作 DOM 一樣獲取目標內容,不過寫正則也挺簡單的,比如我們要 獲取標題/文章鏈接/摘要 這些內容,正則表達式為:

// function dealData
var reg = /<ul\s+class="articlemenu">\s+<li>\s+<a[^>]*>.*?<\/a>\s+<a href="(.*?)"[^>]*>(.*?)<\/a>[\s\S]*?<div\s+class="text">([\s\S]*?)<\/div>/g;
var res = [];
while(match = reg.exec(data)) {
    res.push({
        "url": match[1],
        "title": match[2],
        "excerpt": match[3]
    });
}

這里的正則看起來有點晦澀,不過呢,正則在編程中十分基礎的東西,如果沒有太多的了解,建議先去搞清楚,這里就不細說啦。這里要強調的一點是:

reg.exec(data);

如果只寫上面這句話,只會拿到第一個匹配結果,所以需要使用 while 循環來處理,沒處理一次,正則匹配的位置就會往后推一下。其實上面這條語句執行后返回的是一個對象,其中包含一個 index 屬性,具體可以查閱 JavaScript 正則的內容。

這里返回(res)的數據格式是:

[{
    "url: url,
    "title": title,
    "excerpt" excerpt
}];

3. 數據的過濾

上面雖然拿到了內容,不過我們需要的是純文本,其他標簽什么的得過濾掉,excerpt 中包含了一些標簽:

var excerpt = excerpt.replace(/(<.*?>)((.*?)(<.*?>))?/g, "$3");

雖說文章中有很多代碼,有些標簽是不應該刪除的,不過這里是摘要內容,這些內容的標簽都刪除掉,方便我們儲存。然后把長度處理下:

excerpt = excerpt.slice(0, 120);

4. 存到數據庫(或者文件)

我這里是把文件儲存到文件之中,存放格式為:

[title](url)
> excerpt

哈哈,很熟熟悉吧,markdown 語法,看起來也比較清晰。

var str = "";
for(var i = 0, len = data.length; i < len; i++){
    str += "[" + data[i].title + "](" + data[i].url + ")\n" + data[i].excerpt.replace("\n\s*\n?", ">\n") + "\n\n";
}

先拼接數據,然后寫入到文件:

fs.writeFile('index.md', str, function (err) {
    if (err) throw err;
    console.log('數據已保存~');
});

大功告成,過程其實是很簡單的。拿到的內容(Linux 下,字體真丑!):

二. 源碼與小結

如果對正則不太熟悉,上面的工作是不太好完成的,很多開發者為 Node 提供了工具庫,使用 npm 可以安裝,如果不習慣正則,使用一些工具包輔助處理,可以把拿到的數據當作 DOM 來解析。

我了解到的有一個叫做 node-jquery 的庫貌似還不錯,具體請讀者自己去網上搜吧,應該挺多的。

上面的代碼都是隨手寫的,沒有做什么容錯的機制,也只爬取了首頁的內容,不過思路都是一樣的,拿到 URL 之后再寫個循環,其他頁面的內容也就到手了。

源碼沒幾行:

var http = require("http");
var fs = require("fs");

var url = "http://www.alloyteam.com/";
var data = "";

var req = http.request(url, function(res){
    res.setEncoding("utf8");
    res.on('data', function(chunk){
        data += chunk;
    });
    res.on('end', function(){
        dealData(data);
    });
});

req.on('error', function(e){
    throw e;
});

req.end();
console.log("數據下載中...");


function dealData(data){
    var reg = /<ul\s+class="articlemenu">\s+<li>\s+<a[^>]*>.*?<\/a>\s+<a href="(.*?)"[^>]*>(.*?)<\/a>[\s\S]*?<div\s+class="text">([\s\S]*?)<\/div>/g;
    var res = [];
    while(match = reg.exec(data)) {
        res.push({
            "url": match[1],
            "title": match[2],
            "excerpt": match[3].replace(/(<.*?>)((.*?)(<.*?>))?/g, "$3").slice(0,120)
        });
    }
    writeFile(res)
 }

function writeFile(data){
    var str = "";
    for(var i = 0, len = data.length; i < len; i++){
        str += "[" + data[i].title + "](" + data[i].url + ")\n>" + data[i].excerpt.replace(/\n\s*\n?/g, "\n>") + "\n\n";
    }
    fs.writeFile('index.md', str, function (err) {                                                                                                 
       if (err) throw err;
       console.log('數據已保存~');
    });
}
爬蟲源碼 spider.js

在 node 環境中:

node spider.js

就可以在同級目錄下看到 index.md 文件了。至於如何放到 kindle 中,先了解下 OPF 格式,然后使用 Amazon 的 KindleGen 工具打包就行啦。

三. 參考資料

 


免責聲明!

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



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