##何がやりたかったか?
お付き合いのあるとある公共施設のブログというかWeb日記というかをスクレイピングしてきたものを、RESTでロボットから呼び出してお話させてみたく、とりあえずJSONでスクレイピングしてきた内容を返すだけの簡易サービスを作って置きたかった。
RSSやらAtomやらのフィードがあれば、それを使えばよいのだろうけど、いかんせんそれがなかったので、なんとかしようとしたというのが前提になっている。
##簡単にJSONを返すだけのサービスをTornadoで作る
ということで、Tornadoを使ってスクレイピング結果をGetで、かつ、JSONで返せるようにしようと考えた。作成に使った環境は以下の通り。
- OS:Ubuntu15.10
- Python:3.5.1
- Tornado:4.3
- Tornado-JSON:1.2.2
Tornadoを使った簡易なWeb API作成で、JSONを返すための方法はいくつかあると思うが、今回はTornado-JSONを利用した。Tornado-JSONのsampleやtutorialを参考にすれば、そんなに迷わないはず。
###まずはTornadoでのWebアプリケーション作成と同様
以下のような感じで、WebアプリケーションとしてURLで呼び出せるようにするための部分を書く。
import tornado.ioloop
from tornado_json.routes import get_routes
from tornado_json.application import Application
def main():
import diarytalker
routes = get_routes(diarytalker)
application = Application(routes=routes, settings={})
application.listen(8888)
tornado.ioloop.IOLoop.instance().start()
if __name__ == '__main__':
main()
tornado_json.routesにより、この後記述するAPIのエンドポイント部分のパッケージ名、RequestHandlerから、自動でルートを特定してくれるので、自分でルートの記述を行う必要はない。インポートしているdiarytalkerがRequestHandlerが含まれるAPIの本体。
###RequestHandlerを含んだAPI本体のパッケージ
以下のようなディレクトリ構成で作っていく。
ーdiary_talker.py
|
|
ーdiarytalker/
|
|ー__init__.py
|ーapi.py
|ーdiary.py
インポートされるdiarytalker下で、API本体の実装はapi.pyに記載している。diary.pyはスクレイピングの実装だた、今回の本題とは外れるので、割愛。とにかくWebアクセスしてBeautifulSoup4などを駆使して日記をスクレイピングし、日付、タイトル、本文をdictionary化して返すメソッドが定義されている。
from tornado_json.requesthandlers import APIHandler
from tornado_json import schema
import diary
class DiaryTalkerHandler(APIHandler):
@schema.validate(
output_schema={
"type": "object",
"properties": {
"date": {"type": "string"},
"title": {"type": "string"},
"body": {"type": "string"}
}
}
)
def get(self):
td = diary.Diary()
diary = td.get_newest_diary()
return {
"date": "{}".format(diary["date"]),
"title": "{}".format(diary["title"]),
"body": "{}".format(diary["body"])
}
api.pyのgetメソッドでは、スクレイピングを行っているDiaryのget_newest_diaryメソッドを呼び出し、結果の入ったdictionaryから、schemaにより定義したJSONを返す実装になっている。日記の本体(日付、タイトル、本文)はschema定義のPropertiesでそれぞれ型とともに指定している。
###実際に呼び出すときは
http://〜/api/diarytalkerで呼び出せる。結果は
{"data":{
"date":"20160323",
"title":"hoge",
"body":"〜"
},
"status": "success"
}
のような感じに返ってくる。