mechanizeはWeb上の操作を自動化してくれる便利なPythonのライブラリ。Pure Pythonなのでいろんなところで動くよ。PerlのWWW::Mechanizeにinspireされて作られた。RubyにもMechanizeという同種のライブラリがある。Perl偉い!
「Web上の操作を自動化する」っていうのは,例えばどこかのサービスにログインしてあれこれするとか,そういったことをプログラマブルに行える,ということ。フォームの操作などもオブジェクトを使って実行できるのでとても手軽。Webアプリの開発などではテストに使われたりするんだけど,結局僕がなにをしたかったかというと,朝嫁が出かける準備をしている間にtumblrでqueueした尻画像とか尻画像,あと尻画像なんかを自動的にpostして欲しいってことです。tumblrのqueue,たまに動かなくなるんです。最初はtumblr APIを使ってやろうかと思ったけど,queueの部分がよく動かないのです。
ふにゃふにゃ,って感じで30分くらいでスクリプトを書いてみました。このスクリプトを定期的に動かせば,tumblrのqueueが美味く動かない時にだけ,スクリプトが自動的にqueueに貯めた投稿をpostしてくれる。グレイト。Cookie Jarと組み合わせると,認証時に発行されるセッション用クッキーなんかも自動的に保存してくれるので超便利。
#!/usr/bin/env python
import mechanize
import cookielib
import re
import time
def make_browser():
"""
A function to make browser object.
"""
brwser = mechanize.Browser()
# Making Cookie Jar and bind it to browser
cj = cookielib.LWPCookieJar()
browser.set_cookiejar(cj)
# Setting browser options
browser.set_handle_equiv(True)
browser.set_handle_redirect(True)
browser.set_handle_referer(True)
browser.set_handle_robots(False)
browser.set_handle_refresh(mechanize._http.HTTPRefreshProcessor(),
max_time=1)
browser.addheaders = [('User-agent',
('Mozilla/5.0 (Windows; U; Windows NT 5.1; rv:1.7.3)'
' Gecko/20041001 Firefox/0.10.1'))]
return browser
def time2minutes(s):
"""
A function to obtain minutes of the day from given string.
"""
hstr, rest = s.split(':')
h = int(hstr)
m = int(re.sub(r'am|pm', '', rest))
if rest.endswith('pm'): h += 12;
return h*60+m
if __name__ = '__main__':
browser = make_browser()
browser.open('https://www.tumblr.com/login')
browser.select_form(nr=0)
# Login
browser.form['user[email]'] = '***************'
browser.form['user[password]'] = '*************'
browser.submit()
# Go to queue
browser.open('http://tumblr.com/queue')
body = browser.response().read()
# Getting a part containing time to be published
ptpart = re.findall(r"""var publish_on_times = \[(.+?)];""",
body, re.M | re.S)
ptpart = ''.join(ptpart)
pubtimes = re.findall(r""".+?'(.+?)'.+?'(.+?)'""", ptpart, re.M | re.S)
now = time2minutes(time.strftime('%H:%M', time.localtime(time.time())))
for cnt, (wd, pt) in enumerate(pubtimes):
pm = time2minutes(pt)
if pm < now:
try:
browser.select_form(nr=2+cnt*2)
browser.submit()
except:
pass