0%

Node.js - 使用 Node.js 簡易爬蟲

模組

node.js 爬蟲需要用到兩個 Library

  • request:主要是用來模擬 HTTP 的動作,可以用來取得整個頁面的 HTML。
  • cheerio:從 HTML 中擷取需要的資料。

安裝

1
2
$ npm i request -s
$ npm i cheerio -s

載入

安裝好後就可以看到專案的 package.json 已經出現,這時候就可以引入程式中。

1
2
const request = require("request");
const cheerio = require("cheerio");

觀察

這邊使用 Ptt Marvel 板檔做範例,會用到 Chrome Dev Tool 來分析網頁的 html。
1.先取得需要的區塊

2.接著可以看到一個 <div class="r-ent"></div> 就是一個小區塊。

實作

找到需要的畫面後,就需要用 request 抓取頁面 html,而這裡的 body 是一整網頁裡 body 的內容。

1
2
3
4
5
6
7
const getMarvelTitle = () => {
request({
url: "https://www.ptt.cc/bbs/Marvel/index.html",
method: "GET"
}, (error, res, body) => {
// 如果有錯誤訊息,或沒有 body(內容),就 return
if (error || !body) return;

接著使用 cheerio 擷取 body 裡需要的部分。

1
2
3
4
5
6
7
8
9
10
11
const data = [];
const $ = cheerio.load(body); // 載入 body
const list = $(".r-list-container .r-ent");
for (let i = 0; i < list.length; i++) {
const title = list.eq(i).find('.title a').text();
const author = list.eq(i).find('.meta .author').text();
const date = list.eq(i).find('.meta .date').text();
const link = list.eq(i).find('.title a').attr('href');

if (title.indexOf('經驗') !== -1) data.push({ title, author, date, link });
}

因為我只想看經驗文所以只撈經驗文出來,撈出來的畫面如下。
這邊使用 for 迴圈是因為父元素 (.r-list-container) 裡包著許多子元素 (.r-ent) 的結構。

除了爬標題外,也可以順便爬文章內容,一樣會使用到 request、cheerio。
不同的是 request 的網址載入 body 後的程式碼

首先一樣先分析網頁,可以看到文章內容是在 <div id="main-content" class="bbs-screen bbs-content"></div> 裡,所以就直接選擇 css="bbs-content" 的元素即可。

1
2
3
4
5
6
7
8
const $ = cheerio.load(body); 
const list = $(".bbs-content");
let word;
list.each(function () {
word = $(this).text()
})

word = word.slice(0, word.indexOf('-----'));

最後爬到的內容會包含下面的留言區塊,直接使用 slice----- 後面的都砍掉,就會單獨顯示文章內容了~