作成したスクレイピングツールをHTTPで呼び出したかった

### 前回までのあらすじ
[前回の記事](https://qiita.com/zeeksan/items/934f3dd62c894520ef96) 
メルカリのスクレイピングツールはできたけど、
ローカル環境でコマンド実行するだけなのはちょっともったいない。
なので今回は、対象URLをURLパラメータとして付与して、 
ブラウザからWebサーバ(Apache)にリクエストを投げたら
実行結果が表示されるように改修とか環境構築とかやってみたよ。

### やらなきゃいけないこと

 1. サーバの用意
  - 初期設定
  - firewalld、SELinuxの無効化

 1. 諸々インストール 
  - Python3
  - google-chrome
  - Apache(httpd)

 1. 資材配置 
  - httpd.confの確認、必要に応じて修正
  - 作成資材を規定の場所に配置

 1. 実行結果確認 
  - ツール修正
  - ローカルPCから接続確認  
 ※セキュリティ的な点は全く考えてないので、必要に応じて対策してね。

#### 1.環境構築
サーバは[VMWare Workstation](https://customerconnect.vmware.com/en/downloads/info/slug/desktop_end_user_computing/vmware_workstation_player/16_0)上に、CentOS8を用意。
初期ユーザとかrootパスワードとか作って
firewalldとSELinuxを無効化して準備完了。
ちょっと久々すぎてココを忘れてしばらく詰まった…( ˘ω˘ )

#### 2.諸々インストール
yumリポジトリをアップグレードしたら、環境整備。
実行環境はpython Version3.x、
Apacheで待ち受けてリクエストが来たら[chromedriver](https://chromedriver.chromium.org/downloads)使って実行する感じで。
Apacheならば、特に何の設定もなくPythonツールを動かせるので便利。
ChromeってCLI環境のLinuxでも入るんですね～…

```:諸々インストールしたりサービス起動したり
# yum update

↓必要なパッケージのインストール
# yum install python3
# yum install google-chrome
# yum install httpd

↓スタートアップ起動有効化したりサービス起動したり。
# systemctl enable httpd
# systemctl start httpd
```

#### 3. 資材配置
作成したツールを実行するにはcgi-binディレクトリ配下で
そのツールが実行権限を持ってる必要があるので、
サーバにアップロードしたら、所定の場所に配置して権限変更。
デフォルトのcgi-binディレクトリはconf/httpd.confを参照
よほど変な入れ方していなければ大丈夫だろうけど無ければ追記。

```:conf/httpd.conf
<IfModule alias_module>
    ScriptAlias /cgi-bin/ "/var/www/cgi-bin/"
</IfModule>
```

```:資材配置
# mv <作成ツール> /var/www/cgi-bin/
# chmod 755 /var/www/cgi-bin/<作成ツール>
```

ツールの配置場所と同じところにchromedriverも一緒に置いておく。

#### 4. 実行結果確認  
まずは、Linux環境上でちゃんと動くことを確認しておく

```:とりあえず確認
# python3 /var/www/cgi-bin/<作成ツール> <スクレイピング対象URL>
```
何も考えなくてもとりあえずは動くはず。
しかしブラウザからは↑のようなコマンドは叩けないので、
URLパラメータから取得する仕組みを組み込んであげる必要がある。

```python:作成ツールの上から変更点
# ～↓リクエストを受けたときPythonで実行するように指定～
#!/usr/bin/env python3

# ～↓cgiをインポート～
import cgi
import cgitb
cgitb.enable()

# ～↓文字コード注意～
print("Content-Type: text/html; charset=UTF-8\n\n")
print("")

def getMercari(argURL):
# ～↓chromedriverはツールと同じところに配置しておく。違うところに置く場合はパスに注意して指定する。～
    browser = webdriver.Chrome('./chromedriver',options=options)

# ～getMercari関数終わり。特に変更点っぽいところはない～


def main():
# ～主な変更点：URLパラメータからスクレイピング対象URLを取得～
    argURL = cgi.FieldStorage()
    getMercari(argURL=argURL["url"].value)
    print("done!")

if __name__ =='__main__':
    main()
```

main関数において、FieldStorage()関数を使って
URLパラメータ(URLの?以降に並んでいる文字列)を取得している。
参考：[cgi --- CGI (ゲートウェイインターフェース規格) のサポート](https://docs.python.org/ja/3/library/cgi.html?highlight=cgi%20fieldstorage)

この関数によって取得される値は下記URL例でそのままリクエストすると、
変なところでぶつ切りにされてしまう。
※別の検証用コードを使って実行結果を確認しておく。

```:URLパラメータ確認(とりあえずそのまま突っ込む)
http://<サーバIP>/cgi-bin/<作成ツール>?url=https://jp.mercari.com/search?status=on_sale&page=1&t1_category_id=5&category_id=5
↓
FieldStorage(None, None, [MiniFieldStorage('url', 'https://jp.mercari.com/search?status=on_sale'), 
MiniFieldStorage('page', '1'), 
MiniFieldStorage('t1_category_id', '5'), 
MiniFieldStorage('category_id', '5')])
```
Key-Valueでつながってるから、単純にURLパラメータとして取得して
それぞればらばらに処理したいならなんか大丈夫そうだけど、
文字列自体をそのまま使いたい今回の趣旨にはちょっとそぐわない。

そこでURLエンコード。今回はそこを自動化する必要はないので
Google先生のおチカラを借りることにして、サクっと変換する。
参考：[URLエンコード・デコード](https://tech-unlimited.com/urlencode.html)

日本語URLを扱うときには便利どころか、
アドレスバーでよく使われる記号も変換した文字列として返してくれるので便利。
そこも頼ることができないシチュエーションだとすると…
一覧から取得してエンコードして実行も自動化…みたいなシーンなら
別途調べる必要がありそうなので、次回Updateするなら今度はその辺ですかね…？

```:URLパラメータ確認(エンコード実施)
http://<サーバIP>/cgi-bin/<作成ツール>?url=https%3A%2F%2Fjp.mercari.com%2Fsearch%3Fstatus%3Don_sale%26page%3D1%26t1_category_id%3D5%26category_id%3D5
↓
FieldStorage(None, None, [MiniFieldStorage('url', 'https://jp.mercari.com/search?status=on_sale&page=1&t1_category_id=5&category_id=5')])
```
Key-Valueのセットが一つになった！
…でもって、次の行のスクレイピング関数にそいつを引数として渡せば
あとは実行結果の一覧がブラウザに表示される。
↑のルールに従って変換できていればCurlでも
呼べるっぽいからとりあえず大丈夫そうですかね。

そんなこんなで、今回のところはこれにて。
今まで点々とばらけていた知識が線になっていくところがなんだか楽しいですね。