MEGA の API を使ってCUI環境でファイルアップロード

前回の記事にも書いたように、ラズパイから MEGA にファイルをアップロードします。
ラズパイには特にディスプレイを接続していないため、CUIから操作する必要があります。
そのためのいい感じの Pythonライブラリがあったので、それを使ってみたお話。

僕の MEGA の用途は完全に写真のバックアップで、同期は行っていません。
月ごとにローカルのHDDの写真フォルダを一括でアップロードする(一方向)、という使い方です。


使用したライブラリ


今回使った MEGA の Pythonライブラリは github にあったこれ。
richardasaurus/mega.py

いきなりでかでかと「Deprecated」とあり、公式SDKの案内が書いてありますが、気にしない。
公式SDKはそのままでは Python で扱いづらそうでしたので。

使い方


というわけで mega.py の使い方。
といってもほぼ README そのままですが。

まずはログイン。
from mega import Mega
email = 'hoge@test.com'
password = 'password'
mega = Mega()
m = mega.login(email, password)


続いてアップロード対象のディレクトリが存在するか確認します。
dst_folder = "FOLDER_NAME"
folder = m.find(dst_folder)

ファイルやフォルダにかかわらず、対象のノードを取得したいときはこのようにm.find()を使うようです。
対象ノードが存在した場合、folder[0]にはノード名が、folder[1]にはそのノードの情報が返されます。


対象フォルダが存在した場合、すでにアップロード済みのファイルはアップロードする必要がありません。そこでまず対象フォルダ以下のファイル一覧を取得します。
def get_dst_filenames(folder_node_name):
all_mega_files = m.get_files()
dst_files = []
for v in all_mega_files:
if all_mega_files[v]['p'] == folder_node_name:
dst_files.append(all_mega_files[v]['a']['n'])
return dst_files

引数のfolder_node_nameにはさきほどのfolder[0]を渡してやります。
m.get_files()でMEGA上のすべてのファイルを取得し、その親ノードが対象フォルダのものを抽出しています。
リスト内包で書いても良かったんですが。
all_mega_files[v]['p']が親ノード名、all_mega_files[v]['a']['n']がファイル名を表します。


こちらは対象フォルダが存在しない場合。フォルダを作成します。
def create_folder(folder_name, parent_name):
parent = m.find(parent_name)
m.create_folder(folder_name, parent[0])
return m.find(folder_name)

どのフォルダの下に対象フォルダを作成するかを指定します。
再びm.find()で親フォルダのノードを取得。
m.create_folder()で、親フォルダの下に対象フォルダを作成しました。


アップロードしたいローカルのファイルを取得。
import os
src_folder = "/FOLDER/NAME/"
src_files = os.listdir(src_folder)
print 'number of files in local: %d' % len(src_files)
src_files = [v for v in src_files if v[0] != '.']


対象フォルダが存在した場合は、ローカルのファイルリストからMEGA上のファイルを除外します。
src_files = list(set(src_files)-set(dst_files))


あとはアップロードするだけ。
for v in src_files:
m.upload(src_folder + v, folder[0])

アップロードはm.upload()。第一引数にローカルのファイルパスを、第二引数に対象フォルダのノード名を渡します。


まとめ


上記をまとめたものが以下。
from mega import Mega
import os
import sys

email = 'hoge@test.com'
password = 'password'


def get_dst_filenames(folder_node_name):
all_mega_files = m.get_files()
dst_files = []
for v in all_mega_files:
if all_mega_files[v]['p'] == folder_node_name:
dst_files.append(all_mega_files[v]['a']['n'])
return dst_files


def create_folder(folder_name, parent_name):
parent = m.find(parent_name)
m.create_folder(folder_name, parent[0])
return m.find(folder_name)

if __name__ == '__main__':
if len(sys.argv) < 3:
print 'Usage: post_pictures.py '
print ' example: post_pictures.py /name/of/src/dir/ dst_dir'
exit()

mega = Mega()
m = mega.login(email, password)

src_folder = sys.argv[1]
dst_folder = sys.argv[2]

src_files = os.listdir(src_folder)
print 'number of files in local: %d' % len(src_files)
src_files = [v for v in src_files if v[0] != '.']

folder = m.find(dst_folder)
if folder:
dst_files = get_dst_filenames(folder[0])
print 'number of files in Mega: %d' % len(dst_files)
src_files = list(set(src_files)-set(dst_files))
else:
folder = create_folder(dst_folder, 'Pictures')
print 'created folder "%s"' % dst_folder

num = len(src_files)
print 'number of files to upload: %d' % num
err = 0
for i, v in enumerate(src_files):
try:
m.upload(src_folder + v, folder[0])
print '%d/%d (%d%%): uploaded %s' % (i+1, num, (i+1)*100/num, v)
except:
err += 1
print "error occurred: %s" % v

print "complete. total error: %d" % err


月ごとに写真ファイルを大量にアップロードするため、毎回かなりの時間がかかります。
これでラズパイにHDD挿しっぱなしにして放っておけばアップロードしてくれる!
いままではノートPCに挿して電源を切らないように小分けにしたりしてアップロードしていました。

それにしても、MEGAの転送速度もっと速くならないかなあ。
IT関連の関連記事

Posted on 2015/12/07 Mon. 12:45 [edit]

category: IT関連

tag: python  ラズパイ 

07

コメント

Comment
list

コメントの投稿

Secret

Comment
form