Qiita初投稿です。
今回は下手なところで3時間くらいつまずいた「Heroku上にてPythonをPHP上で動かす」方法を備忘録的に残したいと思います。
脳死で書いています。誤字脱字は温厚な目で見てくれると嬉しいです。
思い立ち
最初はWebページにスクレイピングの情報を掲載できればいいかなーとか思っていました。
でもスクレイピングってPythonで書けば簡単じゃーん!とかいって始まったのが地獄の門の入り口でした。
Pythonでスクレイピングする
取り合えずトップニュースを取得すればいいかなと思い、以下のコードを記述しました。
# coding: utf-8
import requests
from bs4 import BeautifulSoup
# 現在のトップニュースのページIDを取得する
toppage_url = "https://news.yahoo.co.jp/"
html = requests.get(toppage_url)
soup = BeautifulSoup(html.content, "html.parser")
topic_element = soup.select_one("li.topicsListItem")
news_link = topic_element.find("a").get("href")
news_id = int(str(news_link).replace("https://news.yahoo.co.jp/pickup/",""))
# ニュースのトピック情報を取得する
news_url = f"https://news.yahoo.co.jp/pickup/{news_id}"
html = requests.get(news_url)
soup = BeautifulSoup(html.content, "html.parser")
news_element = soup.select_one("p.pickupMain_articleSummary")
print(news_element.text)
PHPでexec()を利用しPythonの出力を取得する
execでコマンドラインのコマンドを実行し、出力を変数に入れることができます。PHPを以下のように書きます。
<?php header("Content-type: text/html; charset=utf-8"); ?>
<!doctype html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>Python-PHP</title>
</head>
<body>
<?php
exec("export LANG=ja_JP.UTF-8");
exec('python news.py', $output);
echo '<p>',$output[0],'</p>';
return false;
?>
</body>
</html>
重要なことは、**exec("export LANG=ja_JP.UTF-8");**の部分。
※日本語が出力される場合、utf-8を明示しないと文字化けすることがあります。日本語嫌い。
1行目はとりあえずレスポンスヘッダにも書いたほうがいいかなーとか思って付けました。必要性はわからないです
文字コードのお話
先ほどからちょくちょくでているUTF-8。今回の苦戦の1つ目になります。
PHPは基本的に文字コードはUTF-8で書くべきとされています。
Pythonの出力もutf-8で統一する必要があり、最初の頃はそこで詰まっていました。(Python側がShift-JISだった)
いざHerokuへDeploy!のはずがエラーの嵐
さあできた!デプロイして様子を見よう!とデプロイしてURLを開いてみると…
\\ 現在Herokuはリクエストを処理できません //
はい。ここでエラーです。デプロイには成功してるのにナンデ状態になりました。
結論から申し上げますと、Heroku上でPHPとPythonの両方を同時に動かす場合、2つのBuildPackが必要になります。
こんな感じで設定しましょう。今回はWebページがメインのため、順番はPHP->Pythonの順になります。
これで大丈夫だろう!こんどこそ!とデプロイしようとすると、
\\ Deploy failed //
うーんこの。今度は何・・・とlogを漁ると、以下のような内容がありました。
-----> App not compatible with buildpack: https://buildpack-registry.s3.amazonaws.com/buildpacks/heroku/python.tgz
More info: https://devcenter.heroku.com/articles/buildpacks#detection-failure
! Push failed
これを検索すると、Pythonアプリケーションのために必要となるファイルが無いとのこと。
それじゃあ作成しましょう。今回のPythonのコードに必要なものを詰めて以下のとおり:
# requirement.txt
beautifulsoup4==4.9.1
requests==2.24.0
# runtime.txt
python-3.7.7
これでデプロイするとうまく行きました。
完走した感想
文字コードとHerokuの環境構築に悩まされた一日を過ごしました。日本語嫌い。
ちなみにXAMPPでテスト環境を作ってみたらHerokuよりも文字コードに関して悩まされました。
今回はとりあえず表示に成功したのでよしとします。
参考資料
BuildPackが必要であることを知らされたサイト
https://stackoverflow.com/questions/12126439/run-python-and-php-in-a-single-heroku-app-procfile
PythonのHeroku上での実行環境を整えるために必要なファイルを知ったサイト
https://teratail.com/questions/258801
(密かに起きてたエラー対処に役立ったサイト)
デプロイ後にcode=H14 desc="No web processes running"
https://qiita.com/rebi/items/efd1c36f0a9e46222d80