PythonからIrvineを使ってファイルをダウンロードする

# 目的

Pythonから、ダウンローダーである[Irvine](https://forest.watch.impress.co.jp/library/software/irvine/)を使ってファイルをダウンロードする。

# 背景

Pythonのrequetsで、ファイルダウンロードしていたら、いろんな種類のエラーにからまれた。
ダウンロードは、ダウンローダーにお願いしたい。

# 環境

- Windows11 バージョン22H2(OSビルド22621.963)
 - Python3.9.1
 - Irvine 1.3.0.126 & DMScript 0.3.12

# Irvineのセットアップ

- [窓の杜 Irvine](https://forest.watch.impress.co.jp/library/software/irvine/)をダウンロードしてきて、インストールする（irvine.exeのパスは「c:\Program1\irvine1_3_0\irvine.exe」とする）
- [Irvineの設定](https://w.atwiki.jp/irvinewiki/pages/32.html)を参考に設定する
    - 特に重要なのはUser-Agentぐらいだと思う

# ダウンロードが終了したらIrvineを閉じる設定
- irvineを起動する
- メニューの[ツール]-[オプション設定]を選ぶ
- [スクリプト]タブを選び、[新規作成]ボタンをクリックする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201344/2e87aa67-8460-2ad1-9147-4065da930ce0.png)
- [オプション設定]が選択された状態で、[次へ]ボタンをクリックする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201344/2bdaf3bb-89f0-e47e-39c7-a46ce4d68035.png)
- イベントの[OnDeactivateQueue]を選び、[次へ]ボタンをクリックする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201344/33ed3fdb-cccb-1960-040b-741563bc24a7.png)
- [ファイル名(拡張子は不要です)]に、[doneclose]を入力する
- [キャプション]に、[すべて終了時にIrvineを終了]を入力する
- [完了]ボタンをクリックする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201344/7d7035ed-70b9-edc1-0eb2-530efa84e2bd.png)
- notepadで編集中になるので、以下の内容に書き換える(末尾の参考ブログから転記、guidは作者のguidをそのまま使用しても問題ないと思う)
```doneclose.dms
/*
スクリプト初期化データ
guid={3FD7CA4D-BB58-4E4E-B1EF-E66AA72E9685}
caption=全て終了時にIrvineを終了
version=0
hint=
event=OnDeactivateQueue
match=
author=
synchronize=0
*/

function OnDeactivateQueue(irvine){
//すべてのダウンロード終了イベント
irvine.ExecuteAction('actFileClose');
}
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201344/16fea6a0-b1da-fad1-ce35-4d80e123a645.png)
- notepadを保存して閉じる
- [オプション設定]の[更新]ボタンをクリックする
- [スクリプト]タブのイベント[OnDeactivateQueue]にキャプション[すべて終了時にIrvineを終了]が増えているので、チェックONする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201344/3dc042c1-7d0c-1565-a6b5-f691e547f046.png)

# 使い方

- [Git](https://github.com/igapon50/training/releases/tag/1.8.0)からSource code(zip)をダウンロードして、展開する
- 展開したパスが「c:\Git\traning\」とすると、「C:\Git\traning\python\Web_scraping\irvineHelper.py」にIrvineHelperクラスがある
- 「irvineHelper.py」ファイルを好きな場所にコピーして使う
- 以下のコードを実行すると、Irvineが起動して、画像を2つダウンロードする設定が行われる
```python:サンプルコード
from irvineHelper import *
# テスト画像のURL
image_url_list = [
    'https://・・・/画像1.png',
    'https://・・・/画像2.png',
    ]
test_target = IrvineHelper(image_url_list)
test_target.download()
```
- 注意としては、Irvineを起動したときに、選択されているフォルダがゴミ箱にならないようにすること
    - ゴミ箱が選択されていると、ゴミ箱にダウンロードファイルが設定される

# コードの説明
- クラスやメソッドの説明はdocstringを参照(以下はPyCharmでIrvineHelperクラスを表示した例)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201344/61d40961-e70f-c8e2-98d9-6821b57a2f57.png)
- IrvineHelperクラスのインスタンスを作るときに、list_pathのファイルにURLリストが書き込まれる(1レコードは20フィールドでタブ区切り)
```python:irvineHelper.py 128行目～143行目
        elif isinstance(value_object, list):
            value_object = copy.deepcopy(value_object)
            download_file_name_list = copy.deepcopy(download_file_name_list)
            with open(list_path, 'w', encoding='utf-8') as work_file:
                buff = ''
                for absolute_path, file_name in zip_longest(value_object, download_file_name_list):
                    buff += absolute_path + '\t'
                    if download_path:
                        buff += download_path
                    buff += '\t'
                    if file_name:
                        buff += file_name
                    buff += '\t' * 17
                    buff += '\n'
                work_file.write(buff)
            self.value_object = IrvineHelperValue(exe_path, list_path)
```
- コマンドラインでlist_pathを引数にしてIrvineを起動する
```python:irvineHelper.py 148行目～159行目
    def download(self):
        """
        irvineを起動して、終了されるのを待つ
        :return:
        """
        cmd = self.value_object.exe_path
        cmd += ' '
        cmd += self.value_object.list_path
        proc = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE)
        self.running = True
        proc.wait()
        self.running = False
```
- 起動したIrvineにlist_pathのURLリストが読み込まれてダウンロードが始まる
- Irvineが終了するとPythonに処理が戻る
- list_pathは、初期値が以下になっている
```python:irvineHelper.py 79行目
    list_path: str = r'./irvine_download_list.txt'
```

# おわりに
URLがわかっているのに、requetsでダウンロードできない時に、使えるかもしれません。

試していないので、URLにDataURIが混ざると、どうなるかわかりません。
IrvineにDataURIを設定できなかったので、たぶんDataURIは無視されると思います。

# 関連リンク

## 参考サイト
- [窓の杜 Irvine](https://forest.watch.impress.co.jp/library/software/irvine/)
- Irvine Uploader
    - https://u1.getuploader.com/irvn/
- Irvine Part36スレ
    - https://mevius.5ch.net/test/read.cgi/win/1545612410

## ドキュメント
- Irvine公式
    - http://hp.vector.co.jp/authors/VA024591/
- Irvineマニュアル
    - http://hp.vector.co.jp/authors/VA024591/doc/manual.html
- IrvineまとめWiki
    - https://w.atwiki.jp/irvinewiki/
- Irvineの設定
    - https://w.atwiki.jp/irvinewiki/pages/32.html