やりたいこと
楽天証券の投資信託の各商品ページから基準価額や純資産といった情報を取得して何らかのテキストファイルに出力する。という方法を自分で試してみる。
[例]https://www.rakuten-sec.co.jp/web/fund/detail/?ID=JP90C0009VE0
※ただし必要以上にサイトにアクセスしないこと、私用目的以外に使用しないことを心がけましょう。
使用した言語 > Node.js
Node.jsを使用したスクレイピングということで「cheerio-httpcli」を使用。
参考にしたサイトは↓こちらです。
[Node.jsのスクレイピングモジュール「cheerio-httpcli」が大規模アップデートして帰ってきた]http://qiita.com/ktty1220/items/64168e8d416d6d8ffb45
大まかな流れ
1.アクセスしたいURLを記述したファイルを外部モジュールとして用意しておく。
(単純なテキストファイルでも別に可)
exports.url1 = "https://www.rakuten-sec.co.jp/web/fund/detail/?ID=JP90C00080J9"
exports.url2 = "https://www.rakuten-sec.co.jp/web/fund/detail/?ID=JP90C0009VE0"
2.「cheerio-httpcli」のfetchメソッドを使用して必要なデータの抽出を行う。
実はここ嵌りました。実際のサイトのソースを見てもらうとわかるのですが、取りたい情報はこんな構造でした。
<table class="tbl-fund-summary">
<tbody>
<tr>
<th>基準価額</th>
<td class="br0"><span class="value-01">8,398</span> 円 (2/3)</td>
<td>
で、初めはこんな書き方をしていました。
for(var i=0; i < urllist.length; i++){
client.fetch(urllist[i], {}, function(err, $, res, body) {
var title = $("title").text();
// // ファンド情報
var target = $("table[class='tbl-fund-summary']");
// 基準価額
var baseCost = target.find("td[class='br0'] > span").eq(0).text();
(省略)
かなりはしょってますが、やろうとしたことは
・テキストファイルに書いたURLをリスト化して繰り返し処理の中でサイトにアクセスし、データを取得。いったん配列に追加して最後にテキストファイルに書き出す。
でした。
が、上記はうまくいきませんでした。まあfetchメソッドが非同期のメソッドだからでしょうね。
最後にファイルに書き出すタイミングではまったくデータがありませんでした。(null,nullとか)
なので、プロミス形式に方法を転換。こんな感じ。
var array = [];
// プロミスによる制御
client.fetch(exports.url1)
.then(function(result) {
var data = getFoundData(result);
array.push(data);
return client.fetch(exports.url2);
})
.then(function(result) {
var data = getFoundData(result);
array.push(data);
})
.catch(function(err) {
console.log(err);
})
.finally(function() {
fs.writeFile(exports.json, JSON.stringify(array, null, ' '));
});
getFoundDataはこんな感じ
function getFoundData(result) {
var $ = result.$;
var title = $(exports.titile).text();
// ファンド情報
var target = $(exports.foundtable);
// 基準価額
var baseCost = target.find(exports.foundbasedata).eq(0).text();
// 純資産額
var assets = target.find(exports.foundbasedata).eq(1).text();
// 直近分配金
var dividend = target.find(exports.foundbasedata).eq(2).text();
var data = {
"商品名": title,
"基準価額": baseCost,
"純資産額": assets,
"直近分配金": dividend
};
return data;
}
各商品のサイト構造はどれも同じなので現状、(2017/2/4)ごり押しで取得できる。
取得した結果を返却して配列にどんどん詰めていって、最後にJSONで書き出してる。
取得したいサイト(商品)が増えたら.thenをどんどんつなげればいいはず。
取り急ぎやったことの覚書でした。
感想
javascriptの知識もNode.jsの知識も全然ないので苦労した。C#ならもう少し楽に書けたとは思うけれど、どうしてもNode.jsを使ってやってみたかったのであえて不慣れな方を選んだのです。
ちなみにこの機能、実際に使うかいうとと使う予定はまったくない。普通に自分の口座にアクセスすれば必要な情報はとりあえず見れるので。