Pythonに全く触れたことのない初心者が、とても簡単なWebアプリを作成した時の備忘録です。
Qiita初投稿です。いつもお世話になっております。
■アプリ概要
・ユーザーからの入力を受け付けるWebページを表示
・入力された書籍タイトルを元に、書籍APIの検索リクエスト(Google Books API)
・レスポンスから書籍サムネイルを表示
作成工程、その中でハマった所、解決方法を記載していきます。
—環境—
Mac OS
1.Pythonのインストール
Macはデフォルトで2.x系のPythonがインストールされています。
下記コマンドでインストールされているPythonのバージョンを確認。
$ python --version
Python 2.7.16
※ python -V でも同じ結果が得られます
Python 2.x系は2020年1月1日にサポート終了しています。
3.x系とのversionの違いで結構不整合が起きる + 今時2.x系を使用していると小学生にも鼻で笑われるらしいので、、、
最初に3.x系にアップデートします。
↓公式サイトから3.x系のパッケージをダウンロード
https://www.python.org/downloads/
Q1.ハマりポイント
インストールしたのにバージョンが2.x系のまま
python3 --version と確認すると3.x系になっている
$ python --version
Python 2.7.16
$ python3 --version
Python 3.7.7
A1.解決方法
1.brewコマンドでpyenvをインストール(読み方が分からず、心の中でぴえんって読んでる)
$ brew install pyenv
2.viエディタ等を使い~/.bash_profileに下記4行を追記
export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init -)"
export PATH="$HOME/.pyenv/shims:$PATH"
※viエディタはTerminalからファイルを編集できるコマンドです。
使い方が結構特殊ですが、Linuxのサーバー構築などでもよく使います。
https://prev.net-newbie.com/linux/commands/vi.html
$ vi ~/.bash_profile
# ~/.bash_profileを編集する
$ source ~/.bash_profile
3.pyenvを使いMac全体にpython3.x系を認識させる。
$ pyenv global 3.7.0
$ pyenv rehash
これで3.x系が使えるようになりました。
$ python --version
Python 3.7.7
2.フォルダ構成
プロジェクトのルートフォルダ直下に index.html と server.py と cgi-bin フォルダを配置。
cgi-bin フォルダ内に index.py を配置します。
project/
┝ ─ index.html
┝ ─ server.py
└ ─ cgi-bin/
└ ─ index.py
3.index.htmlの作成
今回はレイアウトも何も考えず、ただ文字列の入力を受け付けるだけのhtmlを作成します。
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<form method="POST" action="cgi-bin/index.py">
<label>取得図書画像タイトル:</label>
<br>
<input type="text" name="text">
<button type="submit">送信</button>
</form>
</body>
</html>
ザックリ説明すると、
<form>タグで囲まれている箇所に入力されたデータが、
<submit>契機で、cgi-bin/index.py にPOSTメソッドで送信される。
そんな感じです。
テキストボックスに入力されたデータが、[送信]ボタンを押すと、index.py に送信されます。
4.server.pyの作成
ローカルで検証用のサーバーを立てるために必要になります。
import http.server
http.server.test(HandlerClass=http.server.CGIHTTPRequestHandler)
Terminalで作成したPythonファイルを起動すると、ローカルサーバーが立ち上がります。
ローカルサーバーが立ち上がった状態で
http://0.0.0.0:8000/
にアクセスすると、先ほどのindex.htmlが表示されるはずです。
$ python server.py
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
※ちなみにローカルサーバーを中止するのは command + C です。
5.index.pyの作成
index.htmlから送信されたデータを使い、Google書籍検索APIのリクエストを送ります。
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import cgi # CGIモジュールのインポート
import cgitb
import sys
import requests
import json
# 書籍検索APIの雛形
api = "https://www.googleapis.com/books/v1/volumes?q={title}&maxResults=10&startIndex=0"
# デバッグに使うので、本番環境では記述しない
cgitb.enable()
# ユーザーが入力したフォームデータを取得する
form = cgi.FieldStorage()
# HTMLを記述するためのヘッダ
print("Content-Type: text/html; charset=UTF-8")
print("")
# フォームのデータが入力されていない場合
if "text" not in form:
print("<h1>Error!</h1>")
print("<br>")
print("テキストを入力してください!")
print("<a href='/'><button type='submit'>戻る</button></a>")
sys.exit() # index.pyの終了
text = form.getvalue("text") # テキストデータの値を取得する
url = api.format(title=text) # 書籍検索apiの検索単語となる{title}に入力テキストを当てはめる
response = requests.get(url) # リクエストを投げる
data = json.loads(response.text) # レスポンスをjson形式に変換
# レスポンスをhtmlに反映
print(data['items'][0]['volumeInfo']['title'])
print("<br>")
print("<img src=" + data['items'][0]['volumeInfo']['imageLinks']['thumbnail'] + ">")
print("<br>")
print("<a href='/'><button type='submit'>戻る</button></a>")
コメントでだいぶ補足してありますが、ザックリ説明します。
↓こちらがGoogle Books API のURLです。
https://www.googleapis.com/books/v1/volumes?q=いちご100&maxResults=10&startIndex=0
**q=**の後に検索したい書籍の名前を入れると、関連したレスポンスを返してくれます。
curlを使っても手軽に確認できます。
$ curl https://www.googleapis.com/books/v1/volumes?q=いちご100&maxResults=10&startIndex=0
"kind": "books#volumes",
"totalItems": 2836,
"items": [
{
"kind": "books#volume",
"id": "vWSUDwAAQBAJ",
"etag": "b/w9qaxsyy4",
"selfLink": "https://www.googleapis.com/books/v1/volumes/vWSUDwAAQBAJ",
"volumeInfo": {
"title": "いちご100% モノクロ版【期間限定無料】 2",
"authors": [
"河下水希"
],
"publisher": "集英社",
"publishedDate": "2002-10-04",
"description": "【春マン!! 期間限定無料!!/真中淳平が突如迷い込んだ恋の迷路! いちごパンツが導く超青春ラブコメディ!】※2019年5月8日までの期間限定無料お試し版です。2019年5月9日以降はご利用できなくなります。 西野と東城、二人の間で揺れる真中の気持ち。ホントに好きなのは西野? それとも東城? 勉強に全く身が入らないまま迎えた受験当日、いちご模様迷宮の入り口・幻の美少女が目の前に…!! どうする真中!?",
"industryIdentifiers": [
{
"type": "OTHER",
"identifier": "PKEY:088733268733043155P5"
}
],
"readingModes": {
"text": true,
"image": false
},
"pageCount": 188,
"printType": "BOOK",
"categories": [
"Comics & Graphic Novels"
],
"maturityRating": "NOT_MATURE",
"allowAnonLogging": false,
"contentVersion": "1.2.2.0.preview.2",
"panelizationSummary": {
"containsEpubBubbles": true,
"containsImageBubbles": true,
"epubBubbleVersion": "99b0fa95624a43e9_A",
"imageBubbleVersion": "99b0fa95624a43e9_A"
},
"imageLinks": {
"smallThumbnail": "http://books.google.com/books/content?id=vWSUDwAAQBAJ&printsec=frontcover&img=1&zoom=5&source=gbs_api",
"thumbnail": "http://books.google.com/books/content?id=vWSUDwAAQBAJ&printsec=frontcover&img=1&zoom=1&source=gbs_api"
},
"language": "ja",
"previewLink": "http://books.google.co.jp/books?id=vWSUDwAAQBAJ&dq=%E3%81%84%E3%81%A1%E3%81%94100&hl=&cd=1&source=gbs_api",
"infoLink": "http://books.google.co.jp/books?id=vWSUDwAAQBAJ&dq=%E3%81%84%E3%81%A1%E3%81%94100&hl=&source=gbs_api",
"canonicalVolumeLink": "https://books.google.com/books/about/%E3%81%84%E3%81%A1%E3%81%94100_%E3%83%A2%E3%83%8E%E3%82%AF%E3%83%AD%E7%89%88_%E6%9C%9F%E9%96%93%E9%99%90.html?hl=&id=vWSUDwAAQBAJ"
},
"saleInfo": {
"country": "JP",
"saleability": "NOT_FOR_SALE",
"isEbook": false
},
"accessInfo": {
"country": "JP",
"viewability": "NO_PAGES",
"embeddable": false,
"publicDomain": false,
"textToSpeechPermission": "ALLOWED",
"epub": {
"isAvailable": true
},
"pdf": {
"isAvailable": true
},
略------------------------------------------------------
responseには、上記のような長い応答が格納され、
dataにはresponseをJSON型に変換して格納します。
今回はその中から、[title]と[thumbnail]を使いたいので、
data['items'][0]['volumeInfo']['title']
data['items'][0]['volumeInfo']['imageLinks']['thumbnail']
のようにアクセスし、必要となるデータを取り出します。
[0]の値を[1][2]と変更することによって、
取り出す検索結果対象を変更することができます。
↓↓↓
完成○△□
Q2.ハマりポイント
送信ボタンを押下すると、
FileNotFoundError: [Errno 2] No such file or directory: '/Users/hoge/project/cgi-bin/index.py'
とエラーが表示され、検索結果が表示されない
A2.解決方法
/Users/hoge/project/cgi-bin/index.py は存在していた。
index.py の1行目が誤っていた
× #!usr/bin/env python3
○ #!/usr/bin/env python3
Q3.requestsがインポートできない
import requests
の箇所でエラーが起きてしまう
A3.解決方法
こちらの記事が大変参考になりました。
https://qiita.com/Kent_recuca/items/349586e9c034535f2991
Pythonのsys.pathに
requestsがインストールされたパスを追記することで解決
総括
以前SpringBootを用いてWebアプリを作成したことがありましたが、
それに比べフォルダ構成、環境構築が楽ですぐに動かせるという所感です。
機械学習分野に使われていることは知っていましたが、Web環境でも使用されていることに驚きました。
Pythonに初めて触れたので、
コメントであるはずの#の後ろでなぜエラーが起きるのか、
ローカルサーバーを立ち上げると、なぜindex.htmlが表示されるのか、
まだまだ謎だらけですが、これからお勉強して理解を深めていきたいと思います。