« 2005年1月 | トップページ | 2005年3月 »

2005年2月の19件の記事

2005年2月28日

Contents☯2005年2月

続きを読む "Contents☯2005年2月" »

2005年2月27日

便所のラクガキとチラシの裏

先日のウェブログ虎の穴への感想トラックバックを貰ったのでちょっと書いてみます。とはいえその僕らの幼年期は今始まったばかりのサナギなんだ~ブログの可能性を検証するという記事での議論自体について言いたい事があるわけではなくて、

 一方において、楽天的ブログ論がある。ひとつのブログが主体的に一つの話題を展開していくと、トラックバック、コメントの形で第三者の意見がそこにからんできて、そのブログの書き手はそれらを弁証法的に止揚しつつ話をすすめてゆく、というものである。

ということ自体がつまらないな、という事ですが。

そういう事が欲しいのならばプロの編集者が識者を三人も集め鼎談させて記事にして本に載せる方が良いでしょう。少なくとも 開かれていながら、仕切りがしっかりしているブログ なんていう blog に求めるべきと思えないものを期待するよりも。

プロの編集者が企画しプロのライターが書きプロの営業がそれを的確に大衆にプレゼンし不特定多数に販売する、その方が妥当な事、というのは今後とも残る――というか竹熊氏の元の記事はそのためにいかに blog を用立てるか、という話ですし――でしょう。そういう事までプロフェッショナルでない人が書く blog に対して求めるのは期待する方が間違っているかと。

チラシの裏な blog や便所のラクガキな匿名BBSが、プロが金のために作るメディア(あるいはそれを前提の2次創作やアフィリエイト)の都合に回収されたり、あるいはそこまで行かなくてもプロだからこそ求められる水準を基準として良否を量られてしまう。(あるいはその反動としてのアマチュア・ボランティア主義に陥る)

蝶に育って羽ばたく事を自明の前提として幼年期のサナギと評されても、はなから地虫の育成環境にしか興味が無い立場から見ると「……そういう事に価値を置く人も居るんだね」としか。(いやそれはそれでいいのですが)

コンテストなりスカウトなりしてプロに回収してしまえるもの(評価基準)の予備層。blog に期待するものってそんな程度なのか? その部分で良いなら世間の認知に従ってこれからどんどん大きくなるでしょうね。(blog が本になりました。blog からプロライターにデビュー。絶版のあの本が blog で読めます。等々)

でもそんな従来のメディアの代替なんてどうでもいいと私には思えてしまいます。(そういうのならば既にあるわけですし)

消費者を前提としたライターという上下構造ではなく、参加それ自体のみがある BBS や blog や MMORPG といったメディア。それを批判するにしろ賞賛するにしろ、それは全く関係の無い価値基準に思えます。

2005年2月26日

トラックバックリンクを踏む人数

昨日の記事投稿から丸1日で95カウント。前回のアルティメットガールPython の投稿から丸1日だと46カウントくらい(前に計算した平均が44カウント/投稿)だったので、たけくまメモへトラックバックしたせいで倍くらいにアクセスが増えた勘定。もっとも前回のアルティメットガールと Python のネタでやって来た人が今回は居ないわけですから、その分を計算に入れるなら95カウント全てをたけくまメモのトラックバックリンクからの人数と見なしてもいいでしょうか。(ここを定期巡回している人も居ないでしょうし)

いずれにしろ1万ヒット/日の blog にトラックバックしてもそのリンクから流れて来るのは50~100人くらいという事ですね。

もっとも、1万ヒットと言っても blog のヒット数なんてのは本を買った人ではなく本の表紙を眺めた人の数に相当するものですから、実際に記事を読むのはその1割くらいのものでしょう。そして読んだ千人の内の1割の百人がトラックバックして来た先までを見るという事なら納得出来る数字です。

さて、知りたい事(素人 blog の見られる数、トラックバックリンクの踏まれる数)は分かったのでもうアクセスカウンタは外してもいいのですが……別に有って困る物でもないのでこのまま放っておきましょうか。

2005年2月25日

サルでもできるブログ教室:ウェブログ虎の穴 其の十四

竹熊氏の論点からはちょっとずれた話になってしまいますが一言。

どうしても紙の本に縛られてしまうのですね。オンライン出版も従来的な本の形式からキネティックノベルのようなアニメやマンガとの中間形態まで揃い普及期に入っていると思うのですが。

特に評論のような他の資料に言及する必要の多い文書の場合、文中の名称一つクリックするだけで同一文書中のものはもちろん Wikipedia のようなユーザー参加で書き換えられる百科事典のエントリーにまでリンク出来るようになると利点が多いでしょう。

weblog(というよりトラックバック)によってテキストへの被リンクをテキストそのものに取り込めるようになりました。ですから作品への批評や二次創作や感想へ作品そのものから逆リンクさせる事が可能。将来はそれら後付けの不特定な他者によるリンクも含めた全体が作品になるでしょう。もはや独立した批評や感想は存在せず作品への参加のみが存在する。キネティックノベルでプレイ直後にリンクの出る感想投稿やあるいは電車男などはそのような有り方になる未来のとば口でしょう。

演ずる(作品供給する)者だけではなくそれに感想を付け二次創作する側も含めたプロセス全てが作品になる。そうなれば紙に印刷した本などは単なる死体。いや本でなくDVDに焼いたとしても同じ事。それ以後にされたリンクは感知されないのですから。


とはいえ金になるのは本。あるいはそれにアフィリエイトしたり本の形で批評/二次創作を作り(同人)販売する者のみ。全国書店流通だろうがオンデマンドだろうが大前提として本位制。売れないという烙印を押されたライターや作家が、このシステムでどんどん本を出せる ようになったとしても作者様になれる下限が多少下がるというのみ。死体にしないと実にならない、そして屠殺した人だけが報酬を得られる、というヒエラルキーは変わらない。そうである以上共同創作ではなく本に出来るだけのステータスを獲得する神主(作家様)とそれにお布施する信者(消費者)の二項対立にしかなりえない。所詮そうでしかないなら「売れる作家だけ本を出してもらえる」今の事態の方がそのヒエラルキーがちゃんと絞られているだけ正しいでしょう。そもそもが(逆に言うなら)「売れない人は趣味で無料公開(あるいは赤字を出して同人出版)しましょうね」というシステムなのですから「売れない作家」までそのシステムでプロ側に回収しようとすればインフレをおこすだけなわけで……。

どうにかその成長発展し続けるオンライン作品全体への貢献に応じて報酬をシェアするシステムは出来ないものか。@nifty books で使っているようなアフィリエイトつまり物の宣伝を経由しての売り上げに応じた報酬であるかぎりは、スポンサーに支配されるTV番組と同じく出版流通者の都合に回収されてしまうと思いますし。(だからと言って原始共産制に留まっている限りはせいぜいが「良い趣味」にしかなり得ませんし……)

2005年2月22日

Python のリテラル形式を使って HTML を作る

世の中には HTML(XML) を作れる構造化書式が色々ありますがどれも大げさなツールを使い例外規則の山を築いたあげく HTML(XML) で出来るはずの表現を(普通に書ける範囲だと)制限している物が多い感じ。

でもよく考えたらプログラム言語(およびその構文エディター)なら元からデータ構造を記述出来、そしてエラーチェックまでしてくれるわけで。試しにちょっとしたツールを作ってみました。

まず以下のスクリプトを html.py という名前で保存してモジュールとしてください。

from xml.sax.saxutils import escape as _escape
INS, DEL = "ins", "del"
HEAD, BODY = "head", "body"
HTML = "html"
_BLOCK = ("p", "pre", "h1", "h2", "h3", "h4", "h5", "h6", "hr", "frameset",
          "frame", "noframes", "address", "blockquote", "style", "div",
          "center", "ul", "ol", "dl", "dir", "menu", "form", "fieldset",
          "table", "noscript")
(P, PRE, H1, H2, H3, H4, H5, H6, HR, FRAMESET,
 FRAME, NOFRAMES, ADDRESS, BLOCKQUOTE, STYLE, DIV,
 CENTER, UL, OL, DL, DIR, MENU, FORM, FIELDSET,
 TABLE, NOSCRIPT) = _BLOCK
_INLINE = ("a", "bdo", "iframe", "abbr", "acronym", "q", "cite", "em",
           "strong", "code", "dfn", "kbd", "samp", "var", "span", "font",
           "basefont", "big", "small", "b", "i", "s", "strike", "u", "tt",
           "sub", "sup", "form", "input", "button", "textarea", "select",
           "label", "isindex", "caption", "object", "applet", "script",
           "ruby", "rb", "rt", "rp", "br", "img")
(A, BDO, IFRAME, ABBR, ACRONYM, Q, CITE, EM,
 STRONG, CODE, DFN, KBD, SAMP, VAR, SPAN, FONT,
 BASEFONT, BIG, SMALL, B, I, S, STRIKE, U, TT,
 SUB, SUP, FORM, INPUT, BUTTON, TEXTAREA, SELECT,
 LABEL, ISINDEX, CAPTION, OBJECT, APPLET, SCRIPT,
 RUBY, RB, RT, RP, BR, IMG) = _INLINE
_INLINE += (INS, DEL)
_EMPTY = (BR, IMG, HR)
def ruby(base, ruby):
    return (RUBY, (RB, base), (RP, "("), (RT, ruby), (RP, ")"))
def to_html(data, inline=False):
    if isinstance(data, basestring):
        return _escape(unicode(data))
    tag = str(data[0])
    if tag in _INLINE: # ブロック要素としての ins, del が使えないバグ有り
        inline = True
        lb = ""
        if tag == BR:
            lb = "\n"
    else:
        if inline:
            raise "A block element is in an in line element: %s" % data
        lb = "\n"
    if len(data) > 1 and isinstance(data[1], dict):
        attr = " ".join([('%s="%s"' % (unicode(k), unicode(i)))
                         for (k, i) in data[1].items()])
        if tag in _EMPTY:
            if len(data) != 2:
                raise "There is too much data: %s" % data
            return "<%s %s />%s" % (tag, attr, lb)
        else:
            return "<%s %s>%s%s</%s>%s" % (tag, attr, lb, "".join([
                to_html(x, inline) for x in data[2:]]), tag, lb)
    else:
        if tag in _EMPTY:
            if len(data) != 1:
                raise "There is too much data: %s" % data
            return "<%s />%s" % (tag, lb)
        else:
            return "<%s>%s%s</%s>%s" % (tag, lb, "".join([
                to_html(x, inline) for x in data[1:]]), tag, lb)
# 好きに流用してください

後は、例えば

from html import *
data = (
    BODY,
    (P,u"シリーズ後半に入った ",
     (A,{"href":"http://www.pc-moe.com/ug/"},u"UG☆アルティメットガール"),
     u" 微妙絶妙なおかしみのある回でした。"),
    (P,(STRONG,u"光の国"),u"観光のバスに乗り",u"ヒロイン達の",
     (STRONG,u"双子山"),u"学園2年",(STRONG,u"M78"),u"組は修学旅行ですが。"),
    (P,(EM, {"title":u"アルティメットガール・ロリ"}, u"つぼみ"),u"の歌う",
     (CITE,u"『UFOマンの歌』"),u"(?)での ", (Q,u"マッハの腰つき"),u" で ",
     (Q,u"勝利のエクスタシー"),u" を ", (Q,u"飛ばすぜ"),u" って、やっぱり",
     (EM,u"UFOマン"),u"が怪獣を倒していた頃もそんな倒し方をしていたので",
     u"しょうか。"),
    (P,u"しかしクラス丸々一緒に乗っているバスの中から ",
     (Q, ruby(u"白絹", u"シルク"),u"、頑張れ!"),u" と声援を送る",
     (EM,u"ヴィヴィ"),u" & ",(EM,u"つぼみ"),u"、それってヤバくないですか?"),
    (HR,),
    (P,(Q,u"真の女体芸術を追求する"),u" ",(EM,u"クラシック怪獣マーラー"),
     u" & ",(EM,u"UFOマン"),u" & ",
     (EM,{u"title":u"コメンテーター"},u"岡村与作"),u"はともかくとして。"),
    (P,u"怪獣に感じさせられまくった上、",(EM,u"真"),u"とタンデムシートで",
     (STRONG,u"密着"),u"。セクハラ怪獣 & コメンテーターによる表面上の騒ぎ",
     u"より深い部分もエロですね。"),
    (P,(CITE,u"『あるてぃめっとれいでぃお』第6回「熱い男がやって来た!」"),
     u"の方でも今回特別に",(EM,{"title":u"ヒーロー"},u"諸星真"),u"役の",
     (DEL,u"変態"),(EM,{"title":u"正真正銘ロリコン"},(INS,u"泰"),u"勇気"),
     u"氏をゲストに迎え、色気のあるネタで盛り上がってますし。"),
    (P,u"後半に入って浅いエロから深いエロに進化して来ている感じ。")
    )
