AWS lambda layer で仮想環境を構築したった

# Background
Python3.6 以降で`venv`を使ってpipしたパッケージを保存していたのですが、AWS上で出来ないかと調べているとlayerという手頃な機能があったので使ってみた。


# venv 

作業PC上ではこれでOK

```shell
python -m venv [仮想環境名]

./[仮想環境名]/bin/activate
([仮想環境名]) pip install [パッケージ名]
```

# パッケージ用のzip作成
[AWS lambda を使ってWebスクレイピングしたった-Development (Webスクレイピング)](https://qiita.com/satsukiya/items/b9d02abd7fa96cd59355#development-web%E3%82%B9%E3%82%AF%E3%83%AC%E3%82%A4%E3%83%94%E3%83%B3%E3%82%B0)と同様にAWS上にuploadするためにzipファイルを作ります。

```shell
mkdir packages
cd packages
pip install [パッケージ] -t ./
pip install [パッケージ] -t ./
......
zip -r ./myDeploymentPackage.zip ./packages
```

#Layer
pip環境を作成するにはLayerを作成します。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/288206/efb96392-6043-093b-961a-70a564eb04dd.png" width="75%">
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/288206/c4c77475-69c2-1015-a09b-be0894f75edb.png" width="75%">

# Development (error)

ここで[AWS lambda を使ってWebスクレイピングしたった-Development (Webスクレイピング)](https://qiita.com/satsukiya/items/b9d02abd7fa96cd59355#development-web%E3%82%B9%E3%82%AF%E3%83%AC%E3%82%A4%E3%83%94%E3%83%B3%E3%82%B0)でbeautifulsoupを使ったコードを書いてみます。

```Python
import json
import requests
from bs4 import BeautifulSoup

def lambda_handler(event, context):
    # TODO implement

    response = requests.get('https://mainichi.jp/editorial/')
    soup = BeautifulSoup(response.text)
    pages = soup.find("ul", class_="list-typeD")
    articles = pages.find_all("article")
    links = [ "https:" + a.a.get("href") for a in articles]

    return {
        'statusCode': 200,
        'links' : links
    }
```

とすると、

```
{
  "errorMessage": "Unable to import module 'lambda_function'"
}
```

importエラーが出てしまいます。

[Lambda@Pythonのレイヤーを使う際の基本的な注意点（レイヤーに上げたファイルがimport出来ない人向け）-注意点](https://qiita.com/k_hoso/items/78beb33e53abfdddabe7#%E6%B3%A8%E6%84%8F%E7%82%B9)
を見ると、zipファイルは `/opt/` 配下に解凍されるみたいです。

この場合だと、`/opt/packages/`に作業用PCにpipでインストールしたパッケージがあるので、

```Python
import sys
sys.path.append('/opt/packages')
```

にして事前にパスを通しておく必要があります。

# Development (modified)

```Python
import sys
sys.path.append('/opt/packages')
import json
import requests
from bs4 import BeautifulSoup


def lambda_handler(event, context):
    # TODO implement

    response = requests.get('https://mainichi.jp/editorial/')
    soup = BeautifulSoup(response.text)
    pages = soup.find("ul", class_="list-typeD")
    articles = pages.find_all("article")
    links = [ "https:" + a.a.get("href") for a in articles]

    return {
        'statusCode': 200,
        'links' : links
    }
```

```json
{
  "statusCode": 200,
  "links": [
    "https://mainichi.jp/articles/20201120/ddm/005/070/067000c",
    "https://mainichi.jp/articles/20201120/ddm/005/070/065000c",
    "https://mainichi.jp/articles/20201119/ddm/005/070/119000c",
    "https://mainichi.jp/articles/20201119/ddm/005/070/118000c",
    "https://mainichi.jp/articles/20201118/ddm/005/070/115000c",
    "https://mainichi.jp/articles/20201118/ddm/005/070/114000c",
    "https://mainichi.jp/articles/20201117/ddm/005/070/114000c",
    "https://mainichi.jp/articles/20201117/ddm/005/070/113000c",
    "https://mainichi.jp/articles/20201116/ddm/005/070/043000c"
  ]
}
```

# Post Scripting
zipで圧縮するときに"/packages/"なしでできればいいんすけどね:expressionless: