iphoneだけでPythonistaでyoutubeから動画をダウンロード出来るようにしよう!

### 概要

iphoneでyoutubeを使っていて手元に保存したいと思うことがよくあります。でもyoutube premiumは結構高い。。
そこで自分でダウンロードできるようにしました。
お題はずばり__Youtubeの動画をiphoneからダウンロードする__です！

### 参考にしたサイト
- https://qiita.com/Gold_Gliders/items/331eac3045c635ce0612
  - urlの取得方法などでとても参考になりました。この方はpytubeを使って動画を取得していましたが自分はyoutube_dlを使ってダウンロードしたかったので自分流に改造しました。また、動画のフォルダもスクリプトがあるフォルダ配下に作成したかったので少し手を加えています。
- https://mahimahironron.hateblo.jp/entry/2019/09/29/youtubeの動画をダウンロードしよう！
  - youtube_dlでのダウンロード方法を参考にしました。

### 実際やったこと、ソース
- pythonistaの中にフォルダを作ります。
- 作ったフォルダの中に「DL_videos」というフォルダを作成します。ダウンロードした動画はこのフォルダに保存されます。
- 以下のソースを作成します。ソースは少し多いですが頑張って作ってみてください。


①byte2si.py

```byte2si.py
import math
def main(byte):
    #byteの桁数を取得して、3桁刻みに単位を変えてくだけ
    if 0 <= byte:
        dig = int(math.log10(byte))
        if 0 <= dig < 3:
            bytes = byte / pow(10, 0)
            return bytes, 'B'
        elif 3 <= dig < 6:
            bytes = byte / pow(10, 3)
            return bytes, 'KB'
        elif 6 <= dig < 9:
            bytes = byte / pow(10, 6)
            return bytes, 'MB'
        elif 9 <= dig < 12:
            bytes = byte / pow(10, 9)
            return bytes, 'GB'
        elif 12 <= dig <= 15:
            bytes = byte / pow(10, 12)
            return bytes, 'TB'
    else:
        raise ValueError('Not num')


def byte2si(byte):
    num, unit = main(byte)
    #少数第2位まで丸める
    renum = round(num, 2)
    return str(renum) + unit
```

②main.py

```main.py

from pytube import YouTube
#import add_video
import my_module
import byte2si
import url_get
import os
import glob
import time
import sys
import youtube_dl

VIDEO_DIR = os.path.join(os.getcwd(), "DL_videos")
OPTS = {
    "outtmpl": "{VIDEO_DIR}/%(title)s.mp4".format(VIDEO_DIR=VIDEO_DIR),
    'ignoreerrors': True
}


def download(url):
    """
    Download video from YouTube.

    Parameters
    ----------
    url : str
        YouTube video URL

    Returns
    ----------
    info : dict
        Downloaded video info.
    """
    print("Downloading {url} start..".format(url=url))
    with youtube_dl.YoutubeDL(OPTS) as y:
        info = y.extract_info(url, download=True)
        print("Downloading {url} finish!".format(url=url))
    return info

def rename(info):
    """
    Rename downloaded video filename as camelcase.

    Parameters
    ----------
    info : dict
        Downloaded video info.
    """
    title = info["title"]
    pattern = '{VIDEO_DIR}/{title}.mp4'.format(VIDEO_DIR=VIDEO_DIR, title=title)
    for v in glob.glob(pattern, recursive=True):
        print("{title}.mp4 found! Renaming start..".format(title=title))
        file_path = os.path.join(VIDEO_DIR, v)
        new_file_path = file_path.replace(' ', '_')
        os.rename(file_path, new_file_path)
        print("Renaming finish!".format(title))
        
def absfpath(path):
    # ”Download”ディレクトリ下のファイルを取得する
    flist = glob.glob(path + '/*')
    if flist:
        # “Download”ディレクトリ下の1つしかない動画ファイルを取得する
        fpath = os.path.abspath(flist[0])
         # “Download”ディレクトリ下にある動画ファイルの絶対パスを返す
        return fpath
    else:
        raise OSError('The file does not exist.')


def main():
    #プログレスバー
    print('Now executing...')

    # YouTubeアプリからurlを取得
    url = url_get.yturl()
    if not url:
        raise ('Not YouTube')
        
    print(url)
    info = download(url)
    rename(info)
    abspath = absfpath(VIDEO_DIR)


if __name__ == '__main__':
    # 開始時間を取得
    start = time.time()
    main()
    #終了時間を少数第3位まで取得
    finish = round(time.time() - start, 3)
    #実行所要時間を表示
    print('Execute Time:', finish)
    #終了
    print('Done')
```

③url_get.py

```url_get.py

import appex
import re


def trns():
    if not appex.is_running_extension():
        raise RuntimeError(
            'This script is intended to be run from the sharing extension.')

    url = appex.get_text()
    if not url:
        raise ValueError('No input text found.')
    elif re.search(r'youtube', url):
        return url
    raise ValueError('Not YouTube')


def yturl():
    geturl = trns()
    # 取得したurlの余分なテキストを置換し、なくす
    url = geturl.replace('&feature=share', '')
    return url


if __name__ == '__main__':
    print(yturl())
```

- main.pyをSafariやyoutubeの共有→「Run Pythonista Script」の中で実行できるよう登録します。

### 使い方
- Youtubeを開きます。
- 見たい動画またはプレイリストに行きます。
- 「共有」から「Run Pythonista Script」を選び登録したスクリプトを実行します。
  - 動画の場合：動画がダウンロードされDL_Videosフォルダの中に保存されます。
  - プレイリストの場合: プレイリスト内全ての動画がダウンロードされDL_Videosフォルダの中に保存されます（プレイリストは公開のものしかダウンロードできないのでご注意！）。