2010-09-25

Ruby で書いたフィルタを Python で書き直す #1

以前、「単純なフィルタをつなげて複雑なフィルタを実現する」で書いたプログラムを Python で書き直してみよう。

Ruby で書いたフィルタ

シンプルなパイプライン

このパイプラインを実現するために Ruby で書いたフィルタは以下の 4 つ。

  1. all (all_rss.rb)
  2. titles (titles_rss.rb)
  3. mklist (mklist.rb)
  4. mkhtml5 (mkhtml5.rb)

今回は、この内、titles_rss.rb を除く、3 つのフィルタを Python で書き直した。titles_rss.rb を除いたのは、このフィルタではフィードの XML データをパースする必要があるから。Python (2.5) の標準ライブラリにはフィードの XML を扱うライブラリが(RSS、Atom のどちらも)ふくまれていないから。外部のライブラリを使うにしろ、自前で簡単なパースをするにしろ、他のフィルタの書き直しよりは手間がかかるので後回しにした。

Python による実装

以下に示すコードを見ればわかるが、いずれも Ruby のコードとほぼ 1 対 1 で対応が付く。

フィードを取得する (all)
(all_atom.py)
 1: #!/usr/bin/python
 2: # -*- coding: utf-8 -*-
 3: # all_atom.py: get all feeds in the Atom format.
 4: 
 5: from sys import stdin, stdout
 6: import urllib
 7: import re
 8: 
 9: BLOGID = "put your blog id here"
10: FEEDURL = "http://www.blogger.com/feeds/%s/posts/default" % BLOGID
11: 
12: def get_atom(max_results):
13:     params = urllib.urlencode({'max-results': max_results})
14:     f = urllib.urlopen(FEEDURL + "?%s" % params)
15:     res = f.read()
16:     f.close()
17:     return res
18: 
19: # get meta information only
20: md = re.search('<openSearch:totalResults>(\d+)<\/openSearch:totalResults>', get_atom(0))
21: total_posts = int(md.group(1))
22: 
23: stdout.write(get_atom(total_posts) + '\n')
リスト形式に変える (mklist)
(mklist.py)
 1: #!/usr/bin/python
 2: # -*- coding: utf-8 -*-
 3: # mklist.py: make a HTML fragment contains an ordered list.
 4: 
 5: # SPECIFICATION:
 6: # input data must be written in the following format.
 7: # (<title> . <uri>)
 8: 
 9: from sys import stdin, stdout
10: import re
11: 
12: stdout.write('<ol>\n')
13: 
14: regex = re.compile('^\(\"(.*)\"\s.\s\"(.*)\"\)$')
15: for pair in stdin:
16:     md = regex.search(pair)
17:     if md:
18:         stdout.write("<li><a href='" + md.group(2) + "'>" + md.group(1) + "</a></li>\n")
19: 
20: stdout.write('</ol>\n')
HTML として出力する
(mkhtml5.py)
 1: #!/usr/bin/python
 2: # -*- coding: utf-8 -*-
 3: # mkhtml5.py: put input data into a well-formed HTML template.
 4: 
 5: from sys import stdin, stdout
 6: 
 7: stdout.write("""<!DOCTYPE HTML>
 8: <html lang='ja'>
 9: <head>
10: <meta content='text/html; charset=UTF-8' http-equiv='Content-Type'/>
11: <title>Blog Posts</title>
12: </head>
13: <body>
14: """)
15: 
16: for line in stdin:
17:     stdout.write(line)
18: 
19: stdout.write("</body></html>\n")

残るはフィードのパース

次回は、Atom 形式のフィードデータをパースし、記事のタイトルと URL を抽出する部分を書き直そう。実際のフィードデータを見てみると、単に rel 属性が alternate になっている link を抽出すればすみそうなんだが、いまやっていることは Python の練習でもあるんだから、もう少しまじめにパースするコードを書いてみるつもりだ。

関連リンク

関連記事

0 件のコメント:

コメントを投稿