ブラウザに結果を表示しよう

gusutabopb 執筆者 Gustavo Bezerra

本節ではプログラムをサーバ上で実行し、実行結果をブラウザに表示することについて説明します。

目次

ウェブサーバーの仕組み

ウェブサーバとはクライントソフトウェア(ブラウザ等)に対して、HTMLや画像等の表示を提供するソフトウェアもしくはそれが動作するコンピュータを指します。
ウェブサーバとクライントの通信はHTTPというプロトコルで行われますが、その基本的な振る舞いは次の通りです。ユーザがウェブサイトを訪れた時、ブラウザはサイトの web サーバと接続します(リクエスト)。サーバはファイルシステム上からファイルを探し出し、ユーザのブラウザにそれを送り返し、ブラウザが表示します (レスポンス)。
ウェブサーバのレスポンスは大きく別けて2種類あります:

  • 要求されたファイルをそのまま提供する
  • 要求されたプログラムを実行して、その結果を提供する

場合があります。

CGI

CGIとはサーバ上でプログラムを動作させるためのインターフェイスです。CGIを使ったプログラムはCGIスクリプトの呼ばれますが、Perl, PHP, Python等、多くの言語でCGIスクリプトを書くことができます。
近年、CGIよりサーバ負荷が小さいインターフェイス(WSGI, FastCGI等)が一般化してますが、今回は便宜上、CGIを使います。
ウェブサーバのソフトウェアにはApacheというものが主流ですが、正しく設定が行われていれば、Apache上でCGIスクリプトを実行して、HTMLのレスポンスを返すことが可能です。以降、Pythonの簡単なCGIスクリプトの実行の仕方を説明しますが、読者には正しく設定されているウェブサーバがあることことを前提とします。

ブラウザ上でHTMLを出力

以下、今日の日付を返す簡単なCGIスクリプトを示します。

#!/usr/bin/python
# -*- coding: utf-8 -*-
import datetime
today = str(datetime.date.today())
print 'Content-type: text/html\n'
print """
<!DOCTYPE html>
<html>
<head><title>CGIスクリプト</title></head>
<body>
これはサーバの実行結果として生成されたHTMLです<br>
今日は%sです
</body></html>
"""%today

上記のコードは最初の行はサーバのどこにPythonのインタプリタがどこにあるかを意味します。それ以降、今日の日付をdatetimeモジュールを使って取得し、簡単なHTMLとして出力しています。ここでHTML本文より前に、スクリプトが一番最初に出力しなければならい文字列が'Content-type: text/html\n'であることに注意しましょう。これがないとエラーが出ます。一度、上記のコードを自分で書いて実行してみることをお勧めします。以下、実行結果の例です。

エラーの場合
成功の場合

実行エラーの場合

スクリプトが正しく実行されない場合、「Internal Server Error」というエラーメッセージが出る場合がある。このとき以下を確認しましょう。

  • 最初にプリントされる文字列が'Content-type: text/html\n'であるかどうか
  • 正しくchmod 755 foo.pyを行っているかどうか
  • ファイルの拡張子が正しいかどうか(サーバの設定によっては.cgi拡張子にする必要があります)
  • ファイルが正しい実行権限のあるフォルダにあるかどうか(サーバの設定によっては/cgi-bin/フォルダにスクリプトを置く必要があります)
  • スクリプトをシェル上で実行して(python foo.py)、スクリプト自体に問題があるかどうか

上記の確認でも問題がわからない場合は下記のことも試してみるといいでしょう。

  • (権限があれば)サーバのエラーログをチェックしましょう。OS Xに標準インストールされているApacheの場合、/var/log/apache2/error_logというファイルです。
  • cgitbモジュールを使ってデバグしてみましょう(詳しくはグーグル先生まで)

文字化けが起こった場合

文字化けが起こった場合、以下のことを確認しましょう。

  • # -*- coding: utf-8 -*-を忘れていないか
  • <head><meta charset="utf8">が追加されてあるかどうか

フォームを作成

入力のユーザーに対して何かレスポンスを表示したい場合、HTMLのフォーム(<form>)を使うのが一般的です。HTMLフォームの基本計は以下の通りです:

<form action="#" method="foo">
  ...
</form>

actionはフォームが送信されるCGIスクリプトのことで、methodはブラウザが使うHTTPメソッドのことです。

フォームには様々な要素を追加することが可能です。以下、いくつかの要素のあるフォームの例とそのコードを示しておきます。各要素に関する詳しいは参考文献を見ておいてください。

テキスト1 テキスト2 ラジオボタン:
<form>
テキスト1 <input type="text" name="sample_text_field">
テキスト2<textarea name="sample_textarea">テキストエリア</textarea>
ラジオボタン: 
<label><input type="radio" name="size" value="s" checked> 小</label>
<label><input type="radio" name="size" value="m"> 中</label>
<label><input type="radio" name="size" value="l"> 大</label>
<input type="submit" name="submit" value="フォームを送信">
<input type="reset" name="reset" value="リセット">
</form>

HTTPメソッド

HTTPには様々なメソッドががありますが、CGIスクリプトでは主にGETPOSTが使われます。GETの場合、サーバの送信されるユーザーの入力は下記のようにURLの中で表示されるのに対し、POSTではユーザーの入力はサーバにURLとは別に送信されます。GETはデフォルトメソッドですが、パスワードのような情報がある場合は絶対にGETを使ってはいけないです。
http://weblab.t.u-tokyo.ac.jp/~foo/bar.py?key1=value1&key2=value2

実装例

それでは、以上のCGIおよびフォームの知識とキーワード抽出で紹介した内容を組み合わせたCGIスクリプトを紹介しておきます。作動しているものはこちらで確認してください。

#!/usr/bin/python
# -*- coding:utf-8 -*-
import cgi
import MeCab

print 'Content-type: text/html\n'
print """
<!DOCTYPE html>
<html>
<head>
	<title>CGI Script</title>
	<meta charset="utf-8">
	<link rel="stylesheet" type="text/css" href="theme.css">
	<script>
	function clearContents(element) {
		element.value = '';
	}
	</script>
</head>
<body>
<h3>CGI Script</h3>
<form method="post" action="mecabbrowser.py">
	<textarea onfocus="clearContents(this);" name="message">文章を入力してください</textarea>
	<input type="submit" name="submit" value="SEND">
</form>
"""

form = cgi.FieldStorage()
message = form.getvalue('message', '')
tagger = MeCab.Tagger()
result = tagger.parse(message)
l = len(unicode(message,'utf-8')) if message else 0

print """
<p>
<strong>入力された文章:</strong><br>
%s<br><br>
<strong>文字数:</strong>%d
</p>
<h3>形態素解析結果:</h3>
""" % (cgi.escape(message),l)

for line in result.split('\n'):
	word,etc = line.split()
	print '<span>'+word+'</span>'+etc+"<br>"
print '</body></html>'

ウェブフレームワーク

以上紹介してきたように、PythonだけでHTMLを出力することは可能ですが、もう少し複雑なウェブアプリを書こうと思えば、このやり方だと限界があります。そこで、「フレームワーク」と呼ばれる補助ツールのようなものが多く開発されています。Djangoのようなパワフルなものから、マイクロフレームワークと呼ばれるFlaskまで、様々あります。Python以外の言語だと、Ruby用のRuby on Railsもとてもよく使われています。興味があれば是非いずれかのフレームワークの使い方を覚えてみてください。

節末課題

ユーザーの入力に対して、どこかのAPIから情報を取得し、何らかの処理を施し、その結果をブラウザ上で表示するCGIスクリプトを作ってください。

参考文献