【さくらインターネット対応】Python CGIでWebアプリをWordPressに埋め込む方法|初心者向け手順付き

WordPress
スポンサーリンク

こん○○は、よふかしわーくすのよふかしさんです

よふかしさんはちょっとしたツールを作るのに一番使うのはPythonなんですが
これをベースにWebアプリとか作れないかな?と思ってました

先日、レンタルサーバー上にPythonとmatplotlibを構築するところまでやりました
https://www.blog.yofukashi-works.com/?p=2049

今回は実際にさくらインターネットのレンタルサーバー上でPythonコードをCGIで動かして
WordPressサイト上にWebアプリとして公開する手順を解説したいと思います
今回も例にもれず色々とハマりました…


スポンサーリンク

Python CGIとは?なぜWordPressと組み合わせるのか

CGI(Common Gateway Interface)とは、Webサーバーが外部プログラム(今回の場合はPython)を呼び出して、その出力をHTTPレスポンスとして返す仕組みです
さくらインターネットでは、.pyファイルをCGIとして実行可能なので、ちょっとした処理系Webアプリの構築ができます

というわけで、PythonをCGIで動作させる特徴を簡単にまとめてみました

  • Pythonロジック+HTMLで簡単に構築できる
  • Pythonライブラリを活用することで、JavaScriptだけでは難しい処理も実現可能
  • 動作は高速ではないが、小規模、低トラフィックであれば問題ないレベル
  • WordPressにiframeで簡単に埋め込み可能
  • ロジックをユーザーには非公開でバックエンドで実行できる

上位互換な別方策もあるのですが、今回は初トライということもあって、レガシーなCGIベースでやってみました
パフォーマンスやメンテナンス性についてはまずは実際に作ってみてから、今後の改善を検討することにします


Python CGIサンプルコード(初版)

まずは、Pythonのサンプルコードを準備してみます
最大角度を入力すると、0~入力角度までの正弦波をグラフ化するツールです
これを基に解説をしていきます

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import cgi
import matplotlib.pyplot as plt
import numpy as np
import base64
import io

print("Content-Type: text/html; charset=utf-8\n")

form = cgi.FieldStorage()
max_x_str = form.getfirst("max_x", "360")  # デフォルト360
try:
    max_x = int(max_x_str)
except ValueError:
    max_x = 360

# グラフを描画
x = np.linspace(0, max_x, 500)
y = np.sin(np.radians(x))

fig, ax = plt.subplots()
ax.plot(x, y)
ax.set_title("y = sin(x)")
ax.set_xlabel("x(度)")
ax.set_ylabel("y")

buf = io.BytesIO()
plt.savefig(buf, format='png')
buf.seek(0)
img_base64 = base64.b64encode(buf.read()).decode("utf-8")
buf.close()

# HTML出力
print(f"""
<!DOCTYPE html>
<html>
<head><meta charset="utf-8">
  <title>CGI Graph Test</title>
  <style>
    body {{
      font-family: Arial, sans-serif;
      background-color: #f7f7f7;
      text-align: center;
    }}
    form {{
      margin-top: 20px;
    }}
  </style>
</head>
<body>
  <h2>sin(x) グラフ生成</h2>
  <form method="get">
    最大 x 値(度): <input type="text" name="max_x" value="{max_x}">
    <input type="submit" value="グラフ生成">
  </form>
  <hr>
  <img src="data:image/png;base64,{img_base64}" alt="グラフ画像">
</body>
</html>
""")

Shebang

最初の一行目、!/usr/bin/env python3、はShebang(シバン/シェバン)と呼ばれる、
このファイルはどのプログラムから実行させるかをOSに伝える役割を持っています
今回はさくらインターネットのデフォルトではなく、自身で構築したPython3.9.18を使うため、そのパスを指定しておきます

pythonのパスがわからなくなってしまった場合は、下記コマンドで探すと便利です

% find ~ -name "python3*" | grep "/bin/"
/home/username/venv-py39/bin/python3.9
/home/username/venv-py39/bin/python3
/home/username/local/python3.9.18/bin/python3.9
/home/username/local/python3.9.18/bin/python3.9-config
/home/username/local/python3.9.18/bin/python3
/home/username/local/python3.9.18/bin/python3-config

