ふにゃるんv2

もとは、http://d.hatena.ne.jp/Wacky/

Xmarksに替わる、オレ専用のブックマークWebアプリを作る

要するに何をやりたかったかと言うと、↓こういう事です。

  1. パソコンで溜めたブックマークを、iPod touch(iPhoneじゃない所に哀愁を感じて!)でカウチポテトしながら見たい。
  2. ブックマーク同期として Xmarks を使ってみたが、一々ログインしなければならないし、階層を降りるのに時間が掛かるし、オフラインの時にリストも見られない(iPod touchの悲しさ)、後 ブックマークが昇順になっていないのも気に喰わない。
  3. 幾つかの非標準Web browserは、Webの保存機能を持っているようだから、自分でブックマークリストなHTMLを作って、それを保存して使いこなせば良いんじゃね?
  4. 更に調べていたら、HTML5のオフラインアプリケーション機能(mobile Safari実装済み)を使えば、HTMLをキャッシュしておいてオフラインでも使えるらしい。
  5. 早速、PythonでブックマークをHTML化して、オフラインでもリストが見られるように、ローカルWebアプリ化してみたよ。<今ココ

資料

今回、色々回り道を繰り返していましたが、参考にしたURLです。

@ITのこの記事で、「ローカルWebアプリ」が紹介されていたのですが、上の記事を読むまで 自分のやろうとしている事に転用できると、全然気づきませんでした。
(だって、その後のページで、ネイティブアプリの作成の話に行ってるんだもん)


次、ローカルWebアプリ化に際して、iPhone/iPod touchのユーザーインタフェースをWebで再現する為のライブラリ検討として、以下を参考にしました。


幾つかライブラリをダウンロードして、添付されていたデモを iPod touchで見て、今回は jQTouch にしました。

採用理由は、以下のものです。

  • 特にライブラリ本体を弄らなくても、iPhone/iPod touchのユーザーインタフェースになる。
  • 今回は階層を掘っていくイメージの為、1ファイルを複数ページに見せかける jQTouch が 動作が軽くなりそうだし、簡易だと思った。
  • サンプルコードが、結構判り易かった。

ソースコード

試行錯誤したままですが、ソースです。
整理もしていないので、かなり汚いです。すんません。
(しかも、デモコードから切り貼りをしていたりします)

#!/bin/env python
# -*- encoding: cp932 -*-
"""
    IEの「お気に入り」を、iPhone/iPod touch向けのHTMLに変換する。
    HTML化のベースは、jQTouch を使っている。
"""
import sys
import os
import csv
import pdb
import codecs
import ConfigParser
import time

def html_before(title):
    return """
<!doctype html>
<html manifest="fav.manifest">
    <head>
        <meta charset="UTF-8" />
        <title>%s</title>
        <style type="text/css" media="screen">@import "./jqtouch.min.css";</style>
        <style type="text/css" media="screen">@import "./theme.min.css";</style>
        <script src="./jquery.1.3.2.min.js" type="text/javascript" charset="utf-8"></script>
        <script src="./jqtouch.min.js" type="application/x-javascript" charset="utf-8"></script>
        <script src="./jqt.autotitles.js" type="application/x-javascript" charset="utf-8"></script>

        <script type="text/javascript" charset="utf-8">
            var jQT = new $.jQTouch({
                icon: 'jqtouch.png',
                addGlossToIcon: false,
                startupScreen: 'jqt_startup.png',
                statusBar: 'black',
                preloadImages: [
                    './img/back_button.png',
                    './img/back_button_clicked.png',
                    './img/button_clicked.png',
                    './img/grayButton.png',
                    './img/whiteButton.png',
                    './img/loading.gif'
                    ]
            });
        </script>
    </head>
    <body>""" % title

def html_after():
    return """
    </body>
</html>"""

def str_normal(s):
    if s.isalnum() == True:
        return s.replace(".", "_")
    else:
        ss = ""
        for c in s:
            ss += "%d" % ord(c)
        #print ss
        return ss

def get_ini_url(fpath):
    #print "ini file:%s" % fpath
    cfg = ConfigParser.ConfigParser()
    try:
        cfg.readfp(open(fpath))
        return cfg.get('InternetShortcut', 'URL')
    except:
        return "#"

def make_node(is_top, root, dirs, files):
    title = os.path.basename(root)
    
    back_node = ""
    if is_top == False: back_node = '<a href="#" class="back">back</a>'
    
    node = ""
    for s in dirs:
        node += "<li class='arrow'><a href='#%s'>%s</a><small class='counter'>%d</small></li>" % (str_normal(s), s, len(os.listdir(os.path.join(root, s))))
    node += "\n"
    for s in files:
        node += "<li class='forward'><a href='%s' target='_blank'>%s</a></li>" % (get_ini_url(os.path.join(root, s)), s.replace('.url', ''))
    html = """
<div id='%s'>
    <div class='toolbar'>
        %s
        <h1>%s</h1>
    </div>
    <ul class='rounded'>
    %s
    </ul>
</div>""" % (str_normal(title), back_node, title, node)
    return html

