seleniumライブラリを含めて、pyinstallerでEXE化する (軽量版)(Selenium 4で記載) 

## はじめに
本記事では、seleniumライブラリを含めて、pyinstallerでEXE化します。(Selenium 4で記載)
本記事の方法で、10MBbyteくらいにEXE化後のファイルサイズを小さくすることが可能です。

ただし、EXEにはChromeブラウザーは含めないため、
EXE化ツール実行環境ではChromeブラウザーのインストールが必要になります。

`ChromeDriver`は`webdriver-manager`ライブラリによってChromeブラウザーバージョンにあったものを自動取得します。

## 環境
* Windows OS : 21H2(OSビルド 19044.1826) (64bit)
* Python Version : Python 3.10.5
* Chrome : 103.0.5060.134

## プロジェクト構成

```
　project
　　|
　　|-main.py
　　|-selenium-automation.spec
```

## 手順
仮想環境上で`pip install`を行い、最小のライブラリ構成でEXE化します。以下、手順。

1. 仮想環境を作成して、仮想環境上で`pip install`により、必要なライブラリを取得します
    - `python -m venv .venv`
1. 以下のコマンドを実行して、`selenium-automation.spec`ファイルを生成します
    * pyinstaller main.py --onefile --noconsole --name selenium-automation
1. specファイルのAnalysisのhiddenimports`を編集します
    * `hiddenimports=["selenium", "webdriver-manager"],`
1. プロジェクトに`dist`フォルダー、`build`フォルダーがあれば削除します
    * この後のEXE化コマンドが失敗することがあるため
1. EXE化コマンドで実行します。
    * pyinstaller --clean selenium-automation.spec
1. EXE化コマンドで`dist`フォルダー内に`selenium-automation.exe`が作成されるので実行
1. Chromeブラウザーが自動起動された後、Qiitaのページに遷移後は、Stack Overflowのぺージに遷移して、ブラウザーが自動終了する

## ソースコード (main.py)
`main.py`ファイルの内容を以下に記載しました。

proxyがある場合は、proxyを通す設定が必要になります。
proxyを通して、実行する場合は以下のコメントを外してください。

```
    # PROXY_IP_ADDRESS_AND_PORT = "http://XXX.XXX.XXX.XXX:XXXX"    # 例 : "http://192.168.0.100:8080"
    # set_os_proxy_setting(PROXY_IP_ADDRESS_AND_PORT)
    # PROXY_AUTH = '{userid}:{password}'
    # options.add_argument(f"--proxy-server={PROXY_IP_ADDRESS_AND_PORT}")
    # options.add_argument(f"--proxy-auth={PROXY_AUTH}")
```

``` python
import os
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
import time

def set_os_proxy_setting(proxy_server : str):
    # スクリプト内で環境変数をセットする
    os.environ["http_proxy"] = proxy_server
    os.environ["https_proxy"] = proxy_server
    os.environ["no_proxy"] = 'localhost,127.0.0.1'
    
    
def main():
    # WebDriver のオプションを設定する
    # https://qiita.com/skimhiro/items/de501f45607d6a09cde5
    options = webdriver.ChromeOptions()
    options.add_argument("--no-sandbox")
    options.add_argument("--disable-gpu")
    options.add_argument("--ignore-certificate-errors")
    options.add_argument("--start-maximized")
    options.add_experimental_option('excludeSwitches', ['enable-logging'])

    # Selenium Chrome Proxy の設定
    # PROXY_IP_ADDRESS_AND_PORT = "http://XXX.XXX.XXX.XXX:XXXX"    # 例 : "http://192.168.0.100:8080"
    # set_os_proxy_setting(PROXY_IP_ADDRESS_AND_PORT)
    # PROXY_AUTH = '{userid}:{password}'
    # options.add_argument(f"--proxy-server={PROXY_IP_ADDRESS_AND_PORT}")
    # options.add_argument(f"--proxy-auth={PROXY_AUTH}")
    
    # driverを生成する
    service=Service(ChromeDriverManager().install())
    driver = webdriver.Chrome(service=service, options=options)

    # スクレイピングを実行する
    driver.get("https://qiita.com/")
    time.sleep(3)

    driver.get("https://stackoverflow.com/")
    time.sleep(3)
    
    driver.close()
    driver.quit()

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

## specファイル (selenium-automation.spec)

```
# -*- mode: python ; coding: utf-8 -*-


block_cipher = None


a = Analysis(
    ['main.py'],
    pathex=[],
    binaries=[],
    datas=[],
    hiddenimports=["selenium", "webdriver-manager"],
    hookspath=[],
    hooksconfig={},
    runtime_hooks=[],
    excludes=[],
    win_no_prefer_redirects=False,
    win_private_assemblies=False,
    cipher=block_cipher,
    noarchive=False,
)
pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher)

exe = EXE(
    pyz,
    a.scripts,
    a.binaries,
    a.zipfiles,
    a.datas,
    [],
    name='selenium-automation',
    debug=False,
    bootloader_ignore_signals=False,
    strip=False,
    upx=True,
    upx_exclude=[],
    runtime_tmpdir=None,
    console=False,
    disable_windowed_traceback=False,
    argv_emulation=False,
    target_arch=None,
    codesign_identity=None,
    entitlements_file=None,
)
```

## 参考リンク
* [Selenium公式](https://www.selenium.dev/)
* [Selenium 4 の新機能・変更点まとめ](https://zenn.dev/miyajan/articles/whats-new-in-selenium-4)
* [Seleniumライブラリを含めて、pyinstallerでEXE化する](https://qiita.com/WestRiver/items/ce9995161067dc0d75d6)