print to_html(data)

というようにして使います。(ちなみにこれの実行例が一つ前のアレ)

このまま実用に使うにはちょっと辛いですが、どこにでもある Python にちょっとしたスクリプトを加えるだけで、要素名の正当性やタグの交差までチェックしてくれる HTML エディターとして使えるわけですからアイデアとしては悪くないかも。

元々が Python のソースなわけですから変数も関数も使えるわけで。そこで定義してある ruby 関数のようなサポート関数をさらに追加して行けば使い勝手も良くなるでしょう。

アルティメットガール西へ

シリーズ後半に入った UG☆アルティメットガール 微妙絶妙なおかしみのある回でした。

光の国観光のバスに乗りヒロイン達の双子山学園2年M78組は修学旅行ですが。

つぼみの歌う『UFOマンの歌』(?)での マッハの腰つき勝利のエクスタシー飛ばすぜ って、やっぱりUFOマンが怪獣を倒していた頃もそんな倒し方をしていたのでしょうか。

しかしクラス丸々一緒に乗っているバスの中から 白絹(シルク)、頑張れ! と声援を送るヴィヴィ & つぼみ、それってヤバくないですか?


真の女体芸術を追求する クラシック怪獣マーラー & UFOマン & 岡村与作はともかくとして。

怪獣に感じさせられまくった上、とタンデムシートで密着。セクハラ怪獣 & コメンテーターによる表面上の騒ぎより深い部分もエロですね。

『あるてぃめっとれいでぃお』第6回「熱い男がやって来た!」の方でも今回特別に諸星真役の変態勇気氏をゲストに迎え、色気のあるネタで盛り上がってますし。

後半に入って浅いエロから深いエロに進化して来ている感じ。

2005年2月21日

アクセスカウンターを

2月14日に設置して今日で一週間。

カウントが175くらい行ったので 25カウント/日くらいになります。

RSS で更新を通知する blog ですから日数より更新数を基準にした方が良いとして、(実質)4回の更新なのでこちらの基準からだと 44カウント/更新数です。

UG☆アルティメットガールの感想と Python スクリプティングの覚え書きがあるだけの内容でこれだけというのは多いのか少ないのか。プロの漫画家でも 普段は30人くらいのお客様なのですが という事ですから、何の取りえも無い素人 blog としては多い方なのかな?

ちなみに私自身の blog 巡回は goo RSSリーダーキーワード仕掛けてというのがメイン。他に30ヶ所くらいの RSS を登録してもいますが、結局はそこからの記事も含めキーワード機能で引っかかっているのを読む事が多いです。

blog が従来のホームページやBBSと違う最大の部分は RSS による更新通知のおかげで更新頻度の低い所も読み落とす事が無いという点、ですよね。

例えば Eroge RSS Checker のような所を登録しておけばそこに登録している月に一度更新が有るか無いかというようなサイトまでまとめてチェックして、それを(ゲーム名をキーワードに登録しておいた) RSS チェッカーが選り分けてくれる。

ネット自体のノリが特定の場所に発言をまとめておく BBS(メーリングリスト)/ホームページ ではなくて、勝手気ままに発せられる発言を様々な手段で収集/選別する blog の post へと変化しつつある感じ。

電子メール、あるいは WWW の発明以来の本質的な変化なのかもしれません。

2005年2月20日

アカウントやパスワードをソースに置かない

実用品でなくテスト用のプログラムと言えどソース中にパスワードが散乱するのは危険。なので、例えば account.py という名前で

ACCOUNT = "hoge"
PASSWORD = "????????"

というだけの内容の Python パッケージを作っておき、実際のプログラムではそれを

from account import *

して使うのが良。 account.py の方は実行する時だけ置き、使い終わったら削除すれば安全。

……くらい用心しておかないと……。(;_;)

修正と XML-RPC と BOM

ココログの過去ログ・アーカイブ作成」を修正しました。ココログから流用した CSS での表示が IE でおかしくなる( h1 タイトルが h2 と重なる等)のを直したのですが、ついでなので色々と強化。ベーシックテンプレートで使われている style 要素を流用する程度ならそのまま使えるはず。

でも実を言えばこれみたく XML-RPC でデータを取り出すよりも「記事を書き出す(エクスポート)」で出来るファイルからデータを読み込む方が簡単かつ情報量が多かったりします。逆に、エクスポートのファイルに無くて XML-RPC だと取得できる情報は固定リンクの URL のみ。(それだけなら metaWeblog.getRecentPosts 一回で取得出来てしまいます。)

このプログラムだとカテゴリーとトラックバックを取得するため 1 post に付き2回のアクセスがあるせいで 2 post/秒くらいの速度しか出ません。40 post そこそこの、この blog ですら24秒くらい掛かってしまいます。元々は XML-RPC のサンプルを作るつもりでいじっていたのが何となく肥大してしまっただけの代物なので実用上の優劣を気にしてはいませんでしたが……。

ついでに「utf-8 テキストファイルの <, >, & を html 用にエスケープ」の方も訂正。こちらは BOM 付きテキストを処理した時に <pre> の次にその BOM を挟み込んでしまうのを直しました。 pre 要素に入れる処理はこちらに投稿する時に後付けしたのでちゃんとテストしていなかったのが敗因。

まあ BOM は ZERO WIDTH NON-BREAKING SPACE でもあるわけですから文書中の何処にあっても問題ないはずですが、世の中そんなに甘くは無いわけで……。

2005年2月19日

utf-8 テキストファイルの <, >, & を html 用にエスケープ ver.1.0.1

# 要 Python

# Python 等プログラムのソースを html に貼り付ける時に使用。
# 丸のまま貼り付けられるように pre 要素としてタグで囲ってあります。

# コマンドライン引数として対象ファイル名を渡す物なので、
# 「ドラッグ・アンド・ドロップで Python プログラムにファイルを渡す」
# を使うと便利。

# 結果は拡張子を ".txt" に変えたファイルに出力されるので、
# 元々の拡張子が ".txt" の場合は予め他に変更しておくこと。
import sys, os.path
from xml.sax.saxutils import escape
for i in sys.argv[1:]:
    print os.path.basename(i),
    root, ext = os.path.splitext(i)
    if ext == ".txt":
        print u"error: 自身の書き換えは出来ません"
        continue
    f = file(root + ".txt", "w")
    f.write((u"\ufeff<pre>\n%s</pre>" % escape( # BOM を足す
        unicode(file(i).read(), "utf-8").lstrip(u"\ufeff")) # BOM があれば抜く
             ).encode("utf-8"))
    f.close()
    print "ok."
# 好きに流用してください

2005年2月18日

ココログの過去ログ・アーカイブ作成 ver.1.0.1

# ココログのアーカイブ作成 ver.1.0.1
# 要 Python
# CSS はココログの style 要素(あるいは styles.css)がそれなりに使えます
import xmlrpclib, urlparse, calendar, time, os, os.path
WEBLOG = "http://tuchinoko.moe-nifty.com/oboegaki/" # ここを自分のココログ top に
ACCOUNT = "hoge" # ココログアカウント
PASSWORD = "????????" # パスワード
# 以下2つは False にすると速くなる
TRACKBACK = True # トラックバックを取得しないなら False
CATEGORIES = True # カテゴリーを取得しないなら False

MAXTITLES = 10000 # 取得する記事の最大数
WEEK = (u"月曜日", u"火曜日", u"水曜日", u"木曜日",
        u"金曜日", u"土曜日", u"日曜日") # 曜日の表記
HTMLHEAD = "".join([
#    '<?xml version="1.0" encoding="utf-8"?>\n' # IE でおかしい(過去互換モード?)
    '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"'
    ' "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">\n'
    '<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja">\n'
    '<head>\n'
    '<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />\n'
    '<link rel="alternate" type="application/atom+xml" title="Atom"'
    ' href="%satom.xml" />\n' % WEBLOG,
    '<link rel="alternate" type="application/rss+xml" title="RSS"'
    ' href="%sindex.rdf" />\n' % WEBLOG])
class Post(object):
    def __init__(self, post, blogname, userdict, server):
        self.blogname = blogname
        self.title = unicode(post["title"])
        self.time = time.localtime(calendar.timegm(time.strptime( # 決め打ち(^^;
            str(post["dateCreated"]).rstrip("Z")+"UTC", "%Y-%m-%dT%H:%M:%S%Z")))
        self.link = post["link"]
        url = urlparse.urlparse(self.link)[2]
        (dummy, self.weblogname, self.dir_year,
         self.dir_month, self.filename) = url.split("/")
        self.url = "%s/%s/%s" % (
            self.dir_year,self.dir_month, self.filename)
        self.description = unicode(post["description"])
        self.text_more = unicode(post["mt_text_more"])
        if post["mt_convert_breaks"] != "0": # 手抜きです
            self.description = self.description.replace("\n", "<br />\n")
            self.text_more = self.text_more.replace("\n", "<br />\n")
        self.username = userdict[post["userid"]]
        self.postid = post["postid"]
        self.trackback = []
        if TRACKBACK:
            self.trackback = server.mt.getTrackbackPings(self.postid)
        self.categories = []
        if CATEGORIES:
            self.categories = server.mt.getPostCategories(
                self.postid, ACCOUNT, PASSWORD)
        print ".",
    def replace_text(self, replace_text):
        for old, new in replace_text:
            self.description = self.description.replace(old, new)
            self.text_more = self.text_more.replace(old, new)
    def get_html(self, prev=None, next=None):
        if prev:
            prev_url = "../../%s" % prev.url
        if next:
            next_url = "../../%s" % next.url
        data = [
            HTMLHEAD,
            u'<title>%s: %s (アーカイブ)</title>\n'
            % (self.blogname, tagcut(self.title)),
            '<link rel="stylesheet" type="text/css" href="../../styles.css" />\n'
            '<link rel="stylesheet" type="text/css" href="../../post.css" />\n'
            '<link rel="stylesheet" type="text/css" href="styles.css" />\n'
            '<link rel="start" href="../../index.html" title="Home" />\n']
        if prev:
            data += ['<link rel="prev" href="%s" title="%s" />\n'
                     % (prev_url, tagcut(prev.title))]
        if next:
            data += ['<link rel="next" href="%s" title="%s" />\n'
                     % (next_url, tagcut(next.title))]
        data += [
            '</head>\n<body>\n<div id="container">\n<div id="banner">\n'
            u'<h1><a href="%s">%s</a></h1>\n<h2>(アーカイブ)</h2>\n</div>'
            % (WEBLOG, self.blogname),
            '<div class="content">\n<div class="entry-nav">\n<p align="right">']
        if prev:
            data += ['<a href="%s">&laquo; %s</a> | ' % (prev_url, prev.title)]
        data += [u'<a href="../../index.html">目次</a>']
        if next:
            data += [' | <a href="%s">%s &raquo;</a>' % (next_url, next.title)]
        data += [
            '</p>\n</div>\n'
            '<h3><a href="%s">%s</a></h3>\n' % (self.link, self.title),
            '<div class="entry-body">\n%s</div>\n' % self.description]
        if self.text_more.strip():
            data += ['<hr />\n<div class="entry-more">\n%s</div>\n'
                     % self.text_more]
        t = self.time
        y, m = t.tm_year, t.tm_mon
        s = urlparse.urlsplit(WEBLOG)
        about = urlparse.urlunsplit((s[0], s[1], "about.html", "", ""))
        data += [
            '<p class="posted"  align="right">\n'
            u'<a href="../../index.html#year%04d">%d年</a>' % (y, y),
            u' <a href="../../%04d/%02d.html">%d月</a> %d日 %s %d時 %d分'
            % (y, m, m, t.tm_mday, WEEK[t.tm_wday], t.tm_hour, t.tm_min),
            ' <a href="%s">%s</a>' % (about, self.username)]
        if self.categories:
            data += [' in ',
                     ", ".join(['<a href="../../category/%s.html">%s</a>'
                                % (x["categoryId"], unicode(x["categoryName"]))
                                for x in self.categories])]
        data += ['</p>\n']
        if self.trackback:
            data += [
                u'<h2 id="trackback">トラックバック</h2>\n'
                '<div class="trackback-content"><ul>\n%s</ul>\n</div>\n'
                % "".join(['<li><a href="%s">%s</a></li>\n'
                           % (x["pingURL"], unicode(x["pingTitle"]))
                           for x in self.trackback])]
        data += ['</div>\n</div>\n</body>\n</html>\n']
        return "".join(data)
    def make_htmlfile(self, prev=None, next=None, path=""):
        writehtml(os.path.join(path, self.weblogname, self.dir_year,
                               self.dir_month, self.filename),
                  self.get_html(prev, next))
