Node.jsでRSSのデータを取得する【Windows10、RaspberryPi、DragonBoard】
以前からちょっと欲しいなと思っていたのですが、現在のテレビ番組を一覧的に表示できなかなと。テレビをつけてEPGを見ればいいじゃないとというのはもちろんわかっているんですが、もう自分はAmazon Primeなしには生きられない特撮バカですので入力切り替えとかそんなことはもうやりたくありません。(きっぱり)
どうせ、PCつけてコードとか書いているんだしPC上で見れればそれでいいかなと思っていたんです。
テレビを見なければいいという話もあるのかもしれませんが…そういうわけにもいかないので…。
テレビの放送状況を確認するにはテレビ王国
というサイトがあります。
SONYさんが運営しているサービスでHDDレコーダやiEPGなんかでも使われているので比較的確度の高い情報でしょう。
このサイトは全国のエリアをカバーしているので、自分のような地方の人間にも優しいです。また、現在の放送番組のRSSも公開されているので最高です!
RSSはこんな感じ。
Gガイド.テレビ王国 - 放送中のRSS配信 - 地上波(東京)
あとはこのRSSを読み込んでしまえば…ということになります。
今回は他のシステムとの連携もしたかったのNode.js
コーディングしました。
Node.jsでRSSを読み込む
ネットで検索したところWebのスクレイピングではcheerio-httpcli
を使用すると便利そうでした。
特徴としては以下の様です。
- 取得先WEBページの文字コードを自動で判定してHTMLをUTF-8に変換
- UTF-8に変換したHTMLをjQueryのように操作可能
- フォームの送信やリンクのクリックをエミュレート
- Node.jsお馴染みのコールバック形式と最近の流行であるプロミス形式どちらにも対応
- 同期リクエスト対応
- $(‘img’)要素画像のダウンロード(LazyLoad対応)
- $(‘a,img,script,link’)要素のURLを絶対パスで取得可能
- ブラウザ指定による簡単User-Agent切り替え機能
- 現在のクッキーの内容を簡単に取得(読み取り専用)
- XMLドキュメントを自動判別してパース処理を切り替え
半分ぐらいは今回とはあまり関係はないのですが、今後使えそうな機能が多いのでこちらを採用しました。
cheerio-httpcli
のインストール
今回の実行環境(Windows10)は以下の通りです。
PS C:\Users\xxx\Documents\node> node -v v6.11.2 PS C:\Users\xxx\Documents\node> npm -v 3.10.10
インストール作業はnpm
を使えば簡単です。(LinuxでもWindowsでも違いはありません。プロンプトが違うぐらいです。)
PS C:\Users\xxx\Documents\node> npm install cheerio-httpcli
問題なくインストールできました。
コーディング
先程のRSSのURLを.fetch()の引数に与えてあとは、コールバック形式かプロミス形式で処理を行えば問題ありません。プロミスってなんだろうと思ったんですが、「非同期の動作を扱う際にコールバックからメソッドチェーンにすることができコールバック地獄を回避することができる」ってことのようです。非同期処理では結構苦労するので、こういう改良が必要なんですね。
今回は規模的にはどちらを選択しても良かったのですが、せっかくなので
【sample.js】
var client = require('cheerio-httpcli'); // かんとーちほーの現在の放送番組 var RSS = "https://tv.so-net.ne.jp/rss/schedulesByCurrentTime.action?group=10&stationAreaId=23"; client.fetch(RSS, {}) .then(function (result){ if (result.error) { console.log("error"); return; } result.$("item").each(function (idx) { programName = result.$(this).find("title").text(); programFrame = result.$(this).find("description").text(); console.log(programName); console.log(programFrame); console.log("---"); }); console.log("\n" + "放送中番組のタイトルを取得しました。"); });
これを実行してみます。
PS C:\Users\xxx\Documents\node> node .\sample.js Hulu傑作シアター[デ] 9/3 1:30~2:30 [日テレ(Ch.4)] --- 名棋士が読み解く 藤井聡太 “強さ”の秘密[字][再] 9/3 1:45~2:30 [NHK総合・東京(Ch.1)] --- ワールドプロレスリング 9/3 2:00~2:30 [テレビ朝日(Ch.5)] --- お買い物情報 9/3 2:00~2:30 [TOKYO MX1(Ch.9)] --- HERO'S[デ] 9/3 2:05~2:45 [フジテレビ(Ch.8)] --- ランク王国 秋のサキドリSP! 9/3 2:08~3:08 [TBS(Ch.6)] --- 深夜に発見!新shock感~一度おためしください~ 9/3 2:10~2:35 [テレビ東京(Ch.7)] --- 放送休止 9/3 2:12~5:00 [NHKEテレ1・東京(Ch.2)] --- 放送中番組のタイトルを取得しました。
うまく行ったようです。これで取得できるのはタイトル、放送枠時間、放送局だけなので内容がほしい場合には RSS上のlinkタグにあるURLを更にスクレイピングする必要があるので少し面倒ですね。
終わりに
あとはうまい感じで表示できればOKですね。
少し欲を出して、番組情報も出せるようにしました。1回目のRSSのスクレイピングで詳細情報のリンク先を取得し、 2回目のスクレイピングで取得するという感じなのですが、JavaScriptは非同期実行なので、データにタイミングがコードの想定とはズレてしまうようでした。 Objectに格納しようとしたら格納時にはデータがなく、どこでデータ来るのかを判別するのがちょっと難しかったでの悩んでいました。
最初に書いた
- 同期リクエスト対応
こちらのことを思い出して、ググってみました。 以下のリンクに同期的実行に関して情報が乗っていたのでそれを試して見ました。
【参考】 qiita.com
【sample2.js】
var client = require('cheerio-httpcli'); var RSS = "https://tv.so-net.ne.jp/rss/schedulesByCurrentTime.action?group=10&stationAreaId=23"; var programsList = []; var result1 = client.fetchSync(RSS); result1.$("item").each(function (idx) { var program = new Object(); var programName = result1.$(this).find("title").text(); var programFrame = result1.$(this).find("description").text(); var programLink = result1.$(this).find("link").text(); var result2 = client.fetchSync(programLink); programInfo = result2.$(".subUtileSetting").eq(0).find("p").text(); program["Name"] = programName; program["Frame"] = programFrame; program["Link"] = programLink; program["Info"] = programInfo; programsList.push(program); }); programsList.forEach(function(element) { console.log("\n--->\n"); console.log("番組名 :" + element["Name"]); console.log("番組時間 :" + element["Frame"]); console.log("番組リンク:" + element["Link"]); console.log("番組詳細 :" + element["Info"]); });
これを実行させると…
PS C:\Users\xxx\Documents\> node .\sample2.js ---> 番組名 :サンバリュ 「外国人観光客に思い切って注意してみました ニッポンのマナー」[字] 番組時間 :9/3 13:15~14:15 [日テレ(Ch.4)] 番組リンク:http://tv.so-net.ne.jp/schedule/101040201709031315.action?from=rss 番組詳細 :満開の桜の枝をポッキリ折る!市場で生魚を手でベタベタ触る!世界遺産で環境破壊!目に余るマナー違反の外国人観光客を、勇気を出して注意!すると逆ギレ&驚きの言い訳が ---> 番組名 :45th フジサンケイクラシック 最終日[字][デ] 番組時間 :9/3 13:30~14:55 [フジテレビ(Ch.8)] 番組リンク:http://tv.so-net.ne.jp/schedule/101056201709031330.action?from=rss 番組詳細 :世界基準コース富士桜に挑む! 初優勝思い出の舞台で復活V目指す岩田寛! 22歳の若武者が初の頂点へ稲森佑貴! ---> 番組名 :舞台芸術の魅力 第8回「世界の現代演劇-演劇における「20世紀」の意味-」 番組時間 :9/3 13:45~14:30 [放送大学1(Ch.12)] 番組リンク:http://tv.so-net.ne.jp/schedule/101088201709031345.action?from=rss 番組詳細 :京都造形芸術大学教授 森山 直人 ---> 番組名 :海外出張オトモシマス!「フランス 激レア&絶品!チョコ・ハンター」[解][字][再] 番組時間 :9/3 13:50~14:20 [NHK総合・東京(Ch.1)] 番組リンク:http://tv.so-net.ne.jp/schedule/101024201709031350.action?from=rss 番組詳細 :海外出張のプロにオトモして、世界の流行の最前線に潜入する番組。今回の出張は、フランス!激レア絶品チョコの大捜索!パリからブルターニュ地方へ。日本初上陸のチョコ! ---> 番組名 :科捜研の女16 #11[解][字][再] 番組時間 :9/3 13:55~14:50 [テレビ朝日(Ch.5)] 番組リンク:http://tv.so-net.ne.jp/schedule/101064201709031355.action?from=rss 番組詳細 :「グルメ格付け殺人!死を呼ぶ裏メニューで人間発火!?」沢口靖子(他)▽身元不明の外国人男性が殺害された。マリコは 被害者が事件の夜に食事したフレンチ店に鍵があると考え… ---> 番組名 :日本の話芸 林家正雀 落語「怪談牡丹灯籠から お札はがし」[解][字] 番組時間 :9/3 14:00~14:30 [NHKEテレ1・東京(Ch.2)] 番組リンク:http://tv.so-net.ne.jp/schedule/101032201709031400.action?from=rss 番組詳細 :第698回東京落語会から林家正雀さんの「怪談牡丹灯籠から お札はがし」をお送りします(平成29年8月18日(金) 東京・虎ノ門 ニッショーホールで収録) ---> 番組名 :今夜!最大の悲劇がー日曜劇場「ごめん、愛してる」スペシャルダイジェスト[字] 番組時間 :9/3 14:00~14:50 [TBS(Ch.6)] 番組リンク:http://tv.so-net.ne.jp/schedule/101048201709031400.action?from=rss 番組詳細 :クライマックスに向け大きく動き出す長瀬智也主演の胸に迫る切ない物語「ごめん、愛してる」。そこで後編のストーリー&今夜の見所をご紹介! ---> 番組名 :日曜ミステリー「嫌われ監察官 音無一六3」[再] 小日向文世主演[字][解] 番組時間 :9/3 14:00~16:00 [テレビ東京(Ch.7)] 番組リンク:http://tv.so-net.ne.jp/schedule/101072201709031400.action?from=rss 番組詳細 :連続殺人事件の現場に残されたのは、恋愛を詠った百人一首の札。怨恨か?それとも…?監察官・音無一六が“深読み力”で真相を暴く! ≪解説放送あり≫ ---> 番組名 :MXショッピング 番組時間 :9/3 14:00~14:30 [TOKYO MX1(Ch.9)] 番組リンク:http://tv.so-net.ne.jp/schedule/123608201709031400.action?from=rss 番組詳細 :H2OスチームFX 【スチームクリーナー】
個人的には同期的にやったほうがスッキリしますねw。コードも短いし…。
同じソースコードでRaspberryPiとDragonBoard410Cでも実行してみます。
$ node sample2.js ---> 番組名 :決定!こども囲碁名人~第38回少年少女囲碁大会~ 番組時間 :9/3 14:30~16:30 [NHKEテレ1・東京(Ch.2)] 番組リンク:http://tv.so-net.ne.jp/schedule/101032201709031430.action?from=rss 番組詳細 :囲碁を志す全国の小・中学生にとって日本一の栄冠をかけたあこがれの舞台「少年少女囲碁大会・全国大会」今年も、未来の井山七冠を夢見るこどもたちが熱い戦いを繰り広げた ---> 番組名 :路線バスで寄り道の旅[字] 番組時間 :9/3 15:40~16:30 [テレビ朝日(Ch.5)] 番組リンク:http://tv.so-net.ne.jp/schedule/101064201709031540.action?from=rss 番組詳細 :日頃秒刻みスケジュールに疲れ気味の徳さん御一行。のんび~り旅を味わうために選んだのは“路線バス"。今回、目指すのは桜木町~馬車道~山下公園で横浜の裏 通りを散策旅 ---> 番組名 :大捜索ドキュメント! 屋久島“伝説の超巨大杉”[字][再] 番組時間 :9/3 16:00~16:50 [NHK総合・東京(Ch.1)] 番組リンク:http://tv.so-net.ne.jp/schedule/101024201709031600.action?from=rss 番組詳細 :世界遺産・屋久島で語られる『超巨大杉伝説』。縄文杉を超える杉の大捜索に挑んだ。最新航空調査で森をスキャンし、秘境を大冒険。ついに捜索隊は驚きの巨大杉と遭遇する! ---> 番組名 :グラチャンバレー1番は誰?開幕直前SP[字] 番組時間 :9/3 16:00~16:55 [日テレ(Ch.4)] 番組リンク:http://tv.so-net.ne.jp/schedule/101040201709031600.action?from=rss 番組詳細 :9月5日(火)開幕、グラチャンバレー!徳井義実&佐藤栞里がバレー全日本女子を直撃!気になる噂の真相を選手が激白! ---> 番組名 :なるほど!今うなぎが食べたくなるテレビ【旬は秋!画面から香ばしい香りが?!】[解][字] 番組時間 :9/3 16:00~17:00 [TBS(Ch.6)] 番組リンク:http://tv.so-net.ne.jp/schedule/101048201709031600.action?from=rss 番組詳細 :芸能界のグルメ王・渡部建が名店の秘密に迫る!★芸能界屈指の料理人・梅沢富美男が安くて美味しいうなぎレシピに挑戦!★幻の「青うなぎ」を求めて漁に出るのはみやぞん! ---> 番組名 :YOUは何しに日本へ?予習復習▽日本茶&歌声に熱狂YOUマジ惚れ来日大騒ぎ[字] 番組時間 :9/3 16:00~17:05 [テレビ東京(Ch.7)] 番組リンク:http://tv.so-net.ne.jp/schedule/101072201709031600.action?from=rss 番組詳細 :本気で日本茶学びたい!…20歳青年YOUが本場静岡でガチ住み込み修行…超高級茶葉に昇天!?■遠い異国で人生変えた…坂本九匹敵神歌にYOUが全力マジ惚れ旅■ベビ ーメタル ---> 番組名 :いただきハイジャンプ 土曜お昼にお引っ越しSP[字] 番組時間 :9/3 16:00~17:25 [フジテレビ(Ch.8)] 番組リンク:http://tv.so-net.ne.jp/schedule/101056201709031600.action?from=rss 番組詳細 :(予定変更の場合あり) 様々な一大事にJUMPが立ち向かう▽番組引っ越し記念で人気企画を厳選!6歳少年が苦手克服に挑戦…涙のワケとは? ---> 番組名 :お買い物情報 番組時間 :9/3 16:00~16:30 [TOKYO MX1(Ch.9)] 番組リンク:http://tv.so-net.ne.jp/schedule/123608201709031600.action?from=rss 番組詳細 :トゥルースリーパープレミアケア 【低反発マットレス】 ---> 番組名 :障害を知り共生社会を生きる 第8回「難病を知る」 番組時間 :9/3 16:00~16:45 [放送大学1(Ch.12)] 番組リンク:http://tv.so-net.ne.jp/schedule/101088201709031600.action?from=rss 番組詳細 :愛知県立大学教授 吉川 雅博 フリーアナウンサー 岡 知沙登
問題なく動作します!まあNode.jsなんで違いは無いはずですけどね。
うまくいったようです! これで快適なAmazonPrimeの特撮ライフがおくれそうです。