この結果を受けて、前回作成したvenv環境である、
/home/username/venv-py39/bin/python3
を使うことにしますので、先頭行は下記の通り書き換えます

#!/home/username/venv-py39/bin/python3

HTML出力

HTMLはprint(f”””…”””)の中に書くことで出力されます
f”””…”””はf-string構文といって、{変数名}としたものを変数として扱ってくれる機能です
fをつけないと、{変数名}はただの文字列としてprintされてしまうので必須です

ただし、<style>タグの様にbody{…}という記述を構文として使用したい場合、逆に変数だと誤解してしまうので、
それを避けるためにbody{{…}}という様に、中括弧を二重に記述することでリテラルとして出力させる、という点に注意です

改行コードとエンコード

さくらインターネットのサーバーで実行させるための設定です

  • 改行コードは LF(Unix形式)にすること
  • エンコードはUTF-8(BOMなし)でファイル保存すること

Windows環境で開発していると標準設定では、改行コードがCRLF、エンコードがShift-JISになるエディタもあるので要注意です


Pythonコードの設置と実行準備

サーバー上の任意の場所に設置します
今回は、/home/username/www/blog/WebApp/cgi_test.py、という感じに置いてみます

パーミッションは705にすることで実行可能となります

chmod 705 cgi_test.py

CGIを正しく実行するには、.htaccessに以下を追加します

Options +ExecCGI
AddHandler cgi-script .py

.pyファイルをCGIスクリプトとして実行するための基本設定です
これがないと、Pythonファイルの中身がそのまま表示されてしまい、Webアプリとして動作しません


実行してみる

実行結果です
下記の様になりました

ちゃんとWebアプリとして実行できています!
…が、matplotlibのグラフ内の日本語が文字化けしてしまいます


日本語の文字化け対策:日本語フォントのインストール

そもそも、なぜ文字化けするのか?、ですが、
Windowsなどでは日本語フォントが標準でインストールされているので問題にならないのですが、
今回のレンタルサーバー上では日本語フォントが入っていなかった、というのが理由です
その場合は文字がわからないため、豆腐文字(□)として表示されてしまいます

という訳で、日本語フォントをインストールしていきます
まずは、下記よりDownloadします

IPA Font ダウンロード | 一般社団法人 文字情報技術促進協議会

今回は、IPAexゴシック(Ver.004.01)
ipaexg00401.zip(4.0MB)
を使用します

展開してできたipaexg.ttfを、適当なフォルダにUploadします
今回は、/home/username/www/blog/WebApp/font/ipaexg.ttf、という様に置きました

先のPythonコードに対して、下記の通り、追加・修正します

import matplotlib # 追加
from matplotlib import font_manager # 追加

font_path = "/home/username/www/blog/WebApp/font/ipaexg.ttf" # 追加
fp = font_manager.FontProperties(fname=font_path) # 追加
matplotlib.rcParams["font.family"] = fp.get_name() # 追加

ax.set_title("y = sin(x)", fontproperties=fp) # 修正
ax.set_xlabel("x(度)", fontproperties=fp) # 修正
ax.set_ylabel("y", fontproperties=fp) # 修正

そうすると、日本語の文字化けが解消されます


WordPressへの埋め込み

普通にそのままWebページとして公開してもいいのですが、今回はWordPressに埋め込んでみます
例えばWordPressの固定ページを開き、以下のようなiframeタグを挿入すると実現できます

<div style="max-width: 100%; overflow-x: hidden;">
<iframe id="gearCalcFrame"
        src="https://www.blog.yofukashi-works.com/WebApp/cgi_test.py"
        width="100%" height="800"
        frameborder="0"></iframe>
</div>

一旦、簡単なサンプルとしてはこんな感じです
表示関連はHTML側のstyleとWordPress側の兼ね合いで調整していく必要も出てくると思います


終わりに

こんな感じでPythonで作ったWebアプリをWordPressに統合して公開することができました

Python CGIの強みは、軽量ながらも自由度の高いロジック実装ができること、
またWordPressと組み合わせることで、インタラクティブでユーザーに価値あるWebアプリを構築・公開することが可能になるかな、と思います

今回のサンプルを埋め込んでみたものは下記で確認できます

コメント

タイトルとURLをコピーしました