def tagcut(html):
    data = []
    in_tag = False
    for i in html:
        if in_tag:
            if i == ">":
                in_tag = False
        else:
            if i == "<":
                in_tag = True
            elif i == '"':
                data.append("&quot;")
            else:
                data.append(i)
    return "".join(data)
def writehtml(filename, html):
    dirname = os.path.dirname(filename)
    if not os.path.exists(dirname):
        os.makedirs(dirname)
    file(filename, "w").write(html.encode("utf-8"))
def get_posts():
    server = xmlrpclib.ServerProxy("http://app.cocolog-nifty.com/t/api")
    for i in server.blogger.getUsersBlogs("", ACCOUNT, PASSWORD):
        if i["url"] == WEBLOG:
            id, blogname = i["blogid"], unicode(i["blogName"])
            break
    else:
        raise "%s not found." % WEBLOG
    u = server.blogger.getUserInfo("", ACCOUNT, PASSWORD)
    nickname = unicode(u["nickname"])
    print nickname, "'s blog:", blogname
    return [Post(x, blogname, {u["userid"]:nickname}, server) for x in
            server.metaWeblog.getRecentPosts(id, ACCOUNT, PASSWORD, MAXTITLES)]
def make_month_html(posts, prev=None, next=None):
    p = posts[0]
    blogname = p.blogname
    weblogdir = p.weblogname
    year, month = p.time.tm_year, p.time.tm_mon
    data = [
        HTMLHEAD,
        u'<title>%d年 %d月: %s (アーカイブ)</title>\n'
        % (year, month, blogname),
        '<link rel="stylesheet" type="text/css" href="../styles.css" />\n'
        '<link rel="stylesheet" type="text/css" href="../month.css" />\n']
    if prev:
        y, m = prev[0].time.tm_year, prev[0].time.tm_mon
        prev_date = ("../%04d/%02d.html" % (y, m), u"%d年 %d月" % (y, m))
        data += ['<link rel="prev" href="%s" title="%s" />\n' % prev_date]
    if next:
        y, m = next[0].time.tm_year, next[0].time.tm_mon
        next_date = ("../%04d/%02d.html" % (y, m), u"%d年 %d月" % (y, m))
        data += ['<link rel="next" href="%s" title="%s" />\n' % next_date]
    data += [
        '<link rel="start" href="../index.html" title="Home" />\n'
        '</head>\n<body>\n<div id="container">\n<div id="banner">\n'
        u'<h1><a href="../index.html#year%04d">%d年</a> %d月</h1>\n'
        % (year, year, month),
        u'<h2><a href="%s">%s</a> (アーカイブ)</h2>' % (WEBLOG, blogname),
        '</div>\n<div class="content">\n<div class="entry-nav">\n'
        '<p align="right">']
    if prev:
        data += [u'<a href="%s">&laquo; %s</a> | ' % prev_date]
    data += [u'<a href="../index.html">目次</a>']
    if next:
        data += [u' | <a href="%s">%s &raquo;</a>' % next_date]
    data += [
        '</p>\n</div>\n<ol>\n',
        "".join([
            u'<li><a href="../%s"><small>%02d日 %02d:%02d</small> %s</a></li>\n'
            % (p.url, p.time.tm_mday, p.time.tm_hour, p.time.tm_min, p.title)
            for p in posts]),
        '</ol>\n</div>\n</div>\n</body>\n</html>\n']
    writehtml(os.path.join(weblogdir, ("%04d" % year), ("%02d.html" % month)),
              "".join(data))
