やりたいこと
タイトルのそのまま。
コンフィグファイル(yaml)使ったりログも書いたりしているから忘れないようにメモ。
ソースコード
使ったライブラリはこんな感じ。
- cheerio : 食べログAPI のレスポンスがxmlだからそれを解析する用
- request : 食べログAPI にリクエストを送ってレスポンスを取得する用
- yaml : YAML形式のコンフィグファイルを解析する用
- fs : ファイルシステムからコンフィグファイルを取得する用
- commander : コマンドラインオプションを解析する用
- mongoose : mongoDBを扱う用
- log4js : ログを書き込んだりするため用
#!/usr/bin/env node
/**
* @description
* Get restaurant data from tabelog api and insert data to event.
* @author hyde <zuqqhi2 at gmail.com>
*/
//===============================================
// Load Libraries
var cheerio = require("cheerio");
var request = require("request");
var yaml = require("yaml");
var fs = require("fs");
var command = require("commander");
var mongoose = require("mongoose");
var log4js = require('log4js');
//===============================================
// Logging Setting
log4js.configure({
appenders: [{
"type": "dateFile",
"filename": "./logs/insert_tabelog_datas.log",
"pattern": "-yyyy-MM-dd"
}]
});
var logger = log4js.getLogger("dateFile");
//===============================================
// Load config file
var configData = fs.readFileSync("./config/config.yml","utf8");
var config = yaml.eval(configData);
//===============================================
// Make request URL
var requestBaseUrl = config.tabelog_api.base_url;
var apiKey = config.tabelog_api.api_key;
// paramter
// parse command options and create help command automatically
command
.version('1.0.0')
.usage('[option]')
.option('-p, --prefecture <String>', 'prefecture name (default japan)')
.option('-n, --pagenum <n>', 'page number (max 60)', parseInt)
.parse(process.argv);
var pageNumber = 1;
var prefecture = "japan";
if (command.prefecture) prefecture = command.prefecture;
if (command.pagenum) pageNumber = command.pagenum;
var queryParams = new Array();
queryParams.push("Prefecture=" + prefecture);
queryParams.push("PageNum=" + pageNumber);
queryParams.push("ResultSet=large");
queryParams.push("Key=" + apiKey);
// join
var requestUrl = requestBaseUrl + "?" + queryParams.join("&");
//===============================================
// DB setting
var db = mongoose.connect('mongodb://' + config.event_db.host + '/' + config.event_db.event_data,
function (err) {
if (err) {
logger.error("Connection Fail. mongodb://" + config.event_db.host + "/" + config.event_db.event_data);
} else {
logger.info("Connection Success!");
}
}
);
var EventsSchema = new mongoose.Schema({
event_id : { type: Number, default: 0 },
genre_id : Number,
title : String,
image : String,
description : String,
url : String,
station : String,
address : String,
business_hour: String,
holiday : String,
latitude : Number,
longitude : Number,
created_time : { type: Date, default: Date.now },
update_time : { type: Date, default: Date.now }
});
EventsSchema.pre('save', function(next) {
if(!this.isNew) return next();
var model = this;
model.db.db.executeDbCommand({
findAndModify: 'current_event_id', // 'コマンド名': '対象のコレクション名'
query: { name: model.collection.name }, // 検索オプション
update: { $set: { name: model.collection.name }, $inc: { sequence: 1 } },
new: true, // 更新したデータを受け取るかどうか
upsert: true // 見つからなかったら挿入するかどうか
}, function(err, data) {
if(!err && data.documents[0].ok) {
// model.id に取得した値をセット
model.event_id = data.documents[0].value.sequence;
next();
} else {
next(err || new Error(data.documents[0].errmsg));
}
});
});
var Events = db.model("events_tests", EventsSchema);
//===============================================
// Analyze response
logger.info("request url: " + requestUrl);
request({url: requestUrl}, function(error, response, body)
{
if (!error && response.statusCode == 200) {
logger.info("response statusCode : " + response.statusCode);
$ = cheerio.load(body, {ignoreWhitespace: true, xmlMode: true});
var url = response.request.href;
var latest_id = 0;
$("Item").each(function(i, xmlItem) {
var data = {};
data["genre_id"] = 1;
data["title"] = $(xmlItem).children()[1]["children"][0]["data"];
data["image"] = "";
data["description"] = "";
data["url"] = $(xmlItem).children()[2]["children"][0]["data"];
data["station"] = $(xmlItem).children()[12]["children"][0]["data"];
data["address"] = $(xmlItem).children()[13]["children"][0]["data"];
data["business_hour"] = $(xmlItem).children()[15]["children"][0]["data"];
data["holiday"] = $(xmlItem).children()[16]["children"][0]["data"];
data["latitude"] = parseFloat($(xmlItem).children()[17]["children"][0]["data"]);
data["longitude"] = parseFloat($(xmlItem).children()[18]["children"][0]["data"]);
logger.info("Retrieve data: " + i);
logger.info(data);
var newPost = new Events(data);
newPost.save(function(err) {
if (err) {
logger.error("insert error : " + data);
}
});
});
} else {
logger.error("response statusCode : " + response.statusCode);
}
});
tabelog_api:
api_key: "<This is your application key for TabelogAPI>"
base_url: "http://api.tabelog.com/Ver2.1/RestaurantSearch/"
event_db:
host: "localhost"
event_data: "event_data"
結果
> db.event_tests.find()
{ "event_id" : 5, "genre_id" : 1, "title" : "AFURI", "image" : "", "description" : "", "_id" : ObjectId("52108d02514162c71d000005"), "update_time" : ISODate("2013-08-18T08:59:46.757Z"), "created_time" : ISODate("2013-08-18T08:59:46.757Z"), "__v" : 0 }
{ "event_id" : 10, "genre_id" : 1, "title" : "bills 七里ガ浜", "image" : "", "description" : "", "_id" : ObjectId("52108d02514162c71d00000a"), "update_time" : ISODate("2013-08-18T08:59:46.760Z"), "created_time" : ISODate("2013-08-18T08:59:46.760Z"), "__v" : 0 }
{ "event_id" : 15, "genre_id" : 1, "title" : "銀座天龍", "image" : "", "description" : "", "_id" : ObjectId("52108d02514162c71d00000f"), "update_time" : ISODate("2013-08-18T08:59:46.762Z"), "created_time" : ISODate("2013-08-18T08:59:46.762Z"), "__v" : 0 }
{ "event_id" : 20, "genre_id" : 1, "title" : "吉村家", "image" : "", "description" : "", "_id" : ObjectId("52108d02514162c71d000014"), "update_time" : ISODate("2013-08-18T08:59:46.765Z"), "created_time" : ISODate("2013-08-18T08:59:46.765Z"), "__v" : 0 }
{ "event_id" : 4, "genre_id" : 1, "title" : "うどん 丸香", "image" : "", "description" : "", "_id" : ObjectId("52108d02514162c71d000004"), "update_time" : ISODate("2013-08-18T08:59:46.757Z"), "created_time" : ISODate("2013-08-18T08:59:46.757Z"), "__v" : 0 }
{ "event_id" : 9, "genre_id" : 1, "title" : "モンシェール 堂島本店", "image" : "", "description" : "", "_id" : ObjectId("52108d02514162c71d000009"), "update_time" : ISODate("2013-08-18T08:59:46.759Z"), "created_time" : ISODate("2013-08-18T08:59:46.759Z"), "__v" : 0 }
{ "event_id" : 14, "genre_id" : 1, "title" : "アテスウェイ", "image" : "", "description" : "", "_id" : ObjectId("52108d02514162c71d00000e"), "update_time" : ISODate("2013-08-18T08:59:46.761Z"), "created_time" : ISODate("2013-08-18T08:59:46.761Z"), "__v" : 0 }
{ "event_id" : 19, "genre_id" : 1, "title" : "麺屋海神", "image" : "", "description" : "", "_id" : ObjectId("52108d02514162c71d000013"), "update_time" : ISODate("2013-08-18T08:59:46.764Z"), "created_time" : ISODate("2013-08-18T08:59:46.764Z"), "__v" : 0 }
{ "event_id" : 3, "genre_id" : 1, "title" : "風雲児", "image" : "", "description" : "", "_id" : ObjectId("52108d02514162c71d000003"), "update_time" : ISODate("2013-08-18T08:59:46.757Z"), "created_time" : ISODate("2013-08-18T08:59:46.756Z"), "__v" : 0 }
{ "event_id" : 8, "genre_id" : 1, "title" : "あつた蓬莱軒 本店", "image" : "", "description" : "", "_id" : ObjectId("52108d02514162c71d000008"), "update_time" : ISODate("2013-08-18T08:59:46.759Z"), "created_time" : ISODate("2013-08-18T08:59:46.759Z"), "__v" : 0 }
{ "event_id" : 13, "genre_id" : 1, "title" : "ピッツエリア エ トラットリア ダ イーサ", "image" : "", "description" : "", "_id" : ObjectId("52108d02514162c71d00000d"), "update_time" : ISODate("2013-08-18T08:59:46.761Z"), "created_time" : ISODate("2013-08-18T08:59:46.761Z"), "__v" : 0 }
{ "event_id" : 18, "genre_id" : 1, "title" : "梅田はがくれ 本店", "image" : "", "description" : "", "_id" : ObjectId("52108d02514162c71d000012"), "update_time" : ISODate("2013-08-18T08:59:46.763Z"), "created_time" : ISODate("2013-08-18T08:59:46.763Z"), "__v" : 0 }
{ "event_id" : 2, "genre_id" : 1, "title" : "ミート矢澤", "image" : "", "description" : "", "_id" : ObjectId("52108d02514162c71d000002"), "update_time" : ISODate("2013-08-18T08:59:46.756Z"), "created_time" : ISODate("2013-08-18T08:59:46.756Z"), "__v" : 0 }
{ "event_id" : 7, "genre_id" : 1, "title" : "イデミ・スギノ", "image" : "", "description" : "", "_id" : ObjectId("52108d02514162c71d000007"), "update_time" : ISODate("2013-08-18T08:59:46.758Z"), "created_time" : ISODate("2013-08-18T08:59:46.758Z"), "__v" : 0 }
{ "event_id" : 12, "genre_id" : 1, "title" : "出町ふたば", "image" : "", "description" : "", "_id" : ObjectId("52108d02514162c71d00000c"), "update_time" : ISODate("2013-08-18T08:59:46.761Z"), "created_time" : ISODate("2013-08-18T08:59:46.761Z"), "__v" : 0 }
{ "event_id" : 17, "genre_id" : 1, "title" : "たいめいけん", "image" : "", "description" : "", "_id" : ObjectId("52108d02514162c71d000011"), "update_time" : ISODate("2013-08-18T08:59:46.763Z"), "created_time" : ISODate("2013-08-18T08:59:46.763Z"), "__v" : 0 }
{ "event_id" : 1, "genre_id" : 1, "title" : "六厘舎TOKYO", "image" : "", "description" : "", "_id" : ObjectId("52108d02514162c71d000001"), "update_time" : ISODate("2013-08-18T08:59:46.753Z"), "created_time" : ISODate("2013-08-18T08:59:46.752Z"), "__v" : 0 }
{ "event_id" : 6, "genre_id" : 1, "title" : "エッグスンシングス 原宿店", "image" : "", "description" : "", "_id" : ObjectId("52108d02514162c71d000006"), "update_time" : ISODate("2013-08-18T08:59:46.758Z"), "created_time" : ISODate("2013-08-18T08:59:46.758Z"), "__v" : 0 }
{ "event_id" : 11, "genre_id" : 1, "title" : "うさぎや", "image" : "", "description" : "", "_id" : ObjectId("52108d02514162c71d00000b"), "update_time" : ISODate("2013-08-18T08:59:46.760Z"), "created_time" : ISODate("2013-08-18T08:59:46.760Z"), "__v" : 0 }
{ "event_id" : 16, "genre_id" : 1, "title" : "つるとんたん 六本木店", "image" : "", "description" : "", "_id" : ObjectId("52108d02514162c71d000010"), "update_time" : ISODate("2013-08-18T08:59:46.763Z"), "created_time" : ISODate("2013-08-18T08:59:46.763Z"), "__v" : 0 }