Node.jsでrss-parserを使って更新情報を取得する

はじめに

Pythonでfeedparser使ったりもしたんですが、やはり私にはJavaScriptがあっているなぁと感じ、JavaScript(Node.js)でRSSをパースするrss-parserというものを試してみました。
とても簡単で楽しかったです。

rss-parser

A small library for turning RSS XML feeds into JavaScript objects.
bobby-brennan/rss-parser: A lightweight RSS parser, for Node and the browser

インストール

npm i rss-parser  

上のように入れました。
が、今README見てみたところ以下のように書いてありました。

npm install --save rss-parser  

--saveって何だよ。

古いnpmだと必要だったようです。無視します。

使い方

README見てください。
基本的には以下のようになるかと思います(2019/05)。

const Parser = require('rss-parser');  
const parser = new Parser();  

(async () => {  
    const feedUrl = 'https://www.reddit.com/.rss'; // 適当なURL  
    const feed = await parser.parseURL(feedUrl);  
    console.log(feed);  
})();  

awaitを使うのを忘れないようにしましょう。

feedの中身は以下のようになっています(READMEより)。

feedUrl: 'https://www.reddit.com/.rss'  
title: 'reddit: the front page of the internet'  
description: ""  
link: 'https://www.reddit.com/'  
items:  
    - title: 'The water is too deep, so he improvises'  
      link: 'https://www.reddit.com/r/funny/comments/3skxqc/the_water_is_too_deep_so_he_improvises/'  
      pubDate: 'Thu, 12 Nov 2015 21:16:39 +0000'  
      creator: "John Doe"  
      content: '<a href="http://example.com">this is a link</a> &amp; <b>this is bold text</b>'  
      contentSnippet: 'this is a link & this is bold text'  
      guid: 'https://www.reddit.com/r/funny/comments/3skxqc/the_water_is_too_deep_so_he_improvises/'  
      categories:  
          - funny  
      isoDate: '2015-11-12T21:16:39.000Z'  

個人的にisoDateがとても嬉しいです。

サクッと作るよ

#!/usr/bin/env node  

(async () => {  
    const getFeeds = async (...urls) => {  
        const Parser = require('rss-parser');  
        const parser = new Parser();  

        return (await Promise.all(urls.map(url => parser.parseURL(url))))  
            .reduce((acc, cur) => [  
                ...acc,  
                ...cur.items.map(item => ({  
                    title: item.title.trim(),  
                    link: new URL(item.link),  
                    date: new Date(item.isoDate),  
                    site: {  
                        title: cur.title.trim(),  
                        link: new URL(cur.link),  
                    }  
                }))  
            ], [])  
            .sort((a, b) => a.date > b.date ? -1 : 1)  
            ;  
    };  

    const result = (await getFeeds(  
        'http://feed.japan.cnet.com/rss/index.rdf', // CNET  
        'http://gigazine.net/index.php?/news/rss_2.0/', // Gigazine  
        'http://japanese.engadget.com/rss.xml', // Engadget  
        'http://jp.techcrunch.com/feed/', // TechCrunch  
        'http://www.gizmodo.jp/index.xml', // Gizmodo  
    )).map(entry => {  
        return `${entry.title}(${entry.link.toString()}) | ${entry.site.title}`;  
    })  
    .join('\n');  

    console.log(result);  
})();  

特に難しいことはしていませんが説明します。
getFeeds関数にRSSのURLを渡すことによりそのURLから更新情報を取得し整理し新着順にソートします。await Promise.allが肝。reduce()はただの整理用です。
…やっぱ説明することないですね。

おわりに

説明することがないぐらい簡単でした。