def make_category_html(posts):
    blogname = posts[0].blogname
    weblogdir = posts[0].weblogname
    categories = {}
    for p in posts:
        for c in p.categories:
            id = c["categoryId"]
            if id in categories:
                categories[id][1].append(p)
            else:
                categories[id] = (unicode(c["categoryName"]), [p])
    for id, (name, posts) in categories.items():
        data = [
            HTMLHEAD,
            u'<title>%s: %s (アーカイブ)</title>\n' % (name, blogname),
            '<link rel="stylesheet" type="text/css" href="../styles.css" />\n'
            '<link rel="stylesheet" type="text/css" href="styles.css" />\n'
            '<link rel="start" href="../index.html" title="Home" />\n'
            '</head>\n<body>\n<div id="container">\n<div id="banner">\n'
            u'<h1>%s</h1>\n<h2><a href="%s">%s</a> (アーカイブ)</h2>\n'
            % (name, WEBLOG, blogname),
            '</div>\n<div class="content">\n<div class="entry-nav">\n'
            u'<p align="right"><a href="../index.html">目次</a></p>\n</div>\n']
        for y, monthlist in make_yearlist(posts):
            data += [u'<h2><a href="../index.html#year%04d">%d年</a></h2>\n'
                     % (y, y)]
            for m, p_list in monthlist:
                data += [u'<h3><a href="../%04d/%02d.html">%d月</a></h3>\n'
                         % (y, m, m), '<ol>\n']
                for p in p_list:
                    t = p.time
                    data += [
                        u'<li><a href="../%s"><small>%02d日 %02d:%02d</small>'
                        % (p.url, t.tm_mday, t.tm_hour, t.tm_min),
                        ' %s</a>' % p.title]
                    if len(p.categories) > 1:
                        data += ['<small> in %s</small>' % ", ".join(
                            ['<a href="../category/%s.html">%s</a>'
                             % (x["categoryId"], unicode(x["categoryName"]))
                             for x in p.categories if id != x["categoryId"]])]
                    data += ['</li>\n']
                data += ['</ol>\n']
        data += ['</div>\n</div>\n</body>\n</html>\n']
        writehtml(os.path.join(weblogdir, "category", id+".html"),
                  "".join(data))
    c = [(id, name, len(posts)) for (id, (name, posts)) in categories.items()]
    c.sort(lambda x, y:cmp((y[2], x[1]), (x[2], y[1])))
    return c
def make_yearlist(posts):
    yeardict = {}
    for p in posts:
        y, m = p.time.tm_year, p.time.tm_mon
        if y in yeardict:
            if m in yeardict[y]:
                yeardict[y][m].append(p)
            else:
                yeardict[y][m] = [p]
        else:
            yeardict[y] = {m:[p]}
    years = yeardict.keys()
    years.sort()
    years.reverse()
    yearlist = []
    for y in years:
        months = yeardict[y].keys()
        months.sort()
        months.reverse()
        monthlist = []
        for m in months:
            monthlist.append((m, yeardict[y][m]))
        yearlist.append((y, monthlist))
    return yearlist
def make_menu(posts):
    blogname = posts[0].blogname
    weblogdir = posts[0].weblogname
    data = [
        HTMLHEAD,
        u'<title>目次: %s (アーカイブ)</title>\n' % blogname,
        '<link rel="stylesheet" type="text/css" href="styles.css" />\n'
        '<link rel="stylesheet" type="text/css" href="menu.css" />\n'
        '</head>\n<body>\n<div id="container">\n'
        u'<div id="banner">\n<h1>目次</h1>\n'
        u'<h2><a href="%s">%s</a> (アーカイブ)</h2>\n' % (WEBLOG, blogname),
        u'</div>\n<div class="content">\n']
    if CATEGORIES:
        data += [u'<dl>\n<dt>カテゴリー:</dt>\n<dd>%s</dd>\n</dl>\n'
                 % ", ".join(['<a href="./category/%s.html">%s(%d)</a>' % x
                              for x in make_category_html(posts)])]
    all_list = [None]
    for y, monthlist in make_yearlist(posts):
        for (m, p) in monthlist:
            all_list.append(p)
        data += [
            u'<h3 id="year%04d">%d年</h3>\n' % (y, y), '<p>',
            ", ".join([u'<a href="./%04d/%02d.html">%d月(%d)</a>'
                       % (y, m, m, len(p)) for (m, p) in monthlist]), '</p>\n']
    data += ['</div>\n</div>\n</body>\n</html>\n']
    writehtml(os.path.join(weblogdir, "index.html"), "".join(data))
    all_list.append(None)
    for i in range(1, len(all_list)-1):
        make_month_html(all_list[i], all_list[i+1], all_list[i-1])
t = time.clock()
posts = get_posts()
print "ok\n%d posts" % len(posts)
replace_url = [('href="%s"' % p.link, 'href="../../%s"' % p.url) for p in posts]
for p in posts:
    p.replace_text(replace_url)
p = [None] + posts + [None]
for i in range(1, len(p)-1):
    p[i].make_htmlfile(p[i+1], p[i-1])
make_menu(posts)
print "%.2f sec" % (time.clock()-t)
# 好きに流用してください。

2005年2月15日

白絹(シルク)やぶれかぶれ

この weblog の現在のデザインを「井の頭公園」にしているのは UG☆アルティメットガール #1「アルティメット作戦第一号」の舞台がここだったのにちなんでなのですがこのデザイン激しく見づらいです。洒落でわざわざ出来の悪い――吉祥寺シリーズは総じて駄目デザインですが――ものにしておくのも何だしいい加減別のに変えようかとも思うのですが今回の海ネタに合わせようにもなにせココログデザインにあるのはアレくらいですし次回修学旅行に合うのも無さげですし良い具合に使用者も少ないですしもう少しこのままで行こうかと。すみませんけどちゃんと読む時には Web Browser の表示を「スタイルシートを使用しない」にでもしてくださいませ。つーか私もそうして読んでるし。(ダメじゃん)

と、関係無いネタで引っ張ってみたのは今回「あるてぃめっとれいでぃお」第5回「夏特集…ポロリもあるよ!」がアレだったのに合わせて。やはりアレって web radio 収録までに本編制作が間に合わなかったという事なのかな。おそらく最初は触手でうねうねなネタで作っていたのが大人の事情でボツになり作り直しになりやぶれかぶれになって……って考えすぎか?

ってまあ全く本編に言及しないのも何なので。

タコ八郎&クレクレタコラな怪獣がウルトラファイトチープさ小暴れという話。一見ストレートなネタに見えて、実は制作者の愛深いオマージュが感じられる選択です。

もっとも話の本題はそちらではなく、白絹(シルク)レズヴィヴィアンの痴情の拗れと、家政婦見た!聞いた! なアルティメットガール正体解明の方でしたが。でも話自体のレベルは高いのにコンテに起こす段階で雑な表現(冒頭の「親子電話の子機の筈が携帯電話にしか見えない」あたりから「素足で岩に躓いたのに何ともない」のとか「砂煙で視界が遮られ屋根に登っているしか変身解除を見られる位置に無い、というシチュエーションが了解しずらい」とか「知り合いの女子3人を前にしながら彼女らに頼ろうとせずはだけた胸を隠す物を他所に探しに行く」とか)が多くてヘキヘキしました。まあ脚本の作画能力を無視した密度の高さの方が原因なのでしょうけれども。でも話は前回あたりからぐんとレベルが高くなっているのですよね。最初の頃と違いタイトルと内容が合うようにもなりましたし。もったいないなぁ。

