Djangoで他のオブジェクトをそのまま保存したかった
経緯
スカンディナヴィア半島2(Twitter Web クライアント)を作るためにDjangoでTweepyからとってきたオブジェクトをそのまま保存したほうがいいと思った
tweetpy でとれたobjectをDjangoで保存したい→pickleしよう - Togetter
結論
無理だった。理由は2つ
- そもそもデータ量がデカすぎて現実的じゃない
- なぜかModelsに格納できないし、取り出せない
メモを箇条書きしたのでどうぞ
pickleについて
試算
- 1ユーザーが1日10000ツイート取得するのを1日分持つ
- 1オブジェクトが2575B程度
- zlib使っても1200B程度。まだでかい
- 25MB
- 100ユーザーで25000MB, 2.5TB
- 1オブジェクトが2575B程度
- 現実的じゃない
結論
必要なデータだけモデルにマッピングしたほうが現実的
簡単なpickleの使い方
import tweepy #seeはdirするよりわかりやすい便利パッケージ from see import see #パブリックTimeLineの取得 tm = tweepy.api.public_timeline() print tm[0] # <tweepy.models.Status at 0x2ccf5d0> import cPickle as pickle #シリアライズ dump = pickle.dumps(tm[0]) #ちゃんとシリアライズされました。これが2475文字程度ある print dump #'ccopy_reg\n_reconstructor\np0\n(ctweepy.models\nStatus\np1\nc__builtin__\nobject\np2\nNtp3\nRp4\n(dp5\nS\'favorited\'\np6\nI00\nsS\'contributors\'\np7\nNsS\'truncated\'\np8\nI00\nsS\'text\'\np9\nS"Today\'s Full Moon in your sign heightens your emotional sensit... More for Virgo http://t.co/hrG5PcAW"\np10\nsS\'source_url\'\np11\nS\'http://www.twittascope.com\'\np12\nsS\'in_reply_to_status_id\'\np13\nNsS\'user\'\np14\ng0\n(ctweepy.models\nUser\np15\ng2\nNtp16\nRp17\n(dp18\nS\'follow_request_sent\'\np19\nNsS\'profile_use_background_image\'\np20\nI01\nsS\'contributors_enabled\'\np21\nI00\nsS\'id\'\np22\nI278282775\nsS\'verified\'\np23\nI00\nsS\'profile_image_url_https\'\np24\nS\'https://si0.twimg.com/profile_images/1864096060/Snapshot_20120225_3_normal.JPG\'\np25\nsS\'profile_sidebar_fill_color\'\np26\nS\'E6F6F9\'\np27\nsS\'is_translator\'\np28\nI00\nsS\'profile_text_color\'\np29\nS\'333333\'\np30\nsS\'followers_count\'\np31\nI320\nsS\'profile_sidebar_border_color\'\np32\nS\'DBE9ED\'\np33\nsS\'location\'\np34\nS\'Bittersweet, Texas\'\np35\nsS\'default_profile_image\'\np36\nI00\nsS\'listed_count\'\np37\nI3\nsS\'utc_offset\'\np38\nI-28800\nsS\'statuses_count\'\np39\nI12091\nsS\'description\'\np40\nS" Everything sounds better when it\'s written out, but it\'s up to you to believe what you see. Remember seeing is believing. Follow me or Unfollow me!"\np41\nsS\'friends_count\'\np42\nI326\nsS\'profile_link_color\'\np43\nS\'db1154\'\np44\nsS\'profile_image_url\'\np45\nS\'http://a0.twimg.com/profile_images/1864096060/Snapshot_20120225_3_normal.JPG\'\np46\nsS\'notifications\'\np47\nNsS\'show_all_inline_media\'\np48\nI01\nsS\'geo_enabled\'\np49\nI01\nsS\'profile_background_color\'\np50\nS\'DBE9ED\'\np51\nsS\'id_str\'\np52\nS\'278282775\'\np53\nsS\'profile_background_image_url\'\np54\nS\'http://a0.twimg.com/profile_background_images/434604785/Snapshot_20120224_8.JPG\'\np55\nsS\'screen_name\'\np56\nS\'doLL_housE_lova\'\np57\nsS\'lang\'\np58\nS\'en\'\np59\nsS\'profile_background_tile\'\np60\nI01\nsS\'favourites_count\'\np61\nI30\nsS\'name\'\np62\nS\'FunSize_Tweeter :)\'\np63\nsS\'url\'\np64\nS\'http://www.facebook.com/dannielynn\'\np65\nsS\'created_at\'\np66\ncdatetime\ndatetime\np67\n(S\'\\x07\\xdb\\x04\\x07\\x00\\x031\\x00\\x00\\x00\'\np68\ntp69\nRp70\nsS\'profile_background_image_url_https\'\np71\nS\'https://si0.twimg.com/profile_background_images/434604785/Snapshot_20120224_8.JPG\'\np72\nsS\'time_zone\'\np73\nS\'Pacific Time (US & Canada)\'\np74\nsS\'protected\'\np75\nI00\nsS\'default_profile\'\np76\nI00\nsS\'following\'\np77\nI00\nsbsS\'geo\'\np78\nNsg22\nI177751129516544000\nsS\'possibly_sensitive\'\np79\nI00\nsS\'author\'\np80\ng17\nsg66\ng67\n(S\'\\x07\\xdc\\x03\\x08\\r*\\x1a\\x00\\x00\\x00\'\np81\ntp82\nRp83\nsS\'retweeted\'\np84\nI00\nsS\'coordinates\'\np85\nNsS\'in_reply_to_user_id_str\'\np86\nNsS\'source\'\np87\nS\'Twittascope\'\np88\nsS\'in_reply_to_status_id_str\'\np89\nNsS\'in_reply_to_screen_name\'\np90\nNsS\'in_reply_to_user_id\'\np91\nNsS\'place\'\np92\nNsS\'retweet_count\'\np93\nI0\nsg52\nS\'177751129516544000\'\np94\nsb.' #デシリアライズ load = pickle.loads(dump) #ちゃんとオブジェクトに復元されてる print load #<tweepy.models.Status at 0x2ccf5d0> see(load) # hash() repr() str() # .author .contributors .coordinates # .created_at .destroy() .favorite() # .favorited .geo .id # .id_str .in_reply_to_screen_name .in_reply_to_status_id # .in_reply_to_status_id_str .in_reply_to_user_id # .in_reply_to_user_id_str .parse() .parse_list() # .place .possibly_sensitive .retweet() # .retweet_count .retweeted .retweets() # .source .source_url .text # .truncated .user #もちろんプロパティにもアクセスできる print load.text # "Today's Full Moon in your sign heightens your emotional sensit... More for Virgo http://t.co/hrG5PcAW"
@tokibito さんのサンプル
https://gist.github.com/2000021
https://gist.github.com/2000026
ただDjangoのmodles.CharFiledや modles.TextFieldではつかえなかった
DBになぜか保存されるし取り出せるけど、中途半端にしか入らないし、なんかいろいろエラーがでる。原理的にはおかしいと思うんだけど、なぜだろう……
追記
@xxxx DBに保存できてないってのは、エラー内容を見てみないと正確なことは言えないけど、max_lengthの指定が小さいとかunicode/strの変換で失敗してるとかじゃないかな。
max_lengthの指定は3000とか5000とか10000とか試したのでそこで文字列が入りきらないということはない感じでした。ただ、たしかに文字列の変換あたりでコケてる感じはしていています。あとはmodels.CharField()とTextFiledってmodels.Model を継承しているクラスだから models.Fieldを継承すればいいのか?とか検証の余地はあります。
まあおれはどちらにしろ意義がなくなったから疲れたのだよ……
thx!!
@xxxx ++