【プログラムの制作過程】複数の動画をyoutubeから自動で取得

この記事は、python初心者が初めて動画を取得し保存する
プログラムを作ったので、どのような制作過程を経て行ったか
淡々と書いていったものになります。

似たようなプログラムをごろごろと転がっていますが、
どのように調べ、どのように実装していったか
自身の成長記録みたいな感じでこの記事を書いていきます。

#※注意
youtubeのダウンロードは自己責任でお願いいたします。

.

.

.

#制作イメージ
キーワード（検索ワード）を元に、その動画を指定した数だけ取得。
動画をダウンロードして、キーワード（検索ワード）の名前でフォルダを作成。
そのフォルダに動画を保存していきます。

#環境
OS : Big Sur 11.2.3
conda version : 4.8.3
python version : 3.8.3
Jupyter Notebook

#実装
制作イメージにある機能要件を満たすために、
一気に作り込まず、**調べて実装できそうなところから**
進めていきました。

.
また、調べ方、検索の方法として、
**なるべく最新の記事の情報を参考にしました。**

理由は、使うバージョンや環境が異なっていると、
なんか面倒くさそうだからです。

.
サクサクと実装できて、エラーでつまづく時間は最小にしたいので、
こんな感じのマイルールを設けていました。


###youtube動画のキーワード検索を自動化
サンプルコードをそのままコピペして実行できれば、楽ちんなので
コピペして動かせそうなものを探しました。
調べた記事で最も参考になったのが下記の記事です。

参考記事：[Python+APIでYouTube動画を自動検索。ダウンロードも？](https://kodocode.net/python-youtube-download/)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628696/de8164e3-5da0-efa0-3da2-698be5226e90.png)
￼
Google APIキーの取得も必要なので、記事を参考に進めていけば、
サンプル通りに動画のタイトルとURLを取得できました。

###youtubeから動画をダウンロード
取得したURLをもとに動画をダウンロードできないか調べました。
参考記事：[動画をダウンロードしてみる（Python）youtube-dl
](http://blog1.tela.daa.jp/?eid=136)

下記のソースを先程のソースに加えて、
取得したURLの動画をダウンロードできないか試しました。

```python
from __future__ import unicode_literals
import youtube_dl

ydl_opts = {}
with youtube_dl.YoutubeDL(ydl_opts) as ydl:
    ydl.download(['https://www.youtube.com/watch?v=BaW_jenozKc'])
```

.
合体させたソースがこちら
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628696/502cc50a-e207-2c2b-64ff-9f8ae551d904.png)
￼
インポートするモジュールを定義しているところに、2行追加。

ダウンロードの部分を書いている残りの３行は、
取得したURLの情報をスコープの範囲内で使用できるように、
if分の階層に追加しました。

.
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628696/e08b72bd-1991-1a20-6762-ad3e2e78a989.png)
￼
ダウンロードしたファイルは、保存先を定義していないので、
Pythonファイルが置いているディレクトリに保存されます。

###ディレクトリ作成と保存
動画がダウンロードされて、よかったのですが、
これがもし30、40、5000兆件ダウンロードしようとすると
整理がとても大変になりますよね。

なので、検索ワードの名前のフォルダを作成して、
そこに動画を入れていけないか調べました。

参考記事：[ディレクトリの作成と削除](https://www.javadrive.jp/python/file/index8.html)

.

最終的に完成させたのがこちら。

.
▼ソース

```python
from apiclient.discovery import build
from __future__ import unicode_literals
import youtube_dl
import os

api_key = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'

def get_videos_search(keyword):
    youtube = build('youtube', 'v3', developerKey=api_key)
    youtube_query = youtube.search().list(q=keyword, part='id,snippet', maxResults=25)     #取得件数設定
    youtube_res = youtube_query.execute()
    return youtube_res.get('items', [])

keyword = input("検索ワードを入力してください:")

# os.mkdir('/Users/XXXXX/Desktop/' +keyword)
result = get_videos_search(keyword)

for item in result:
    if item['id']['kind'] == 'youtube#video':
        print(item['snippet']['title'])
        print('https://www.youtube.com/watch?v=' + item['id']['videoId'])
        
        url = 'https://www.youtube.com/watch?v=' + (item['id']['videoId'])
        ydl_opts = {
           'outtmpl': keyword+ '/%(title)s.%(ext)s'
        }
        with youtube_dl.YoutubeDL(ydl_opts) as ydl:
            try:
                ydl.cache.remove()
                ydl.download([url])
            except youtube_dl.DownloadError as error:
                pass
```

▼実行結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628696/388c0761-860f-4ea1-c8c4-33bb52b08c38.png)
￼
▼フォルダの中身
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628696/e314e367-7ba3-ba57-c610-5c5339533fd5.png)
￼
####ディレクトリの作成
参考記事の通り、os モジュールで用意されている mkdir 関数を使います。
それを先頭の部分に追加。

```python
import os
```

youtube-dlを使用してydl_optsにディレクトリの設定ができると
調べてわかったので、ydl_optsに検索ワードの名前でフォルダを作成し、
そこに動画を保存するようにさせました。

```python
...
for item in result:
    if item['id']['kind'] == 'youtube#video':
        print(item['snippet']['title'])
        print('https://www.youtube.com/watch?v=' + item['id']['videoId'])
        
        url = 'https://www.youtube.com/watch?v=' + (item['id']['videoId'])
  これ=> ydl_opts = {
           'outtmpl': keyword+ '/%(title)s.%(ext)s'
        }
...
```
####エラー回避
ダウンロードを実行している際に、エラーで停止することがありました。
調べたら、キャッシュのクリア？が問題かなと思ったので、
なんとなく追加してみました。

認識が間違っているかもしれないので、有識者の方
ご指摘をいただけると助かります。

```python
...
with youtube_dl.YoutubeDL(ydl_opts) as ydl:
            try:
                ydl.cache.remove()
                ydl.download([url])
            except youtube_dl.DownloadError as error:
                pass
```

#あとがき
インデントやスコープ等の基礎知識があれば、エラーで悩む時間も少なく
簡単に実装できるのではないかと思いました。