Twistedで作るローカルYoutubeサーバ その1
Youtubeネタ発展版。
せっかくなのでサーバも書いてしまおう。
Twistedはマルチサーバーを簡単に書く事ができる。
今回は
を書いてみる。
なんでsshかは秘密。
キモいサーバを書くからだよ。
DBを使わないだっさいサーバだけどね。
今回はtwisted.webではなくnevowを使用。
更にAxiomを使った発展系はあとでかくかも。
まずはvideoのダウンロード部分を作る。
downloader.py
from twisted.web import client from twisted.web import error from twisted.internet import reactor import os.path import re import web const_video_url_params_re = re.compile(r'player2\.swf\?([^"]+)"', re.M) const_video_url_real_str = 'http://www.youtube.com/get_video?%s' const_video_url_re = re.compile(r'^((?:http://)?(?:\w+\.)?youtube\.com/(?:v/|(?:watch(?:\.php)?)?\?(?:.+&)?v=))?([0-9A-Za-z_-]+)(?(1)[&/].*)?$') const_video_title_re = re.compile(r'<title>YouTube - ([^<]*)</title>', re.M | re.I) def _finish(data, id, title, file): print 'finish %s %s %s' % (title, id, file) v = web.VideoItem() v.title = title v.id = id v.file = file web.items.append(v) def _err(error): print error def downloadFlv(url, file): def _parseFlvUrl(data): match = const_video_url_params_re.search(data) param = match.group(1) url = const_video_url_real_str % param match_title = const_video_title_re.search(data) title = match_title.group(1) return (url, title) def _download(file, id): if os.path.isdir(file): file = os.path.join(file, '%s.flv' % id) def _downloadPage(data): url, title = data client.downloadPage(url, file).addCallback(_finish, id, title, file).addErrback(_err) return _downloadPage match = const_video_url_re.search(url) id = match.group(2) return client.getPage(url).addCallback(_parseFlvUrl).addCallback(_download(file, id)).addErrback(_err) def downloadAll(): print 'start' import setting while setting.video: url = setting.video.pop() downloadFlv(url, setting.repo)
downloader部分は以前のままだけどtitleとidも取るようする。
finishで値を保持しているオブジェクトはwebで参照するためのオブジェクト。
今回はあまり深く触れない。
setitngのvideoという名前のリストにダウンロードするvideoのURLを入れておくと実行時にdownloadAllに読み込まれる。
あとはdownloadAllをTimerServiceから呼び出すし、定期的にキューを監視する。
またファイルの保存先もsetting.pyの'repo'を参照しているので設定する必要がある。
repo = '/tmp' #video =['http://jp.youtube.com/watch?v=4-uxh1iQX0E'] video = []
TimerServiceへの登録は簡単こんな感じ。
from twisted.application.internet import TimerService from twisted.application import service, strports from nevow import static from nevow import appserver import setting import downloader import web import shell application = service.Application('youtube') timer = TimerService(60, downloader.downloadAll) timer.setServiceParent(application)
TimerServiceのコンストラクタに実行間隔(秒数)と関数を渡すだけ。
そしてサーバの親をsetParentでセットすると起動時に勝手にstartされる。
次はweb周りも絡めていく。
うくく。