nodejsで最新ニュースをmongoDBに保存する他


論理構成とかなしただただメモですが読んで分かると思います。
データをテンプレートに投げれば、ニュースアプリとか作れます。

テンプレ

parseXML = require("xml2js").parseString
util = require "util"
http = require "http"
URL = require "URIjs"
mongoose = require "mongoose"
settings = require "./settings"
appId = 'XXXXXXXXXXXXXXXX'
log = (a) ->
    if arguments.length isnt 1
        return console.log arguments
    console.log util.inspect a,
        showHidden: false
        depth: 2
        color: true
    return a
  • xml2js:XMLをjsonに変える。超重要。
  • util:ログとれる、階層レベルを変えて目当てのデータを見つけるためにlog関数。
  • mongoose:データ保存、スキーマで必要なデータだけ取る。
  • settings:ホストとかポートとかの設定情報
  • appId: ヤフーのAPI使うための認証鍵。
  • URL:urlをjsonっぽく投げて作れる。url作るだけです。

yahooAPI

これを使ってみる。ほかに日本語解析とか、緯度経度で場所探しとかあるけど使い方は一緒。
リクエストパラメータに必要な情報を上ページから探してそれをもとにurlとクエリとデータの中身の表示を書く。

news =
    uri: 'http://news.yahooapis.jp/NewsWebService/V2/topics'
    data: # 後でクエリに使う
        appid: appId
        category: 'domestic'
        sort: 'pvindex'
        results: 10
    res: (data) -> data.ResultSet.Result

URL生成。使い方はnpmで調べてみて。

urler = new URL news.uri
urler.search news.data

通信します。



http.get urler.toString(), (res) ->
    body = ''
    res.setEncoding 'utf-8'
    res.on 'data', (chunk) ->
        body += chunk

    res.on 'end', (res) ->
        parseXML body,
            trim: true
            explicitArray: false
        , (err, data) ->
            if err then throw err
            log news.res data
.on 'error', (e) ->
    log e.message


APIってっこうやって使うんですかね。
これくらいならクライアントサイドだけで直接投げて済みそうですね。
一応APIの使い方でした。いろんなAPIで遊べますよ!

さて月5000回しか使えないらしいからDB保存しよう。log関数の代わりにデータベースに投げる、dbSave関数を作ります。

mongoose = require "mongoose"

mySchema = new mongoose.Schema
    NewsUpdateTime: String
    Keyword: String
    TopicName: String
    English: String
    Overview: String
    Category: String
    SubCategory: String
    Url: String
    PickupCategory: String
    PickupOrder: String
    PvIndex: String
    NewsNum: String
    NewsUrl: String
    SmartphoneUrl: String
mongoose.model 'yahoonews', mySchema
dbName = "yahoonews"

dbSave = (datas)  ->
    mongoose.connect "mongodb://" + settings.host + "/" + dbName
    News = mongoose.model "yahoonews"
    datas.forEach (data) ->
        news = new News data
        news.save()

databaseNameとコレクションネームが一緒でややこしい、ごめん
無事に保存できました。

しかし、、、
ここまで読んでくれて難だけど、10件しかとれないし、ニュースのURLはいってないし、なんだこのAPI?! ってなるんです。
なのに制限とか^^;

ニュースでもいいですけど、こんどは為替情報を保存してみようかな。さて

やってることは控えめなのに、げすいタイトルのページがあったのでまねてみます。yahooファイナンスさんのページからスクレイピングしてみます。アクセスは重いので練習しにくかったです。


# マーケットの最新情報を得るスクレイピング
jsdom = require "jsdom"
jsdom.env 'http://finance.yahoo.co.jp', ["http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"], (err, window) ->  window.$('.yjfinMarquee:first em').each () ->
        console.log window.$(this).children('a, strong').text()

スクレイピング自体はjqueryだけでconsole上でできます。
今回はサーバーにてhtmlをgetしてDOMに変えて、jqueryでさがしたら簡単になるわけなんですが。npmで検索した結果がこれ。
+ jsdom: htmlをDOMに変えてくれる
途中でjqueryを読みこむオプションがあって便利!
以上、上のqiitaページのnodejsばーじょんでした。

しかし得られる情報がしょぼい!

いまどきのRSSで制限もよわいのにめっちゃ情報のってますやん。XMLぱーさー使ってるんだったら最初からRSSでいいやん!

# RSSから最新のマーケット情報を得る。
urler = new URL 'http://jpy.jp.fx-exchange.com/rss.xml'

http.get urler.toString(), (res) ->
    body = ''
    res.setEncoding 'utf-8'
    res.on 'data', (chunk) ->
        body += chunk

    res.on 'end', (res) ->
        parseXML body,
            trim: true
            explicitArray: false
        , (err, data) ->
            if err then throw err
            log data.rss.channel.item

うわ、とれたわ。
わんちゃんマーケットアプリ作ってひと儲けできるんかな。

以上、API探しの旅の記録でした。