しかし岡村与作へ向ける諸星真敬愛あたりは視聴者に全然通じてない気配ですし、また今回の話で特に重要だった小春野繭のアルティメットガールの正体解明に対する熱意の理由も分からないですし。足元がしっかりしていないのが……。

でもUFOマンは幸せそうだったし、つぼみはスク水だし、まあいいか。

ところで想い人がどつかれ屋根から転落する様を見て白絹(シルク)は何とも思わなかったのだろうか?

2005年2月13日

…で作ってみたカレンダー

先のココログのカレンダー形式リンク作成で作ってみたサンプルです。

2005年

2005年 2月
12345
6789101112
13141516171819
20212223242526
2728

2005年 1月
1
2345678
9101112131415
16171819202122
23242526272829
3031

2004年

2004年 12月
1234
567891011
12131415161718
19202122232425
262728293031

ココログのカレンダー形式リンク作成 ver.1.0.2

# 要 Python
import xmlrpclib, xml.sax.saxutils, calendar, time, sys
URL = "http://tuchinoko.moe-nifty.com/oboegaki/" # ここを自分のココログ top に
NAME = "hoge" # ココログアカウント
PASS = "????????" # パスワード
MAXTITLES = 10000 # 取得する記事の最大数
class Post(object):
    def __init__(self, post):
        t = time.strptime(str(post["dateCreated"]).rstrip("Z")+"UTC",
                          "%Y-%m-%dT%H:%M:%S%Z")
        self.time = time.localtime(calendar.timegm(t))
        self.title = unicode(post["title"])
        self.link = post["link"]
    def get_date(self):
        t = self.time
        return t.tm_year, t.tm_mon, t.tm_mday
def make_calendar(year, month, month_data):
    calendar.setfirstweekday(calendar.SUNDAY)
    data = [
        '<table rules="cols" style="text-align:center;">\n',
        u'<caption>%d年 %d月</caption>\n' % (year, month),
        '<tr style="color:green; background-color:#ffc;">'
        u'<th style="color:red;">日</th>',
        u'<th>月</th><th>火</th><th>水</th><th>木</th><th>金</th>',
        u'<th style="color:blue;">土</th></tr>\n']
    for week in calendar.monthcalendar(year, month):
        data.append('<tr>')
        for day in week:
            data.append('<td>')
            if day:
                if day in month_data:
                    d = month_data[day]
                    p = d[-1] # その日の最初の post
##                    p = d[1] # その日の最後の post にするなら
                    t = [x.title for x in d]
                    t.reverse()
                    title = " | ".join(t)
##                    if len(d) > 1: # タイトル全部でなく数を表示する場合
##                        title = u"%s、他%d" % (p.title, len(d)-1)
##                    else:
##                        title = p.title
                    title = xml.sax.saxutils.quoteattr(
                        xml.sax.saxutils.unescape(title))
                    data.append('<a href="%s" title=%s>%d</a>' % (
                        p.link, title, day))
                else:
                    data.append('%d' % (day,))
            data.append('</td>')
        data.append('</tr>\n')
    data.append('</table>\n')
    return "".join(data)
try:
    server = xmlrpclib.ServerProxy("http://app.cocolog-nifty.com/t/api")
    blogs = server.blogger.getUsersBlogs("", NAME, PASS)
except Error, v:
    print "ERROR", v
    sys.exit()
for i in blogs:
    if i["url"] == URL:
        ID = i["blogid"]
        print "blog:", unicode(i["blogName"])
        break
else:
    print URL,"not found."
    sys.exit()
try:
    posts = server.metaWeblog.getRecentPosts(ID, NAME, PASS, MAXTITLES)
except Error, v:
    print "ERROR", v
    sys.exit()
data = {}
min_time = (10000,)
max_time = (0,)
for i in posts:
    p = Post(i)
    d = p.get_date()
    if d in data:
        data[d].append(p)
    else:
        data[d] = [p]
    min_time = min(min_time, p.time)
    max_time = max(max_time, p.time)
##    print "%4d/%2d/%2d" % p.get_date(), p.title
all_calendars = []
for year in range(max_time.tm_year, min_time.tm_year-1, -1):
    year_calendars = []
    for month in range(12, 0, -1):
        month_calendar = {}
        for day in range(1, 32):
            k = (year, month, day)
            if k in data:
                month_calendar[day] = data[k]
        if month_calendar:
            year_calendars.append((month, month_calendar))
    if year_calendars:
        all_calendars.append((year, year_calendars))
data = [
    '<?xml version="1.0" encoding="utf-8"?>\n',
    '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"',
    ' "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">\n',
    '<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja">\n',
    '<head>\n',
    '<title>calendar</title>\n',
    '</head>\n<body>\n']
for year, year_calendars in all_calendars:
    data.append(u'<h4>%d年</h4>\n' % (year,))
    year_data = []
    for month, month_calendar in year_calendars:
        print u"%4d年%2d月 %3d posts" % (year, month, len(month_calendar))
        year_data.append(make_calendar(year, month, month_calendar))
    data.append('<hr />\n'.join(year_data))
data.append('</body>\n</html>')
f = file("calendar.htm", "w") # 作成する html ファイル名
f.write("".join(data).encode("utf-8"))
f.close()
# 好きに流用してください。

ゆのはな体験版

ゆのはなカウントダウン

ゆのは黒いよゆのは

体験版が楽しいので大きなお友達は是非やりましょう。

ゆのはなカウントダウン

2005年2月12日

Pygame の system font を一通り見る ver.1.1.1

