m3u8形式の動画をダウンロード

#はじめに
 m3u8 を落とすソフトは無数にあるが、今回は一番シンプルにつくりたい。複雑だとブラックボックスのようになってつまらない。

#流れ

1. まず m3u8 のテキストから 動画の url を取る。
2. url が TS 形式なら、データを取る。
2. url が m3u8 なら再帰的にデータを取る。
3. 取ったデータを足す。

#コード

```python:dl.py
import requests
import urllib.parse as up
import sys

def _dlm3u8(url,session=None,log=sys.stdout):
        if not session:
                session=requests.Session()
        resdata=bytes()
        res=session.get(url)
        for line in res.text.split("\n"):
                if not line:    #skip empty
                        continue
                if line[0]=="#":    #skip comment
                        continue
                vurl=up.urljoin(url,line)
                if log:
                        print("vurl",vurl,file=log)
                if ".m3u8" in vurl:    #dl m3u8
                        resdata+=_dlm3u8(vurl,sesison=session)
                elif ".ts" in vurl:    #dl ts
                        res=session.get(vurl)
                        resdata+=res.content
        return resdata

def dlm3u8(url,fname):
        data=_dlm3u8(url)
        if not data:
                return False
        with open(fname,"wb") as f:
                f.write(data)
``` 

###_dlm3u8

引数 |意味
--- |--
url |url

返り値 |意味
---|---
data |ビデオのデータ


##dlm3u8

引数 |意味
--- |--
url |url
fname |書き込むファイル名

返り値 |意味
---|---
bool |ダウンロードの可否

#試す

pornhubの動画で試してみる。

```python:main.py
import dl

url="https://ev-h.phncdn.com/hls/videos/201902/19/208607941/,200810_2009_1080P_4000K,200810_2009_720P_4000K,200810_2009_480P_2000K,200810_2009_240P_1000K,_208607941.mp4.urlset/master.m3u8?validfrom=1635132054&validto=1635139254&ipa=158.201.248.177&hdl=-1&hash=ocl5naHjd1I2e7sK9NVDL8dPLmw%3D"
fname="a.mp4"

dl.dlm3u8(url,fname)
```

```shell:実行結果
$ python main.py

~~ 略 ~~ 

vurl https://ev-h.phncdn.com/hls/videos/201902/19/208607941/,200810_2009_1080P_4000K,200810_2009_720P_4000K,200810_2009_480P_2000K,200810_2009_240P_1000K,_208607941.mp4.urlset/seg-101-f2-v1-a1.ts?validfrom=1635132054&validto=1635139254&ipa=158.201.248.177&hdl=-1&hash=ocl5naHjd1I2e7sK9NVDL8dPLmw%3D
vurl https://ev-h.phncdn.com/hls/videos/201902/19/208607941/,200810_2009_1080P_4000K,200810_2009_720P_4000K,200810_2009_480P_2000K,200810_2009_240P_1000K,_208607941.mp4.urlset/seg-102-f2-v1-a1.ts?validfrom=1635132054&validto=1635139254&ipa=158.201.248.177&hdl=-1&hash=ocl5naHjd1I2e7sK9NVDL8dPLmw%3D
vurl https://ev-h.phncdn.com/hls/videos/201902/19/208607941/,200810_2009_1080P_4000K,200810_2009_720P_4000K,200810_2009_480P_2000K,200810_2009_240P_1000K,_208607941.mp4.urlset/seg-103-f2-v1-a1.ts?validfrom=1635132054&validto=1635139254&ipa=158.201.248.177&hdl=-1&hash=ocl5naHjd1I2e7sK9NVDL8dPLmw%3D
vurl https://ev-h.phncdn.com/hls/videos/201902/19/208607941/,200810_2009_1080P_4000K,200810_2009_720P_4000K,200810_2009_480P_2000K,200810_2009_240P_1000K,_208607941.mp4.urlset/seg-104-f2-v1-a1.ts?validfrom=1635132054&validto=1635139254&ipa=158.201.248.177&hdl=-1&hash=ocl5naHjd1I2e7sK9NVDL8dPLmw%3D


~~ 略 ~~
```

時間はかかるが一応落とせた。

#終わりに
 改良すれば早くなるのかな。こればっかりは、サーバーの問題な気もするが。。。
 dlm3u8 はイテレータにすればオシャレかもしれない。(邪道な気もする。(笑))

```python:dl.py
def _dlm3u8(url,session=None):
        if not session:
                session=requests.Session()
        res=session.get(url)
        for line in res.text.split("\n"):
                if not line:
                        continue
                if line[0]=="#":
                        continue
                vurl=up.urljoin(url,line)
                print("vurl",vurl)
                if ".m3u8" in vurl:
                        for data in _dlm3u8(vurl,session=session):
                                yield data
                elif ".ts" in vurl:
                        yield session.get(vurl).content

def dlm3u8(url,fname):
        with open(fname,"wb") as f:
                for data in _dlm3u8(url):
                        f.write(data)
```

```python
for data in _dlm3u8(vurl,session=session):
        yield data
```

は

```python
yield from _dlm3u8(vurl,session=session)
```

の方が簡潔だが、肌に馴染まないので、使いたくないような。

##[コード](https://github.com/tetsuya111/util/tree/main/m3u8)