執筆者 Gustavo Bezerra
本節ではプログラムをサーバ上で実行し、実行結果をブラウザに表示することについて説明します。
目次
ウェブサーバとはクライントソフトウェア(ブラウザ等)に対して、HTMLや画像等の表示を提供するソフトウェアもしくはそれが動作するコンピュータを指します。
ウェブサーバとクライントの通信はHTTPというプロトコルで行われますが、その基本的な振る舞いは次の通りです。ユーザがウェブサイトを訪れた時、ブラウザはサイトの web サーバと接続します(リクエスト)。サーバはファイルシステム上からファイルを探し出し、ユーザのブラウザにそれを送り返し、ブラウザが表示します (レスポンス)。
ウェブサーバのレスポンスは大きく別けて2種類あります:
場合があります。
CGIとはサーバ上でプログラムを動作させるためのインターフェイスです。CGIを使ったプログラムはCGIスクリプトの呼ばれますが、Perl, PHP, Python等、多くの言語でCGIスクリプトを書くことができます。
近年、CGIよりサーバ負荷が小さいインターフェイス(WSGI, FastCGI等)が一般化してますが、今回は便宜上、CGIを使います。
ウェブサーバのソフトウェアにはApacheというものが主流ですが、正しく設定が行われていれば、Apache上でCGIスクリプトを実行して、HTMLのレスポンスを返すことが可能です。以降、Pythonの簡単なCGIスクリプトの実行の仕方を説明しますが、読者には正しく設定されているウェブサーバがあることことを前提とします。
以下、今日の日付を返す簡単な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
)、スクリプト自体に問題があるかどうか上記の確認でも問題がわからない場合は下記のことも試してみるといいでしょう。
/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メソッドのことです。
フォームには様々な要素を追加することが可能です。以下、いくつかの要素のあるフォームの例とそのコードを示しておきます。各要素に関する詳しいは参考文献を見ておいてください。
<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には様々なメソッドががありますが、CGIスクリプトでは主にGET
とPOST
が使われます。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スクリプトを作ってください。