import pygame # 要 Pygame
from pygame.locals import *
import math
def main():
    screen = pygame.display.set_mode((640, 480))
    fonts = pygame.font.get_fonts()
    fonts.sort()
    order = 0
    for fontname in fonts:
        order += 1
        print order, fontname
        for bold, italic in ((False, False), (True, False),
                             (False, True), (True, True)):
            screen.fill((0, 0, 34))
            y = 10
            for i in range(9):
                size = int(12 * math.sqrt(2) ** i)
                font = pygame.font.SysFont(fontname, size, bold, italic)
                screen.blit(
                    font.render(
                        u"%d$ Hoge, %s! @±つちのこ。" % (size, fontname),
                        True, (200, 200, 0))
                    ,(10, y))
                pygame.draw.aaline(screen, (0, 100, 0), (0, y), (640, y))
                ascent = font.get_ascent()
                pygame.draw.aaline(screen, (255, 0, 255),
                                   (10, y+ascent), (630, y+ascent))
                y += size #font.get_linesize() #font.get_height()
            pygame.display.flip()
            pygame.display.set_caption("%d %s %s" % (order, fontname,
                        pygame.font.match_font(fontname, bold, italic)))
            pygame.time.wait(500)
            if pygame.event.get((QUIT, KEYDOWN, MOUSEBUTTONDOWN)):
                return
    print "[[[ end ]]]"
    while pygame.event.wait().type not in (QUIT, KEYDOWN, MOUSEBUTTONDOWN):
        pass
pygame.init()
try:
    main()
finally:
    pygame.quit()
# 好きに流用してください。

2005年2月 8日

アキバより愛をこめて

UG☆アルティメットガール 何だこの気合の入りまくった回は!(笑) やはり舞台が秋葉原だからなのか!? コスプレ喫茶でバイトというシチュエーションやら敵が編集怪獣メガミマスクやらとネタとパロディー満載。やっと出たヴィヴィにゃんの変身シーンも に代わってお仕置きよ♥ なスベシャルバージョン。

ヤマァトナデシコタルモノ… と言い含められ教育されたハーフヴィヴィアンをアキバのガイジンチョウドキュウハイカラボインガール だの オーコレハナマツバモノデェス だの形容させるのとか、地味な所でも芸がありますね。

ヴィヴィアンは三人の中で一番大人に見えてもそれは外面から規定され本音を押し殺して適応している姿でしかないですので――白絹(シルク)への歪んだ(?)愛も「外面化された理想の自分を彼女が体現しているから」という理由もあるのでしょうし――ブチ切れると自分を制御できなくなって……。

しかし、語尾が にゃん になってましまった(笑)ネコミミモード白絹(シルク)声援MOEパワーをマックスにするヴィヴィアン。今回の MOE見ちゃイヤん 乙女 エナジー ではなく 見ていて! 乙女 エナジー の方ですね。

でもそれだとロリ姫マスター・ロリ妃殿下のマナイタだの声援され舞い上がっているつぼみの方も、前回の写真撮影で MOE 溜めても良さそうなもんでしたが……やはりロリにはまだ何かが足りないのか。

そして拗れた三角関係に、アルティメットガールの正体に迫る小春野。今後の展開が楽しみです。

2005年2月 4日

自分のココログのデータを取得する Python サンプル

import xmlrpclib
import sys
URL = "http://tuchinoko.moe-nifty.com/oboegaki/" # ここを自分のココログ top に
NAME = "hoge" # 自分のココログアカウント
PASS = "????????" # 同パスワード
MAXTITLES = 10000 # 取得する記事の最大数

server = xmlrpclib.ServerProxy("http://app.cocolog-nifty.com/t/api")
try:
    blogs = server.blogger.getUsersBlogs("", NAME, PASS)
except Error, v:
    print "ERROR", v
    sys.exit()
for i in blogs:
    if i["url"] == URL:
        ID = i["blogid"]
        print "blog:", i["blogName"]
        break
else:
    print URL,"not found."
    sys.exit()
try: # ここらへんを適当に改造するべし
    titles = server.mt.getRecentPostTitles(ID, NAME, PASS, MAXTITLES)
except Error, v:
    print "ERROR", v
    sys.exit()
for i in titles:
    print str(i['dateCreated']), unicode(i['title'])
print "total", len(titles), "titles."
# 好きに流用してください。

2005年2月 1日

あっ!つぼみが食べられる!

UG☆アルティメットガール メディカル怪獣オチューシャーさん。バルタン星人ポーズで笑うメトロン星人風情の彼ですが……あああ、あれは痛そう。(^^;;;;;

んで、彼を倒したエッチ怪獣つぼみですが、ギャラリーにもオチューシャーにもサービス精神を振り撒いた上に MOE に頼らぬ頭脳プレイでオチューチャーを昇天させた手並み、さすがです。というかUFOマンすら騙すタヌキっぷり、空恐ろしくもありますね。

しかしあの注射、何を注入していたのやら。後遺症出ないかな……。

今回の4話にして初めてつぼみの変身シーンが登場。DVDが6話ずつ全2巻ですからヴィヴィアンの変身シーンが7話目に来れば上手く分散できるわけか……って邪推かな? ってそれはともかく。つぼみのあの、変身最後でニカッと笑う所が良いです。彼女がヒロイン3人中では一番好きだな。

あるてぃめっとれいでぃお第3回の方で「白絹(シルク)大人の扉が という台詞が元の台本では 赤ちゃん出来ちゃう になっていた」という話が出てますが。改めて見直すとこの話全体が家族、恋人をイメージさせるシーンばかり。今まで設定にしか無かった「小春野繭白絹(シルク)の姉」というのも今回表に出ましたし。お話自体は中埋めの設定確認めいたものでしたがシリーズ全体としては重要な話になるのかも。怪獣の内面が出る話、としてもこれが初めてですね。

ところで諸星の裸を 見覚えがある って……まあつぼみだと家の中でも風呂上り等平気で裸のままうろついていそうか。直前に裸を見られた更衣室シーンでも恥じらいの無い妹 & 動じない兄、でしたし。……いや、妹以外の女の子達の下着姿にまで動じないのはいろいろな意味で失礼だと思いますが。

しかしヴィヴィアンって白絹(シルク)諸星真の事を……。

« 2005年1月 | トップページ | 2005年3月 »

ブログ妖精

  • ココロ

Affiliate

無料ブログはココログ