2008/04/24

Recent entries from same category

  1. Google App EngineでZIPファイル内に存在するファイルに対してリクエストハンドラ制御が出来る様になった Hatena
  2. Growl for Windowsで日本語が表示出来た Hatena
  3. Google App Engine Oilが素晴らしい Hatena
  4. Google App Engineで作れるアプリ数が3個から10個に増えた Hatena
  5. ゆの in Python Hatena

はてな
こんなのあるんだ...
freshmeat.net: Project details for pytumblr - ロックスターになりたい
pytumblr is a Python library for the tumblr.com API. freshmeat.net: Project details for pytumblr
Google App Engine そう言えば前に「Windowsのエクスプローラで「送る」からShareOnTumblr」なんてのも作ったなぁ。 pythonで作ってあってlinuxなんかでも動くように作ったはず。

でpytumblrですが、ソース見たら簡単なソースだったのでGoogle App Engineで動くように改造してみました。以下パッチ
--- pytumblr.py.orig    Thu Apr 24 03:15:26 2008
+++ pytumblr.py Thu Apr 24 12:02:32 2008
@@ -1,7 +1,9 @@
 #!/usr/bin/env python
+#!-*- coding:utf-8 -*-
 
-import string, httplib, urllib2, urllib
-from xml.dom import minidom
+import urllib2, urllib
+from google.appengine.api import urlfetch
+from BeautifulSoup import BeautifulSoup
 
 class pytumblr(object):
    """Tumblr API Object.
@@ -75,14 +77,11 @@
 
        data = urllib.urlencode(values)
        headers = {"Content-type": "application/x-www-form-urlencoded"}
-       conn = httplib.HTTPConnection(self.url)
-       conn.follow_all_redirects = True
-       conn.request("POST",'/api/write', data, headers)
-       response = conn.getresponse()
-       if ( int(response.status) == 201):
+       response = urlfetch.fetch("http://%s/api/write" % self.url, headers=headers, method='POST', payload=data)
+       if ( int(response.status_code) == 201):
            return 'Success'
-       elif( int(response.status) != 201):
-           raise 'Error - Status %s (%s) returned' %(response.status, response.reason)
+       elif( int(response.status_code) != 201):
+           raise 'Error - Status %s (%s) returned' %(response.status_code, 'something wrong')
 
    def auth(self):
        values = {
@@ -92,13 +91,10 @@
            }
        data = urllib.urlencode(values)
        headers = {"Content-type": "application/x-www-form-urlencoded"}
-       conn = httplib.HTTPConnection(self.url)
-       conn.follow_all_redirects = True
-       conn.request("POST", '/api/write', data, headers)
-       response = conn.getresponse()
-       if ( int(response.status) != 200 ):
-           return '< There was a tiny problem: %s (%s) >' %(response.status, response.reason)
-       if ( int(response.status) == 200 ):
+       response = urlfetch.fetch("http://%s/api/write" % self.url, headers=headers, method='POST', payload=data)
+       if ( int(response.status_code) != 200 ):
+           return '< There was a tiny problem: %s (%s) >' %(response.status_code, 'something wrong')
+       if ( int(response.status_code) == 200 ):
            return '< Authenticated! >'
    
 
@@ -112,25 +108,8 @@
            opts = opts + "?type=" + type
        if ( id != 'None' ):
            opts = opts + "?id=" + id
-       return urllib.urlopen('http://%s.tumblr.com/api/read%s' %(self.user, opts)).read()
+       return urlfetch.fetch('http://%s.tumblr.com/api/read%s' %(self.user, opts)).content
        
    def getblog(self):
-       rxml = minidom.parseString(self.blogread())
-       titles = rxml.getElementsByTagName('regular-title')
-       postid = rxml.getElementsByTagName('post')
-       i = 0
-       n = 0
-       posts = {}
-       while ( i < len(postid)):
-           if ( postid[i].attributes['type'].value == 'regular' ):
-               t = titles [n]
-               t = t.toxml()
-               t = t.replace('<regular-title)', '')
-               t = t.replace('</regular-title)', '')
-               poid = postid[i].attributes["id"].value
-               posts[ poid ] = t
-               n = n + 1
-           if ( postid[i].attributes['type'].value != 'regular' ):
-               pass
-           i = i + 1
-       return posts
+       soap = BeautifulSoup(self.blogread())
+       return soap('post')
思いっきり弄ってますね。。。
minidomの代わりにBeautifulSoupを、urllib2の代わりにurlfetchを使っています。したがってgetblogは自分のregular情報のdictだけを返すのではなくBeautifulSoupを使ってlink、photo、quoteを返す様にしてあります。
実際に動くよって所は以下のサイトで確認して下さい。
pytumblr
このサイトのURLの後ろに
http://mattn.appspot.com/tumblr/mattn
と言った感じにtumblrアカウント名を付けてみて下さい。
今回のデモにはweb.pyというフレームワークを使用してみました。
以下スクリプトソースです。
#!-*- coding:utf-8 -*-
import web
from pytumblr import pytumblr
from BeautifulSoup import BeautifulSoup

def unescape(str):
  return  BeautifulSoup(str, convertEntities=BeautifulSoup.HTML_ENTITIES).contents[0].encode('utf-8', 'replace')

urls = (
  '/tumblr/(.*)', 'tumblr'
)
render = web.template.render('templates/')

class tumblr:
  def GET(self, name):
    web.header("Content-Type", "text/html; charset=utf-8")
    template_values = { 'name': '', 'posts': [] }
    name = name.replace('/', '')
    if name:
      pt = pytumblr(name, None, None)
      template_values['name'] = name
      for blog in pt.getblog():
        if blog['type'] == 'link':
          template_values['posts'].append({
            'type': 'link',
            'text': unescape(blog('link-text')[0].string),
            'desc': blog('link-description') and unescape(blog('link-description')[0].string) or '',
            'link': unescape(blog('link-url')[0].string),
          })
        if blog['type'] == 'photo':
          template_values['posts'].append({
            'type': 'photo',
            'text': unescape(blog('photo-caption')[0].string),
            'link': unescape(blog('photo-url')[0].string),
          })
        if blog['type'] == 'quote':
          template_values['posts'].append({
            'type': 'quote',
            'text': unescape(blog('quote-text')[0].string),
            'link': unescape(blog('quote-source')[0].string),
          })
    return render.tumblr(template_values)

if __name__ == "__main__":
  web.application(urls, globals()).cgirun()
案外短く書けますね。そしてテンプレートHTML
$def with (res)
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<link rel="stylesheet" href="/static/css/tumblr.css" type="text/css" />
$if res['name']:
    <title>pytumblr - $res['name']</title>
$else:
    <title>pytumblr</title>
</head>
<body>
$if res['name']:
    <h1>pytumblr - $res['name']</h1>
$else:
    <h1>pytumblr</h1>
    <img src="http://b.hatena.ne.jp/entry/image/http://mattn.appspot.com/tumblr/" title="はてなブックマーク" />
    <div id="content">
$if res['name']:
    <h2>$res['name']'s tumblr</h2>
    $for post in res['posts']:
        $if post['type'] == 'photo':
            <b>PHOTO:</b>$:post['text']<br />
            <blockquote><img src="$post['link']" /></blockquote>
        $elif post['type'] == 'link':
            <b>LINK:</b><a href="$post['link']">$:post['text']</a><br />
            <blockquote class="link">$:post['desc']</blockquote>
        $elif post['type'] == 'quote':
            <b>QUOTE:</b><br />
            <blockquote class="quote">
                $:post['text']<br />
                <cite>$:post['link']</cite>
            </blockquote>
    </div>
    <hr clear="all" />
    <p style="text-align: center">provided by <a href="http://mattn.kaoriya.net">mattn</a>, hosted on google app server.</p>
</body>
</html>
このweb.pyのテンプレートって癖があってpythonインデント方式なのですが、これってpreとかcodeで先頭が入っちゃったら不味いんじゃないかと思ったり...
解決方あるのか、調べてみます。pytumblrで面白いもの作ってみて下さい。

みんなのPython みんなのPython
柴田 淳
ソフトバンククリエイティブ / ¥ 2,940 (2006-08-22)
 
発送可能時間:通常24時間以内に発送


WriteBacks

TrackBack ping me at
Post a comment

writeback message: Ready to post a comment.