-
Notifications
You must be signed in to change notification settings - Fork 78
/
m3u8.py
95 lines (86 loc) · 3.16 KB
/
m3u8.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#coding: utf-8
from gevent import monkey
monkey.patch_all()
from gevent.pool import Pool
import gevent
import requests
import urlparse
import os
import time
class Downloader:
def __init__(self, pool_size, retry=3):
self.pool = Pool(pool_size)
self.session = self._get_http_session(pool_size, pool_size, retry)
self.retry = retry
self.dir = ''
self.succed = {}
self.failed = []
self.ts_total = 0
def _get_http_session(self, pool_connections, pool_maxsize, max_retries):
session = requests.Session()
adapter = requests.adapters.HTTPAdapter(pool_connections=pool_connections, pool_maxsize=pool_maxsize, max_retries=max_retries)
session.mount('http://', adapter)
session.mount('https://', adapter)
return session
def run(self, m3u8_url, dir=''):
self.dir = dir
if self.dir and not os.path.isdir(self.dir):
os.makedirs(self.dir)
r = self.session.get(m3u8_url, timeout=10)
if r.ok:
body = r.content
if body:
ts_list = [urlparse.urljoin(m3u8_url, n.strip()) for n in body.split('\n') if n and not n.startswith("#")]
ts_list = zip(ts_list, [n for n in xrange(len(ts_list))])
if ts_list:
self.ts_total = len(ts_list)
print self.ts_total
g1 = gevent.spawn(self._join_file)
self._download(ts_list)
g1.join()
else:
print r.status_code
def _download(self, ts_list):
self.pool.map(self._worker, ts_list)
if self.failed:
ts_list = self.failed
self.failed = []
self._download(ts_list)
def _worker(self, ts_tuple):
url = ts_tuple[0]
index = ts_tuple[1]
retry = self.retry
while retry:
try:
r = self.session.get(url, timeout=20)
if r.ok:
file_name = url.split('/')[-1].split('?')[0]
print file_name
with open(os.path.join(self.dir, file_name), 'wb') as f:
f.write(r.content)
self.succed[index] = file_name
return
except:
retry -= 1
print '[FAIL]%s' % url
self.failed.append((url, index))
def _join_file(self):
index = 0
outfile = ''
while index < self.ts_total:
file_name = self.succed.get(index, '')
if file_name:
infile = open(os.path.join(self.dir, file_name), 'rb')
if not outfile:
outfile = open(os.path.join(self.dir, file_name.split('.')[0]+'_all.'+file_name.split('.')[-1]), 'wb')
outfile.write(infile.read())
infile.close()
os.remove(os.path.join(self.dir, file_name))
index += 1
else:
time.sleep(1)
if outfile:
outfile.close()
if __name__ == '__main__':
downloader = Downloader(50)
downloader.run('http://m3u8.test.com/test.m3u8', '/home/video/')