youtube-dlのextractor書き方講座 3/4

# あけましておめでとうございます
あけましておめでとうございます。
色々忙しくて気づいたら年末どころか年を越していました。

今年もよろしくお願いします。

# 前回の続き
また見てない方は[前回はここから](https://qiita.com/nao20010128nao/items/ef0af6e9a356013e69dd)どうぞ。
前回はエラー処理を書きました。
今回は、最低限以上の情報の取得をやって行きます。

## 最終目標
[これを作ります。](https://github.com/nao20010128nao/ytdl-patched/blob/8648116f743d8ea9f58db7c2daf726903232ccda/youtube_dl/extractor/whowatch.py)

# ウェブサイトから何が見えるのか
また[適当な配信を持ってきました](https://whowatch.tv/viewer/19199115)。開いてみましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111609/efa9e679-b9e3-8970-9310-dc032ad4ab2f.png)

第一巻と同様、開発者ツールを開き、それっぽい通信を探してみましょう。
Chromeでも`Ctrl+Shift+I`で開きます。

# とりあえず投稿者名で検索
少しスクロールすると、投稿者名や説明文などが出てきました。
これをDevToolsで検索すると、こんな感じ。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111609/4c48aeb3-1b54-cd06-4a11-0cd424f27f72.png)

投稿者名などが出てきました。
このAPIエンドポイントのURLは`https://api.whowatch.tv/lives/19199115`でした。

# この情報を抽出する
まず、`'https://api.whowatch.tv/lives/' + video_id`をダウンロードして、JSONとしてパースさせます。

```python
metadata = self._download_json('https://api.whowatch.tv/lives/' + video_id, video_id)
```

さて、`_real_extract`の返り値は`dict`で返していたのを覚えていますか?
この`dict`のキーには一定の取り決めがあり、これは[`README.md`の`OUTPUT TEMPLATE`セクションに掲載されています。](https://github.com/ytdl-org/youtube-dl#output-template)

例えば、今回取り扱う投稿者名と投稿者のニックネームは、それぞれ`uploader`と`uploader_id`になります。

この規則を守って`dict`を設定していきます。

```python
# その他の情報を取り出す
uploader = metadata['live']['user']['name']
uploader_id = metadata['live']['user']['user_path']

return {
    # (略)
    # 投稿者情報
    'uploader': uploader,
    'uploader_id': uploader_id,
}
```

同様に、`thumbnail`キーで(`--write-thumbnail`オプションで書き出すことができる)サムネイルを設定できます。

```python
thumbnail = metadata['live']['latest_thumbnail_url']

return {
    # (略)
    # サムネイル
    'thumbnail': thumbnail,
}
```


# おわりに
今回は、最低限以上の情報の取得を書きました。
これで、最終目標と同じようなextractorが完成したので、次はyoutube-dlのコーディング規則を簡単にやりたいと思います。
`KeyError`などのエラーハンドリングは、youtube-dlで容易に行う方法が用意されているので、皆さんへの課題にしたいと思います。

ここまでご覧いただきありがとうございました。

次: [第4巻](https://qiita.com/nao20010128nao/items/f4514125363d7ad2c1b8)

## 付録: 今回のコード

```python
# coding: utf-8
from __future__ import unicode_literals

from .common import InfoExtractor
from ..utils import ExtractorError


class WhoWatchIE(InfoExtractor):
    _VALID_URL = r'https?://whowatch\.tv/viewer/(?P<id>\d+)/?'

    def _real_extract(self, url):
        video_id = self._match_id(url)

        # URL、IDの順で指定する
        live_data = self._download_json('https://api.whowatch.tv/lives/' + video_id + '/play', video_id)
        metadata = self._download_json('https://api.whowatch.tv/lives/' + video_id, video_id)

        # デバッグ用: live_dataを表示する
        # self.to_screen(live_data)

        # HLSのURL
        hls_url = live_data.get('hls_url')

        # hls_urlが無ければエラーを投げる
        if not hls_url:
            raise ExtractorError(live_data.get('error_message'), expected=True)

        # とりあえずHLSのフォーマットを検索する
        formats = self._extract_m3u8_formats(
            hls_url, video_id, ext='mp4', entry_protocol='m3u8_native',
            m3u8_id='hls')
        # 並び替える。これによって何も設定しない状態で最高画質をダウンロードするようにする
        self._sort_formats(formats)

        # その他の情報を取り出す
        uploader = metadata['live']['user']['name']
        uploader_id = metadata['live']['user']['user_path']
        thumbnail = metadata['live']['latest_thumbnail_url']

        return {
            'id': video_id,
            # 鉤括弧があったので同時に外してしまう
            'title': live_data['share_info']['live_title'][1:-1],
            # フォーマット一覧
            'formats': formats,
            # これは生放送です
            'is_live': True,
            # 投稿者情報
            'uploader': uploader,
            'uploader_id': uploader_id,
            # サムネイル
            'thumbnail': thumbnail,
        }
```

今回のコードは[ここにも置いておきます。](https://github.com/nao20010128nao/youtube-dl/blob/qiita_explaination/youtube_dl/extractor/whowatch.py)