def make_manifest(dir):
    print >>f, "CACHE MANIFEST\n# %s\n" % time.asctime()
    print >>f, "CACHE:"
    for root, dirs, files in os.walk(dir):
        for s in files:
            ext = os.path.splitext(s)[1]
            if (ext == ".css") or (ext == ".js") or (ext == ".png") or (ext == ".gif"):
                fpath = os.path.join(root, s)
                print >>f, fpath.replace(dir, "").strip("\\").replace("\\", "/")

def main(f):
    fav_dir = r"C:\Documents and Settings\あなたの名前\Favorites"
    
    is_top = True
    html_body = ""
    for root, dirs, files in os.walk(fav_dir):
        #print root, dirs, files
        print ">", root
        html_body += make_node(is_top, root, dirs, files)
        is_top = False
    print >>f, html_body

if __name__ == "__main__":
    save_dir =  r"C:\配置したいフォルダパスを指定する"
    # 「お気に入り」から、HTMLページを生成(use jQtouch)
    save_path = os.path.join(save_dir, "_test.html")
    f = file(save_path, "w")
    print >>f, html_before("Favoraites List")
    main(f)
    print >>f, html_after()
    f.close()
    
    # fav.manifestを生成
    save_man = os.path.join(save_dir, "fav.manifest")
    f = file(save_man, "w")
    make_manifest(save_dir)
    f.close()
    
    # cp932からutf-8に変換
    save_path2 = os.path.join(save_dir, "index.html")
    f_i = file(save_path, "r")
    f_o = file(save_path2, "w")
    f_o.write(unicode(f_i.read(), "cp932").encode('utf-8'))
    f_i.close()
    f_o.close()

コードの流れとしては、大体以下の様です。

  1. お気に入りフォルダを os.walk で再起探索し、HTMLリスト化しています。
    サブフォルダ毎を1ページとして ulタグでくくり、後は .url ファイルの URLキー値を、liタグ内の aタグでジャンプ先になるようにしています。
    (jQTouchは、divタグでページを作り出している)
  2. ローカルWeb化する為に、jQTouch提供のライブラリ群を、fav.manifest ファイルで ローカルキャッシュ対象にしています。
    fav.manifestファイルは、htmlタグのmanifest属性キーでファイル指定できます。
  3. 1.でHTML化したファイルは、cp932(shift_jis)なので、utf-8に保存し直しています。
    (最初からutf-8でファイルを作ろうと思ったのですが、encodeメソッドを使うのが面倒になったので、後から変えてしまえ。と思った次第)

動かし方

1.パソコン内に、ローカルなWWWサーバーが走っている環境を構築します。
自分の環境は Apache ですが、最近なら WebMatrix でも良いかも知れません。


2.仮に、Apacheを動かしていたら、httpd.confに以下の行を追加します。

AddType text/cache-manifest .manifest


3.次に、ブックマークをHTML化したファイルを保存したいフォルダを決めます。
仮に、「c:\html\test」フォルダに配置すると仮定します。
上のソースの「save_dir」変数の値を、「c:\html\test」に設定してください。


4.jQTouchのライブラリをダウンロード(私のは、jqtouch-1.0-beta-2-r109.zip でした)して展開します。
で、jqtouchフォルダとthemes/jqtフォルダのファイルを、「c:\html\test」フォルダに ぶち込みます。


5.上のソースを Python で実行します。
すると、「c:\html\test」フォルダに、「index.html」ファイルが出来上がります。
(ChromeとかSafariなどのWebKit系ブラウザで、簡単な確認が出来ます)


6.作成したページのURLを、iPod touchから参照します。
例えば、↓こんな感じの画面になります。
fav_test
fav_test posted by (C)wacky


7.ローカルWeb化しているので、機内モード:ONにしてアクセスしても、「ページを開けません」と出ずに、ページが開きます。やったぁ。
(但し、ブックマークリスト先のURLを開こうとすると、当然ですが「ページが開けません」となります)

最後に

ローカルWebアプリって、結構簡単に作れるもんですね。
(.manifestファイルで、キャッシュ対象を指示すれば良いだけなんですもん)


Mac使いじゃない私には、iPhone/iPod touchなアプリは、永遠に作る事が出来ないのか。と半分諦めモードでしたが、少し元気が出てきました。


これなら、自分のPCのローカルWWWサーバーで、ちまちまWebアプリを作って、それをローカルWebアプリ化すれば良いのですから、かなり敷居が低くなった気がしてきました。
(しかも、ローカルWebアプリ化すれば、Wi-Fiの使えない所でも使えるし)