-
Notifications
You must be signed in to change notification settings - Fork 0
/
gogoanimeapi.py
297 lines (274 loc) · 13.2 KB
/
gogoanimeapi.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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
import os
import requests
from bs4 import BeautifulSoup
from tornado import ioloop, httpclient
import converter
directory = "Episodes/"
path = ""
#program settings
silent_setting = True
#anime settings
ep_start = str(0)
ep_end = str(5001)
#anime_id = str(1502) #1502 watch this one
default_ep = str(1)
#quality_preferred = str(360) #1080p,720p,480p,360p
#quality = "lowest" #highest,lowest,average
http_client = ""
start_anime_id = 0
end_anime_id = 10000
#async settings
i = 0
threads = 100
headers={"Origin": "https://vidstreaming.io", "Referer": "https://vidstreaming.io"}
def init():
global directory
try:
os.stat(directory)
except:
os.mkdir(directory)
def anime_folder(title,episode_title):
try:
os.stat(title)
except:
os.mkdir(title)
try:
os.stat(title+"/"+episode_title)
except:
os.mkdir(title+"/"+episode_title)
def get_video_src(url):
headers = {"User-Agent":"letmein 5.0 / user"}
req = requests.get(url, headers=headers)
page = req.text
soup = BeautifulSoup(page, "lxml")
anime_name = soup.find("div", attrs={"class": "title_name"}).find("h2").text.strip().replace(":","").replace(" ","")
anime_series_name = soup.find("div", attrs={"class": "anime-info"}).find("a").text.strip().replace(":","").replace(" ","")
print("Episode Name:",anime_name)
if not silent_setting:
print("Anime Name:",anime_series_name)
#video_src = "https://"+soup.find("div", attrs={"class": "play-video"}).find("iframe").get("src")[2:]
video_src = soup.find("li", attrs={"class": "vidcdn"}).find("a").get("data-video")
back_up_src = soup.find("li", attrs={"class": "mp4"}).find("a").get("data-video")
return video_src,anime_name,anime_series_name
def get_m3u8_initiator_src(video_src):
headers = {"User-Agent":"letmein 5.0 / user"}
req = requests.get(video_src, headers=headers)
page = req.text
soup = BeautifulSoup(page, "lxml")
js = soup.findAll("script")[3].text #sometimes [4].text
m3u8_src = "http://"+js.split("file: '")[1].split("'")[0][8:] #isolate the https link in the js and convert it to http
return m3u8_src
def get_m3u8_playlist_src(m3u8_src,quality_preferred,quality,headers):
quality = quality.lower()
req = requests.get(m3u8_src, headers=headers) #can sometimes fail to load, too many connections in short time maybe
m3u8_stream = req.text
m3u8_stream_array = m3u8_stream.split("\n")
m3u8_stream_options = []
for line in m3u8_stream_array:
try:
if line[0] != "#":
m3u8_stream_options.append(line)
except:
pass
if not silent_setting:
print("Options:",m3u8_stream_options)
try:
flag = False
if quality_preferred != "default":
for quality_setting in m3u8_stream_options:
quality_setting_string = quality_setting.split(".")[2]
if quality_preferred == quality_setting_string:
m3u8_quality_playlist = quality_setting
flag = True
quality_ordered = []
quality_list = ["360","480","720","1080"]
for theorectical_quality in quality_list:
for quality_setting in m3u8_stream_options:
if theorectical_quality in quality_setting:
quality_ordered.append(quality_setting)
if flag == False:
if quality == "highest":
m3u8_quality_playlist = quality_ordered[-1:][0]
elif quality == "average":
index_num = round(len(quality_ordered)/2)-1
if (index_num < 0) or (index_num > len(quality_ordered)-1):
index_num = 0
m3u8_quality_playlist = quality_ordered[index_num]
else: #lowest or something else
m3u8_quality_playlist = quality_ordered[0]
quality_chosen = m3u8_quality_playlist.split(".")[2]
else:
quality_chosen = m3u8_quality_playlist.split(".")[2]
print("Selected Quality:",str(quality_chosen)+"p")
except:
m3u8_quality_playlist = m3u8_stream_options[0] #maybe need another [0]
url_domain = "/".join(m3u8_src.split("/")[:-1])+"/"
m3u8_stream_src = url_domain + m3u8_quality_playlist
return m3u8_stream_src,url_domain,m3u8_quality_playlist,m3u8_stream
def get_m3u8_playlist_links(m3u8_stream_src,headers):
req = requests.get(m3u8_stream_src, headers=headers)
m3u8_playlist = req.text
m3u8_playlist_doc = req.text.split("\n")
m3u8_links = []
for line in m3u8_playlist_doc:
try:
if line[0] != "#":
m3u8_links.append(line)
except:
pass
return m3u8_links,m3u8_playlist
def save_playlist_information(m3u8_src,directory,anime_name,m3u8_quality_playlist,m3u8_playlist,m3u8_stream,anime_series_name):
global path
m3u8_src_name = m3u8_src.split("/")[-1:][0]
anime_folder(directory+anime_series_name,anime_name) #creates the anime folder
path = directory+anime_series_name+"/"+anime_name+"/"
if not silent_setting:
print("Path:",path)
with open(path+"playlist.m3u8", "w", encoding="utf-8") as file:
file.write(m3u8_playlist)
return path
def download_ts_files(m3u8_links,url_domain,headers,path,threads):
try:
global i, http_client
i = 0
http_client = httpclient.AsyncHTTPClient(force_instance=True,defaults=dict(user_agent="Mozilla/5.0"),max_clients=threads)
for sub_link in m3u8_links:
url = url_domain+sub_link
wait_time1 = (i/8) + 90
wait_time2 = (i/8) + 150
request = httpclient.HTTPRequest(url.strip(),headers=headers,method='GET',connect_timeout=wait_time1,request_timeout=wait_time2)
http_client.fetch(request,handle_ts_file_response)
i += 1
ioloop.IOLoop.instance().start()
except:
print("Reattempting Downloading Episode Files..")
download_ts_files(m3u8_links,url_domain,headers,path,threads)
def handle_ts_file_response(response):
global i,path,headers, http_client
if response.code == 599:
#http_client.fetch(response.effective_url.strip(),headers=headers,method='GET',connect_timeout=10000,request_timeout=10000)
#request = httpclient.HTTPRequest(response.effective_url.strip(),headers=headers,method='GET',connect_timeout=10000,request_timeout=10000)
#http_client.fetch(request,handle_ts_file_response)
try:
wait_time1 = (i/8) + 20
wait_time2 = (i/8) + 60
request = httpclient.HTTPRequest(response.effective_url,headers=headers,method='GET',connect_timeout=wait_time1,request_timeout=wait_time2)
http_client.fetch(request,handle_ts_file_response)
except Exception as e:
pass
else:
file_name = str(response.effective_url.split("/")[-1:][0])
if not silent_setting:
print("Retrying:",file_name)
else:
try:
file_name = str(response.effective_url.split("/")[-1:][0])
m3u8_video_file_part = response.body #use binary
with open(path+file_name, "wb") as file: #save the file as a binary
file.write(m3u8_video_file_part)
if not silent_setting:
print("Downloaded ({} remaining):".format(i),file_name)
#print("alive",response.effective_url)
i -= 1
except Exception as e:
pass
#print("dead",response.effective_url,e)
#http_client.fetch(response.effective_url.strip(),headers=headers,method='GET',connect_timeout=10000,request_timeout=10000)
#request = httpclient.HTTPRequest(response.effective_url.strip(),headers=headers,method='GET',connect_timeout=10000,request_timeout=10000)
#http_client.fetch(request,handle_ts_file_response)
if i == 0: #all pages loaded
ioloop.IOLoop.instance().stop()
#print("Download Complete")
def download_episode(url,directory="Episodes/",convert=True,output_format=".mkv",overwrite=True,keep_source_stream=False,silent=True,quality_preferred="default",quality="highest",threads="100",headers={"Origin": "https://vidstreaming.io", "Referer": "https://vidstreaming.io"}):
global silent_setting
silent_setting = silent
try:
video_src,anime_name,anime_series_name = get_video_src(url)
if not silent_setting:
print("Embed Src",video_src)#,anime_name)
m3u8_src = get_m3u8_initiator_src(video_src)
if not silent_setting:
print("M3U8 Src",m3u8_src)
m3u8_stream_src,url_domain,m3u8_quality_playlist,m3u8_stream = get_m3u8_playlist_src(m3u8_src,quality_preferred,quality,headers)
if not silent_setting:
print("Playlist:",m3u8_stream_src)#,url_domain)
m3u8_links,m3u8_playlist = get_m3u8_playlist_links(m3u8_stream_src,headers)
if not silent_setting:
print("Parts:",len(m3u8_links))
if not silent_setting:
print("Saving Playlist Files..")
path = save_playlist_information(m3u8_src,directory,anime_name,m3u8_quality_playlist,m3u8_playlist,m3u8_stream,anime_series_name)
print("Downloading Episode Files..")
download_ts_files(m3u8_links,url_domain,headers,path,int(threads))
print("Download Source Files Complete")
if convert:
playlist_path = path+"playlist.m3u8"
if not silent_setting:
print("Playlist Path:",playlist_path)
converter.convert_file(playlist_path,output_format,overwrite,keep_source_stream)
except Exception as e:
print(e)
download_episode(url)
def download_anime(anime_id,ep_start="default",ep_end="default",directory=directory,default_ep="1",convert=True,output_format=".mkv",overwrite=True,keep_source_stream=False,silent=True,quality_preferred="default",quality="highest",threads="100"):
global silent_setting
silent_setting = silent
url = anime_id #turn most of this into a function to return the episodes available (useful for checking for new episodes)
if silent == False:
silent_setting = silent
try:
anime_id = int(anime_id)
except:
pass
if not isinstance(anime_id, int): #if not an anime_id
req = requests.get(url)
page = req.text
soup = BeautifulSoup(page, "lxml")
anime_id = str(soup.find("input", attrs={"id": "movie_id"}).get("value")) #gets anime id
default_ep = str(soup.find("input", attrs={"id": "default_ep"}).get("value")) #gets default episode
episode_page = soup.find("ul", attrs={"id": "episode_page"}).findAll("a")
if ep_start == "default":
ep_start = str(episode_page[0].get("ep_start"))
if ep_end == "default":
ep_end = str(episode_page[-1].get("ep_end"))
url = "https://www04.gogoanimes.tv/load-list-episode?ep_start="+ep_start+"&ep_end="+ep_end+"&id="+anime_id+"&default_ep="+default_ep
else:
anime_id = str(anime_id)
if ep_start == "default":
ep_start = "0"
if ep_end == "default":
ep_end = "5001"
ep_start = str(ep_start)
ep_end = str(ep_end)
default_ep = str(default_ep)
url = "https://www04.gogoanimes.tv/load-list-episode?ep_start="+ep_start+"&ep_end="+ep_end+"&id="+anime_id+"&default_ep="+default_ep
req = requests.get(url)
page = req.text
soup = BeautifulSoup(page, "lxml")
episodes = ["https://www04.gogoanimes.tv"+tag.get("href").strip() for tag in soup.findAll("a")][::-1] #reverses episode order
if not silent_setting:
print("API Episodes:",url)
if len(episodes) != 0:
print("Anime ID:",anime_id)
print("Episodes:",len(episodes))
for episode in episodes:
if not silent:
print("Episode Link:",episode)
download_episode(url=episode,directory=directory,convert=convert,output_format=output_format,overwrite=overwrite,keep_source_stream=keep_source_stream,silent=silent,quality_preferred=quality_preferred,quality=quality,threads=threads)
else:
print("No Anime with ID:",anime_id)
def download_multiple_anime(start_anime_id=start_anime_id,end_anime_id=end_anime_id,ep_start="default",ep_end="default",directory=directory,default_ep="1",convert=True,output_format=".mkv",overwrite=True,keep_source_stream=False,silent=True,quality_preferred="default",quality="highest",threads="100"):
global silent_setting
silent_setting = silent
try:
start_anime_id=int(start_anime_id)
end_anime_id=int(end_anime_id)
for anime_id in range(start_anime_id,end_anime_id):
try:
download_anime(str(anime_id),ep_start,ep_end,directory,default_ep,convert,output_format,overwrite,keep_source_stream,silent,quality_preferred,quality,threads)
except Exception as e:
print("No Anime(?)",e)
except:
print("Invalid Anime ID's")
init()
if __name__ == "__main__":
download_multiple_anime(start_anime_id=start_anime_id,end_anime_id=end_anime_id,ep_start="default",ep_end="default",directory=directory,default_ep="1",convert=True,output_format=".mkv",overwrite=True,keep_source_stream=False,silent=True,quality_preferred="1080",quality="highest",threads="100")