Help us understand the problem. What is going on with this article?

ツイートを長期間収集する実験(プログラム準備編(3))

More than 3 years have passed since last update.

前回まで

  • Twitterまわりは何となくそれっぽくなった、んじゃないかな?
  • じゃあ次はMongoDB。
    • 簡単なプログラムから始めよう

やらないといけないこと

 今回のプログラムにおけるMongoDBの側の最優先事項は「受信したデータのMongoDBへの格納」です。
 仕様を踏まえて言い換えると、「受信したデータは欠けなく保存し、3か月分ため込めること」になるでしょうか。

とりあえずありそうな事態を列挙してみる

 DBへの入力で、失敗する事態はどんなことがあるでしょうか?

  • DB・プログラム間の接続が切れて死亡
  • DBそのもののプログラムエラーで死亡
  • データの書式のエラーで取り込む前に死亡
  • 大量にデータが流れすぎて処理が追いつかなくなって死亡

 ぱっと思いついたのはこのくらいでしょうか(へっぽこなので専門的なあたりは勘弁)。
1. 接続が切れるほうは、Localhost間なのであんまり気にしなくて良い、んじゃないかな、たぶん。
2. DBそのものが落ちるほうは、何か別の対処手段を考えないといけないので今回パス。
3. 書式エラーは、加工ゼロでぶち込む以上、まがりなりにもTwitterから送られてくるデータなのだから、信用してよいよね、と思うんですが。
4. 処理が追いつかなくて死亡、怖い。

 流量的には大丈夫だと信じているのですが、比較的CPUもディスク速度も潤沢な開発機とは違い、実行環境はCeleron 2.41GHz、メモリは増強して8GBという環境(増強済み)。NASとしても利用するので環境としてはかなり厳しいんじゃないかなー、と思うわけです。

 先の実験をもとにして考えると1日当たり2GBは押し寄せる想定となっています。
 1時間平均に直すと33MB/hで、さらに最大ピーク時は倍、つまり66MB/hをさばく必要があります。

 ……ん?思ったよりも少ない?? またどこかで計算間違ってる??
 検算は後にするとして。わかりやすく数値を均すとして70MB/hと計算。Sqliteに保存したJSONデータの平均長さが7000byteなので、10,000ツイート/hということに。
 ……ホントか? どっかしらに穴がある気がしてならないのだけど……

とりあえずプログラムしてみる

 とりあえず検算とか置いておいて、PyMongo使ったプログラムを書いてみることに。

pymongotest1.py
#!/usr/bin/env python
# -*- coding:utf-8 -*-

from pymongo import MongoClient

Client = MongoClient()  # Localhost,既定ポートなら設定不要
db = Client.testdb      # DB名:testdb(自動で作成される)
Collection = db.testCollection    # コレクション(テーブル)名:testCollection

Collection.insert({"test": "てすと"})

 ……えっ、これでいいの?
 と思いつつ、pymongoをインストールしたうえで実行。結果もGUI上で見たいなーと思ったら、Robomongoというツールが。普通に使う分にはタダなので、さくっとインストール&実行。

実行結果

 登録したデータが入ってます。 "_id"ってのは自動で振られるみたいですね。
次は複数登録してみるか……

for i in range(0, 10):
    Collection.insert({"test": "てすと"})

 登録できました。想像以上に楽です。
 次はTwitterのツイートJSONを入れてみます。元データは初回のチェック時にSQLiteに格納していたツイートを適当にピックアップ。

 Collection.insert({"created_at":"Sat Sep 24 15:35:21 +0000 2016", ...(長いので略)... })
NameError: name 'false' is not defined

 なんかエラーが出ました。 素のままで読むと、falseは未定義……という意味になるんですが、なんじゃそりゃ。生JSONのはずなんですが。
 ググってみたら同じことで悩んでる人が即見つかりました

import json

#(略)

raw_string = r'''{"created_at":"Sat Sep 24 15:35:21 +0000 2016", ...(長いので略)... }'''
json_object = json.loads(raw_string)
Collection.insert(json_object)

 こんな感じにすればよいとな。なるほど、登録できます。
 じゃあ次は複数。

raw_string = r'''{"created_at":"Sat Sep 24 15:35:21 +0000 2016", ...(長いので略)... }'''
json_object = json.loads(raw_string)

for i in range(0, 10):
    Collection.insert(json_object)

 エラーになりました。「pymongo.errors.DuplicateKeyError: E11000 duplicate key error collection:」だそうなので、全く同じものを連打でぶち込むことはできない、ということでしょうか。

for i in range(0, 10):
    raw_string = r'''{"created_at":"Sat Sep 24 15:35:21 +0000 2016", ...(長いので略)... }'''
    json_object = json.loads(raw_string)

    Collection.insert(json_object)

 こんな風にやったらうまくいきました。json.loads()の段階でidが振られている、という感じ……なんだと思う。

速度計測

 では、実際どの程度の速度が出るか試してみます。
速度チェックのコードは以下の通り。

MongoSpeed.py
#!/usr/bin/env python
# -*- coding:utf-8 -*-

from pymongo import MongoClient
import json

import time    # 時間計測

Client = MongoClient()
db = Client.testdb
Collection = db.testCollection

start = time.time()   # 計測開始
for i in range(0, 10000):    # 10,000回ループ
    aw_string = r'''{"created_at":"Sat Sep 24 15:35:21 +0000 2016", ...(長いので略)... }'''
    json_object = json.loads(raw_string)
    Collection.insert(json_object)

elapsed_time = time.time() - start   # 計測終了、開始時を引いて経過時間計算
print('実行時間:', elapsed_time * 1000 ,' [ms]')

 JSONデータは10KB程度のちょっと長めのもの。画像URLが4つ分、ハッシュタグなども入ったものです。
 前回取得したデータで一番大きかったのが25KB、小さいほうでは2KB。平均7KBからするとちょっと大きい?位のデータ。
 つまりこれの実行時間が1時間以内なら、だいたい問題ない。

(Python) >Python .\MongoSpeed.py
実行時間: 11719.62308883667  [ms]

(Python) >

 は?
(つづく。)

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away