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


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

テンプレ
------

~~~coffeescript
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
--------
http://developer.yahoo.co.jp/webapi/news/news/v2/topics.html

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

~~~coffeescript
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で調べてみて。

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

通信します。

~~~coffeescript


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で遊べますよ！

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

~~~coffeescript
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とコレクションネームが一緒でややこしい、ごめん
無事に保存できました。

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


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

http://qiita.com/yoneken/items/720027c648002cbf36ff

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

~~~coffeescript

# マーケットの最新情報を得るスクレイピング
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でいいやん！



~~~coffeescript
# 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探しの旅の記録でした。