【Python】Excelに書かれたURLから動画をダウンロードしたい

#はじめに
Pyhtonを使ってExcelに書かれたURLから動画をダウンロードするツールを作ったので、せっかくなので記事としてまとめることにしました。
PythonはおろかIT初心者が書いた記事ですが、何かの助けになれば幸いです。

#作ったもの

|ファイル名|URL|
|:---:|:---:|
|動画1.mp4|http://example.com/sample1.mp4|
|動画2.mp4|http://example.com/sample2.mp4|
|:|:|

このような形式のエクセルから、リンク先の動画をファイル名に書かれた名前で保存する。

#環境
MacBook Pro (M1, 2020)
macOS Big Sur 11.6.1
Python 3.9.7

#ソースコード

```python:download.py
import requests
from openpyxl import load_workbook
from pathlib import Path
from tqdm import tqdm

# Excelファイルのロード
excel_path='sample.xlsx'
workbook = load_workbook(filename=excel_path, read_only=True)

# シートのロード
sheet = workbook['sheet1']

# ダウンロードを始める行を設定
start_row = 2

# 繰り返しの処理
for row in range(start_row, sheet.max_row + 1):
  
  # ファイル名作成
  file_name = sheet[f'A{row}'].value

  # URLを変数に格納
  url = sheet[f'B{row}'].value

  # ファイルサイズ取得
  file_size = int(requests.head(url).headers["content-length"])

  # 出力フォルダ作成
  output_folder = Path('download')
  output_folder.mkdir(exist_ok=True)

  # ダウンロード中のファイル表示
  row_num = sheet[f'A{row}'].row
  print(f'{row - (start_row-1)}/{sheet.max_row - (start_row-1)}_{row_num}行目_{file_name}')

  # ダウンロード
  response = requests.get(url)
  pbar = tqdm(total=file_size, unit="B", unit_scale=True)
  with open(output_folder/file_name, "wb") as saveFile:
    for chunk in response.iter_content(chunk_size=1):
        saveFile.write(chunk)
        pbar.update(len(chunk))
    pbar.close()

# ロードしたExcelファイルを閉じる
workbook.close()
```

#ざっくり解説

###1. 特定のセルからデータ取得
```python
from openpyxl import load_workbook

# Excelファイルのロード
excel_path='sample.xlsx'
workbook = load_workbook(filename=excel_path, read_only=True)

# シートのロード
sheet = workbook['sheet1']
```

エクセルの読み込みには、load_workbook(ファイルパス)を使用します。
読み込んだエクセルを変数に入れ、シート名を指定することでワークシートを抜き出します。

###2. ダウンロード開始行を設定
```python
# ダウンロードを始める行を設定
start_row = 2
```

|ファイル名|URL|
|:---:|:---:|
|動画1.mp4|http://example.com/sample1.mp4|
|動画2.mp4|http://example.com/sample2.mp4|
|:|:|

今回はこのような形のエクセルを用いたので２行目からダウンロードを開始します。

###3. for文
```python
# 繰り返しの処理
for row in range(start_row, sheet.max_row + 1):
```

先ほど設定したstart_rowから最後の行まで繰り返します。

###4. ダウンロードの下準備
```python
  # ファイル名作成
  file_name = sheet[f'A{row}'].value

  # URLを変数に格納
  url = sheet[f'B{row}'].value

  # ファイルサイズ取得
  file_size = int(requests.head(url).headers["content-length"])

  # 出力フォルダ作成
  output_folder = Path('download')
  output_folder.mkdir(exist_ok=True)
```

sheet[f'A{row}'].valueでA列からファイル名を、sheet[f'B{row}'].valueでB列からURLを抜き出し、それぞれ変数に入れます。
ファイルサイズの取得については、ダウンロード時に進捗情報を表示する際に必要となるので、進捗表示機能が必要ない場合は省略可です。
ダウンロードした動画を入れるdownloadフォルダを作成します。

###5. ダウンロード中のファイル表示

```python
  # ダウンロード中のファイル表示
  row_num = sheet[f'A{row}'].row
  print(f'{row - (start_row-1)}/{sheet.max_row - (start_row-1)}_{row_num}行目_{file_name}')
```
![スクリーンショット 2021-11-22 17.22.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1967086/5f1353e9-96ca-e82a-5a8f-c23ec3642417.png)
このような表示を出すだけなので、こちらも必要に応じてです。もっといい書き方もあると思うので自由にアレンジしてください。

###6. 動画をDLする

```python
  # ダウンロード
  response = requests.get(url)
  pbar = tqdm(total=file_size, unit="B", unit_scale=True)
  with open(output_folder/file_name, "wb") as saveFile:
    for chunk in response.iter_content(chunk_size=1):
        saveFile.write(chunk)
        pbar.update(len(chunk))
    pbar.close()
```

このようにプログレスバーを表示させることに成功しました。
ダウンロードの進捗状況が一目でわかるので便利です。
![ダウンロード.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1967086/a7b13619-4df0-b889-2afa-ff18fbdca8b1.gif)

進捗表示がいらないという方は

```python:進捗表示がないバージョン
import requests
from openpyxl import load_workbook
from pathlib import Path

# Excelファイルのロード(読み取り専用)
excel_path='対象講座.xlsx'
workbook = load_workbook(filename=excel_path, read_only=True)

# シートのロード
sheet1 = workbook['対象講座']

# ダウンロードを始める行を設定
start_row = 3

# 繰り返しの処理
for row in range(start_row, sheet1.max_row + 1):
  
  # ファイル名作成
  file_name = sheet1[f'B{row}'].value

  # URLを変数に格納
  url = sheet1[f'C{row}'].value

  # 出力フォルダ作成
  output_folder = Path('download')
  output_folder.mkdir(exist_ok=True)

  # ダウンロード中のファイル表示
  row_num = sheet1[f'B{row}'].row
  print(f'{row - (start_row-1)}/{sheet1.max_row - (start_row-1)}_{row_num}行目_{file_name}')

  # ダウンロード
  response = requests.get(url)
  movie = response.content
  with open(output_folder/file_name, "wb") as saveFile:
    saveFile.write(movie)

# ロードしたExcelファイルを閉じる
workbook.close()
```

このように書けばOKです。