So-net無料ブログ作成
検索選択

「チッターぽい」解説します [プログラム三昧]このエントリーを含むはてなブックマーク#

WS000363.png

「チッターぽい」作りましたで、作成したプログラムですが、忙しさにかまけて、全く整備していませんでした。 認証なんか装備していないにもかかわらず、いままで、SPAMの標的にされなかったのが、不思議なぐらいです。 それでは、作成したソースコードを説明していきます。

データベース初期化CGI : chitter-poi-init.cgi

おなじみのデータベース初期化CGIです。 さくらのレンタルサーバでは、シェルが使えないので、データベースを初期化するためだけに CGI スクリプトを作成します。

#!/usr/local/bin/python
# $Id: chitter-poi-init.cgi,v 1.1 2010/01/16 03:01:47 noritan Exp $

import sys
import os
import cgi

db_file = "chitter-poi.sqlite"
table_name = "visitor"
sql = "CREATE TABLE %s (time NUMBER, description TEXT)" % table_name
command = "/usr/local/bin/sqlite3 %s \"%s\"" % (db_file, sql)

# Show error as a page description.
sys.stderr = sys.stdout

# Execute command
print """Content-type: text/plain

STATUS=%s
""" % (os.system(command))

データベースの構造自体は、今まで作ってきた「掲示板みたいなもの」と同じです。 数値型(NUMBER)の"time"と文字列型(TEXT)の"description"という二つのカラムから出来た"visitor"という表が一つだけ存在する"chitter-poi.sqlite"というデータベース・ファイルを作成しています。

レコード追加兼表示CGI : chitter-poi.cgi

すでに、Python CGI で作るアクセスカウンタ~sqlite3モジュール編~で、 Python から sqlite3 モジュールを使う手法を獲得しました。 しかしながら、この「チッターぽい」では、「納期優先」の旗の下、Python CGI で 掲示板みたいなものを作る~FieldStorage編~で使用した、「"sqlite3"コマンドを呼び出して、その入出力からデータベースを扱う」手法を取り入れました。 そのため、変更箇所は、ほんの少しです。 「再利用」と呼んでください。

#!/usr/local/bin/python
# $Id: chitter-poi.cgi,v 1.1 2010/01/16 03:09:52 noritan Exp $

import os
import sys
import cgi
import urllib
import time
import cgitb
import subprocess

# Show error as a page description.
sys.stderr = sys.stdout
cgitb.enable()

# Database releated information
db_file = "chitter-poi.sqlite"
table_name = "visitor"
command = "/usr/local/bin/sqlite3 %s" % (db_file)

# Get a POST data.
form = cgi.FieldStorage()

# Get Current time
now = time.time()

# Get and escape a MESSAGE
message_key = 'message'
if message_key in form:
    message = urllib.quote(cgi.escape(str(form.getvalue(message_key))))
else:
    message = ""

# Compose a SQL
sql = "SELECT time, description FROM %(table)s ORDER BY time DESC LIMIT %(limit)s;"
if len(message) > 0:
    sql = \
      "INSERT INTO %(table)s VALUES (%(now)f, \"%(message)s\");\n" \
      + sql

# Show HTML header
print """Content-type: text/html; charset="utf-8"

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
    "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" >
<head profile="http://www.w3.org/2005/10/profile">
<title>Chitter-poi</title>
</head>
<body>
<h1>Chitter-poi</h1>
<form action="./chitter-poi.cgi" method="post">
<div>
<textarea name="message" rows="2" cols="20"></textarea>
</div>
<p>
<input type="submit" value="Submit" />
<a href="./chitter-poi.cgi">Reload</a>
</p>
</form>
"""

# Access to the DATABSE
pipe = subprocess.Popen(command, shell=True,
    stdin=subprocess.PIPE,
    stdout=subprocess.PIPE,
    close_fds=True
);
(pipe_out, pipe_in) = (pipe.stdin, pipe.stdout)
pipe_out.write(
  sql % {
    "table"   :table_name,
    "now"     :now,
    "message" :message,
    "limit"   :16
  }
)
pipe_out.close()

# Show a list of visitor record
print """<dl>
"""

# Make a list of messages
try:
    for line in pipe_in:
        field = line.split("|")
        asctime = time.strftime(
          "%Y-%m-%d %H:%M",
          time.localtime(float(field[0]))
        )
        message = urllib.unquote(field[1])
        print "<dt>%s</dt><dd>%s</dd>\n" % (asctime, message)
finally:
    pipe_in.close()


# Show footer
print """
</dl>
</body>
</html>
"""

この CGI では、 HTML 文書の作成までをおこなっています。 そのため、連動する別の HTML などは必要なく、この CGI だけですべての処理を行っています。

もともと、遅い携帯端末で使用することを考えて作成したので、メッセージを書き込む textarea もちいさめです。 また、余分なパケットを飛ばさないために、 CSS などの装飾やカワイイ画像などは、一切ありません。

この「チッターぽい」では、最新の書き込み16件のみを表示して、端末の負荷を軽くしています。 初版のプログラムでは、すべてのレコードを取り出して、最初の16件だけを表示していました。 しかし、それでは、レコードが増加するとサーバ側の負荷が増えてしまいます。

SQL で、上位レコードだけを取り出す構文として最初に紹介されているのが "TOP n" という句です。 この句を SELECT 文にくっつけると、最初の数レコードだけを取り出すことが出来ます。

ところが、 SQLite では、 TOP 句を使用することが出来ませんでした。 おそらく、 SQLite が対応していないのが原因だとは思います。 調べていくうちに、 SQLite では、 TOP 句の代わりに LIMIT 句というものが使えるらしいとわかってきました。

SELECT time, description FROM %(table)s ORDER BY time DESC LIMIT %(limit)s;

SELECT 文に "LIMIT n" を加えると、最初の n レコードのみを取り出すことが出来ます。 これに "ORDER BY" 句を組み合わせると、最新の書き込みだけを表示することが出来ます。

次は、 "sqlite3" モジュールを使って書き直すことですが、時間あるかな。 他には、センサーノードの受け皿専用の「チッターロボ」も計画しています。

参考サイト

SQL As Understood By SQLite
SQLite 本家のSQL文法書です。 これを見ると、 LIMIT 句には、範囲を指定する使い方もあることがわかります。

参考文献

ウサギ本は、 SQL の文法までは解説していません。

Python クックブック 第2版

Python クックブック 第2版

  • 作者: Alex Martelli
  • 出版社/メーカー: オライリー・ジャパン
  • 発売日: 2007/06/26
  • メディア: 大型本
Python Cookbook

Python Cookbook

  • 作者:
  • 出版社/メーカー: Oreilly & Associates Inc
  • 発売日: 2005/05/05
  • メディア: ペーパーバック

nice!(0)  コメント(0)  トラックバック(0)  このエントリーを含むはてなブックマーク#

nice! 0

コメント 0

コメントを書く

お名前:
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。

トラックバック 0

トラックバックの受付は締め切りました

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。