Python を使って、できる限りシンプルに、ローカルネットワーク内の Web サーバーで動く掲示板を作ってみます。
以下の環境で動作確認をしています。
環境:
Windows パソコン、Python 3.x (+Anaconda)
※ スタンドアロンの Windows で動作確認をしています。
加えて、ローカルネットワーク内の Linux を Web サーバーとして他のパソコンからアクセスしても動作することを確認しています。
背景 ~ Python でローカル掲示板!
自宅などで Wi-Fi などのローカルネットワークを使っているとき、ネットワーク内に掲示板が設置できると便利です。
たとえば、使っていない Raspberry Pi (Linux)や Windows パソコンがあったとき、Web サーバーとして活用することにし、スマートフォンなどの他のデバイスからサーバーにアクセスできるようにします。そして、Web サーバー上の掲示板で、予定や行先、備忘メモなどを書き込んで情報を共有できるようにすると、ローカルネットワーク内の各機器をさらに有効活用できることになります。
Web サーバーといえば、LAMP(Linux、Apache、MySQL、PHP)が知られています。また、Django や Flask を使う方法もあります。しかし、インストールや設定などが煩雑です。
そこで、Python の標準機能のみを使って、できる限りシンプルに掲示板を作ってみることにします。Python がインストールされていれば、たかだか 70行程度のプログラミングで、Web サーバーとして動くことになります。
なお、サンプルスクリプトは、最小限の知識や手間で動かせるようにすることを優先しています。
いたずら防止、パスワード設定画面、データのバックアップなど、不特定の人がアクセスする環境で実用上必要となる機能は実装しておりませんので、ご理解をいただきますようお願いいたします。
設定手順
ステップ1:ドキュメントルートの設定
① ドキュメントルート(公開フォルダ)にするためのフォルダを作成してください。
例: C:\user\html1
② ①のフォルダ内にさらに “cgi-bin” というフォルダを作成してください。
③ ②のフォルダ “cgi-bin” 内に “bulletin_board1.py” という名前でテキストファイルを作成し、末尾のサンプルコードをコピー&ペーストして保存してください。簡易な掲示板の Web アプリになっています。
ステップ2: Web サーバーの起動
④ コマンドプロンプト(または、Anaconda Prompt)を起動して、①のフォルダに移動してください。
例: cd C:\user\html1
⑤ 以下のコマンドを実行し、ローカル PC 上で Web サーバーを起動してください。
例:
python -m http.server 8000 --cgi
※ ここで、コマンドプロンプトに ”Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) …” 等の文字列が表示されたら、Web サーバーが起動しています。
※ Web サーバーを停止する場合は、コマンドプロンプト上で、[ctrl] + c を入力してください。
※ また、上記で “8000”(ポート番号)の部分は、別の数値としてもよいですが、⑥で設定する数値と一致させてください。
ステップ3:ブラウザでの確認
⑥ ⑤で Web サーバーを稼働させた状態で、Microsoft Edge などのブラウザを起動し、URL 部分に以下を貼りつけて表示させてください。ブラウザに掲示板のページが表示されると思います。
http://localhost:8000/cgi-bin/bulletin_board1.py
⑦ 掲示板の入力欄に文字列を入力し、「書き込み」ボタンをクリックしてみてください。
→ 掲示板に書き込みができたら、成功です!
サンプルコードの説明
・ サンプルコードは、下記の関連リンク「Webサーバーで動く Python アプリ【Windows 版】」とほぼ同様です。
・ 具体的には、ユーザーがブラウザ経由でサイトの URL にアクセスすると、Python のスクリプトにべた書きされている HTML のテンプレートを返し、ブラウザ側で表示するようになっています。
・ HTML のテンプレート上では、テキストボックスに文字列を入力して送信できるようになっています。
ユーザーが文字列入力して送信すると、サーバー側でユーザーの入力を取得し、テンプレートの HTML ファイルにテキストを差し込んでテンプレートを返します。ユーザーのアクセスに対し、毎回、HTML を更新する動きとなっています。
・ より詳細には、サイトへのアクセス時には ①のフォルダ(ドキュメントルート)内のテキスト(”text1.txt”)を読み込んで表示するようにしています。また、掲示板にコメントを書き込むと、同テキストを更新・保存するようになっています。これにより、過去の書き込みが蓄積されていくようになっています。
・ また、re.sub( … ) としたところで、入力された文字列のチェックをしています。
具体的には、掲示板に HTML の文字列が書き込めるようになっていると XSS 攻撃などが可能になってしまいます。そこで、タグ < … > を除去し、HTML の特殊文字が機能しなくなるようにしています。
他に、文字数に上限を入れるなど、機能を改善したい場合は、この部分を修正してください。
・ 掲示板の内容を削除する場合は、”text1.txt” を削除するか、別フォルダへ移動してください。
・ 掲示板では、新しいコメントをサイト画面の上側に表示するようにしています。
多くの掲示板とは逆にしてありますが、個人/小規模でメモ書きとして使う場合は、最近のコメントがすぐ読めるほうが便利ですので、このような順にしています。
うまく動いたら
・ できる限り簡素なスクリプトとしたため、掲示板は、入力されたテキストをほぼそのまま、HTML に差し込む程度の処理としています。うまく動いたら、テキストファイルの記載量に上限をつける、いたずら防止用の処理を入れる、などしてみてください。
・ スクリプトの末尾のコメントアウト部分で、掲示板の内容を HTML で書き出せるようにしています。
同コメントアウト部分を外すと、掲示板に文字列を書き込んだ際、HTML ファイルを出力するようにできます。たとえば、サーバーが動いていない場合(⑤を実行していない状態)であっても、このファイルをダブルクリックすることで、任意のブラウザで内容を確認できるようになります。
・ 前述の手順では、トップページの HTML すら作っていません。①のドキュメントルートに トップページとなる “index.html” を追加することでトップページを追加できます。このトップページ内に ③の Python スクリプトへのリンクを張ることで、任意の Web アプリを実行できるサイトを設計できます。
・ 掲示板のデータは、単なるテキストで保存しています。データベース(SQLite、SQLなど)すら使っていません。データが増えるようでしたら、入力されたテキストをデータベースに保存するなどの機能改善も検討してみてください。
・ また、掲示板のデータは、現状、1行程度の簡易な入力を想定しています。文字数を増やしたい場合は、HTML のテキストボックスの部分を変更し、改行も入れられるように修正してみてください。
・ ID やパスワード入力の機能を追加したい場合、簡単に対応するのであれば、テキストボックスやボタンを追加することで対応できると思います。たとえば、欄を追加して、書き込みの実行時にパスワードのチェックをするようにし、ID やパスワードの入力が正しい場合のみ書き込みを実行することも可能です。
・ Python の基本機能のみを使って掲示板を動かしています。余計なライブラリは入れていません。したがって、掲示板のデザインや機能を修正し、気に入ったものができたら、たとえば、Windows パソコンから、ネットワーク内にある別の Linux パソコン(Raspberry Pi)などにコピー&ペーストすることで、ほぼそのまま、Web アプリを動かすことが可能だと思います。
・ Python がインストールされている Windows や Linux のパソコンさえあれば、Flask や Django など、ややこしいフレームワークの設定をせず、そのまま動作、移植できることになります。OS 環境、開発環境が異なっていても、掲示板のデータをコピー&ペーストする程度で、比較的かんたんに掲示板の動作環境を移植、再設定できることになります。
・ なお、日本語を扱うページ(HTML ファイル)を作成・生成する場合、以下を例に、生成する HTML のヘッダー内に “UTF-8” 等であることを明記することをお勧めします。(テキストファイルを作る際も、UTF-8 形式で作成・保存するようにします。)
<head>
<meta charset=”utf-8″ />
</head>
Python、HTML、各テキストファイル等で、文字コードを統一・明記しない場合、ページ内で実際に使っている文字やユーザのブラウザに依存して、文字コードの判定が変わる(文字化けが生じる)ことがあるようです。
手元の Windows および Linux 環境で確認する限り、[a] テキストファイルを作る際、また、[b] Python などから読み書きする際、[c] HTML を生成する際、UTF-8 (あるいは、shift-JIS)ですべて統一しておくようにします。こうすると、OS やブラウザの各組み合わせが異なっていても、文字化けなどせずに表示されるようです。
・ 今回、1台のパソコンでサーバーとクライアントを共用し、Web アプリを動かす事例について説明しています。
システムの構成を変え、ローカルネットワーク内で Linux (Raspberry Pi)を Web サーバーとして掲示板を設置しても、同様に動作することを確認しています。
Linux と Windows のように、異なる OS でも Web アプリが動くようにする際は、下記の関連リンク「Web サーバーで動く Python アプリ 【Raspberry Pi 版】」なども参照してみてください。ローカルネットワークでの設定を例に、Web サーバー化、Web アプリ化の手順をまとめています。
ローカルネットワーク内で、ちょっとした掲示板や行先表示板、便利な Web ツールを構築できると思います。
まとめ
ローカルの Web サーバー上で動く掲示板について、Python のスクリプトをまとめました。
70 行程度の Python のスクリプトを1つ作るだけで、簡単に、掲示板の Web アプリを作成できます。
Python がインストールされていれば、Linux などの異なる OS でもほぼ同様に動くことになります。
他にも、Web アプリ、Web サーバーに関連するスクリプトをまとめ、公開しています。
もし関心があるようでしたら、関連リンクなども参考にしてみてください。
関連リンク
・ Webサーバーで動く Python アプリ 【Windows 版】
・ Webサーバーで動く Python アプリ 【Raspberry Pi 版】
・ Python で Web サーバーを動かす 【Windows】
・ Raspberry Pi でローカルWebサーバー 【Python 活用】
・ ローカル Web アプリでグラフ描画 【Python】
・ レンタルサーバーの比較表
関連リンク [PR]
・ Raspberry Pi 5 (8GB RAM) 技適対応品
・ Raspberry Pi 5 8GB 技適対応品/アクティブクーラー
・ Raspberry Pi 5用 27W USB-C PD(電源アダプタ)
サンプルスクリプト bulletin_board1.py
#!/usr/bin/python3
# coding: utf-8
import cgi
import sys, io
import datetime as dt1
import os
import re
# python -m http.server 8000 --cgi
# http://localhost:8000/cgi-bin/bulletin_board1.py
def read2( file1 ):
str1 = ""
if os.path.exists( file1 ):
str1 = read1( file1 )
return str1
def read1( file1 ):
with open( file1, 'r', encoding='utf-8' ) as f1:
# with open( file1, 'r', encoding='shift_jis' ) as f1:
str1 = f1.read()
return str1
def write1( file1, str1 ):
with open( file1, 'w', encoding='utf-8' ) as f1:
f1.write( str1 )
return 0
def format1( str1 ):
return ("00" + str(str1))[-2:]
def get_yymmdd1():
str1 = dt1.datetime.now()
str2 = str(str1.year) + "/" + format1(str1.month) + "/" + format1(str1.day) + " " + format1(str1.hour) + ":" + format1(str1.minute) + ":" + format1(str1.second)
str2 = str( str2 )
return str2
file1 = "text1.txt"
str01 = read2( file1 )
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')
form1 = cgi.FieldStorage()
str02 = form1.getvalue( 'TextBox1', '' )
str02 = re.sub('<.+?>', '', str02)
date1 = get_yymmdd1()
if str02 != '':
str01 = '<font color="#007000"><b>' + date1 + '</b></font><br>' + str02 + "\n\n" + str01
write1( file1, str01 )
str03 = str01.replace( "\n", "<br>\n" )
str04 = '''
<html>
<head>
<meta charset="UTF-8"/>
</head>
<title>掲示板</title>
<body style="background-color:#efefef" >
<form name="Form" method="POST" action="/cgi-bin/bulletin_board1.py">
<input type="text" size="40" name="TextBox1" value="">
<input type="submit" value="書き込み" name="button1">
</form>
{str11}
</body>
</html>
'''.format( str11=str03 )
print("Content-Type: text/html; charset=UTF-8;\n")
print( str04 )
# file1 = "bulletin_board1.html"
# write1( file1, str04 )