DockerでJupyter notebookインストール

# 概要
スクレイピングやRPA学習のためにJupyter labをインストールしたときのメモ。

# 環境構築
## 動作環境

```
$ uname -a ; docker --version                    
Darwin uni.local 20.6.0 Darwin Kernel Version 20.6.0: Wed Jun 23 00:26:31 PDT 2021; root:xnu-7195.141.2~5/RELEASE_X86_64 x86_64
Docker version 20.10.13, build a224086
```

## Dockerイメージ
コンテナでポートフォワーディング & 作業ディレクトリをマウントでローカルから操作できるようになる。
コンテナイメージは[Jupyter Docker Stacks](https://jupyter-docker-stacks.readthedocs.io/en/latest/index.html)に複数あるので自分に合ったものを。
個人用だと[jupyter/scipy-notebook/](https://hub.docker.com/r/jupyter/scipy-notebook/)で十分らしいのでこれを使う。

```:イメージ取得 & 確認
$ docker pull jupyter/scipy-notebook
$ docker images
```

```:コンテナ作成
$ docker run -d -v 
"Path":/home/jovyan/work
-e NB_GID=100 
-e GEN_CERT=yes
-e GRANT_SUDO=yes
--user root
-p 8888:8888 jupyter/scipy-notebook start-notebook.sh 
--NotebookApp.token='' 
```

:::note warn
デフォルトのJovyanユーザはsudo権限がないのでsudoを使いたい場合は下記オプションでビルドする
ansibleも使いたかったけど sshpass がないと動かなかったので root で再ビルドした。

-e GRANT_SUDO=yes
--user root
:::

- Jupyter notebookにブラウザでログイン時にトークンが必要になるので、ターミナルで出力されるトークンをコピーしておく
- コンテナ起動時のディレクトリをマウントするので、作業ディレクトリに移動してから起動する

## Jupyterコンフィグ設定（任意）
IP、ポート、トークン、作業ディレクトリなど指定できる


```:コンフィグファイル作成
$ jupyter notebook --generate-config
```
ファイル（~/.jupyter/jupyter_notebook_config.py）は全てコメントアウトされている雛形になるので好きな部分のコメントを外して設定する

token無しの場合は '' で設定する（非推奨）

```:jupyter_notebook_config.py
c = get_config()
c.NotebookApp.ip = '0.0.0.0'
c.NotebookApp.open_browser = False
c.NotebookApp.port = 8080
c.NotebookApp.token = ''
c.NotebookApp.password = u'sha1:xxxx'
```

パスワードはSHA1のハッシュ値になるので下記コマンドで出力されるハッシュ値を入れる
```:ハッシュ値取得
$ python -c "import IPython;print(IPython.lib.passwd())"
```

## Jupyter起動

```:Jupyter起動
# ノートブック起動
$ jupyter notebook

# ラボ起動（インストール必要）
$ jupyter lab
```

起動するとこんな感じ
右の新規からノートを作っていく
pythonを選択すると .ipynb の拡張子ファイルで作られる
![スクリーンショット 2022-04-04 17.58.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/445177/6f675265-c8a0-25fa-0924-32e49fb00e30.png)

それっぽい画面に遷移する
![スクリーンショット 2022-04-04 17.59.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/445177/690dbdf2-121a-995f-4812-3fa69b92c210.png)


# Python実行
## コード入力
スクレイピング学習で作ったスクリプトを入力して動作を確認
変数に指定した年度の住みたい街ランキング情報をCSV出力する

```python:test.py
year = '2019'
# 例) year = '2020'

import requests
from bs4 import BeautifulSoup

# 変数設定
err_msg1 = 'error'
url = xxxxxx
res = requests.get(url)
soup = BeautifulSoup(res.text, 'html.parser')

rank_list = soup.find_all(attrs={'class': 'matrixdatabox'})[0]
item_list = []
for item in rank_list.select('tr'):
    if '順位' in item.text:
        continue

    item = item.text.replace('\n', ',')
    columns = item.split(',')
    rank = int(columns[1].replace('位', ''))
    name = columns[2]
    point = int(columns[3].replace(' ', ''))
    
    
    _item_list = rank, name, point
    item_list.append(_item_list)

import pandas as pd
df = pd.DataFrame(item_list)
df.columns=['順位','駅名（代表的な沿線名）','得点']
df.to_csv(f'./csv/{year}年_住みたい街ランキング.csv', index=False)
```

マークダウンは一般的な書き方だけどnoteとかは入らない
処理単体で出力結果が出るので分かりやすい

![スクリーンショット 2022-04-06 12.09.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/445177/562b06e0-684a-f78f-082f-3e9bf55541b0.png)
![スクリーンショット 2022-04-06 12.10.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/445177/cc782b15-a3e1-ea38-cc9f-0cbc660435c5.png)