Last active
September 11, 2015 05:40
-
-
Save imayhaveborkedit/55ff40ff06018236a108 to your computer and use it in GitHub Desktop.
Silly anime watching assistant
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import sys, inspect, re | |
import requests, webbrowser | |
from BeautifulSoup import BeautifulSoup | |
USER_AGENT_HEADER = {'User-agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:34.0) Gecko/20100101 Firefox/34.0.1'} | |
class Anime(object): | |
baseurl = '' | |
_total_episodes = -1 | |
_video_cache = {} | |
def __init__(self, url): | |
raise NotImplementedError | |
self.anime_name = '' | |
self.info_page = '' | |
self.start_ep = 1 | |
self.current_ep = 1 | |
def get_total_episodes(self): | |
raise NotImplementedError | |
if self._total_episodes < 0: | |
pass | |
return self._total_episodes | |
def get_episode(self, episode): | |
return | |
def get_video_link(self, episode): | |
if episode in self._video_cache: | |
return self._video_cache[episode] | |
def pop_episode(self): | |
if self.reached_end(): return | |
elif self.current_ep == self.get_total_episodes(): | |
self.current_ep = -1 | |
return self.get_episode(self.get_total_episodes()) | |
else: | |
self.current_ep += 1 | |
return self.get_episode(self.current_ep-1) | |
def cache_video_link(self, episode): | |
self._video_cache[episode] = self.get_video_link(episode) | |
def reached_end(self): | |
return self.current_ep == -1 | |
def goto(self, ep): | |
self.current_ep = int(ep) | |
class GogoAnime(Anime): | |
baseurl = 'http://gogoanime.tv/' | |
def __init__(self, url): | |
if not url.startswith(self.baseurl): | |
raise NameError("Wrong class idiot") | |
print url | |
if '.tv/category/' in url: | |
self.anime_name = url.split('/')[-1] | |
self.start_ep = 1 | |
self.info_page = url | |
elif '-episode-' in url: | |
self.anime_name = '-'.join(url.split('/')[-1].split('-')[:-2]) | |
self.start_ep = int(url.split('/')[-1].split('-')[-1]) | |
self.info_page = self.baseurl + 'category/' + self.anime_name | |
else: | |
raise AttributeError("What the fuck is up with this: " + url) | |
self.current_ep = self.start_ep | |
def get_total_episodes(self): | |
if self._total_episodes < 0: | |
data = BeautifulSoup(requests.get(self.info_page).text) | |
eps = data.body.find('ul', attrs={'id':'episode_page'}) | |
self._total_episodes = int(eps()[-1].string.split('-')[-1]) | |
return self._total_episodes | |
def get_episode(self, episode): | |
if episode > self.get_total_episodes(): raise IndexError | |
return self.baseurl + self.anime_name + '-episode-%s' % int(episode) | |
def get_video_link(self, episode): | |
super(self.__class__, self).get_video_link(episode) | |
data = BeautifulSoup(requests.get(self.get_episode(episode)).text) | |
udata = data.body.find('select', attrs={'id':'selectQuality'}) | |
odata = udata.findChildren()[-1] | |
print 'Using quality ' + odata.string | |
return str(odata.get('value')) | |
class AnimeJoy(Anime): | |
baseurl = 'http://animejoy.tv/watch/' | |
def __init__(self, url): | |
if not url.startswith(self.baseurl): | |
raise NameError("Wrong class idiot") | |
surl = url.split('/') | |
self.anime_name = surl[4] | |
self.info_page = '/'.join(surl[:5]) | |
self.current_ep = self.start_ep = int(surl[5]) if len(surl) == 6 else 1 | |
def get_total_episodes(self): | |
if self._total_episodes < 0: | |
data = BeautifulSoup(requests.get(self.info_page).text) | |
eps = data.body.find('div', attrs={'class':'episodes'}) | |
self._total_episodes = int(eps('a')[0]['href'].split('/')[-1]) | |
return self._total_episodes | |
def get_episode(self, episode): | |
if episode > self.get_total_episodes(): raise IndexError | |
return self.baseurl + self.anime_name + '/%s' % int(episode) | |
def get_video_link(self, episode): | |
super(self.__class__, self).get_video_link(episode) | |
data = BeautifulSoup(requests.get(self.get_episode(episode)).text) | |
odata = data.body.find('source')['src'] | |
return str(odata) | |
class AnimeShowTv(Anime): | |
baseurl = 'http://animeshow.tv/' | |
_mirror_prioritys = ['MP4UPLOAD HD', 'MP4UPLOAD', 'MP4VIDS', 'AUENGINE', 'RAW'] | |
_mirror_video_reg = { | |
'auengine': | |
"file: \s*'(.*?\.mp4)',\s*?label:\s*'720p'", | |
'mp4upload': | |
"url:\s*'(.*\.mp4)\?", | |
'mp4vids': | |
"file:\s*'(.*?\.mp4)'", | |
} | |
def __init__(self, url): | |
if not url.startswith(self.baseurl): | |
raise NameError("Wrong class idiot") | |
surl = url.split('/') | |
durl = surl[3] | |
if '-episode-' in url: | |
self.anime_name = durl.split('-episode-')[0] | |
self.info_page = url.split('-episode-')[0] + '/' | |
else: | |
self.anime_name = url.split('/')[3] | |
self.info_page = url if url.endswith('/') else url + '/' | |
if '-mirror-' in durl: | |
self.current_ep = self.start_ep = int(durl.split('-mirror-')[1].strip('/')) | |
elif '-episode-' in durl: | |
self.current_ep = self.start_ep = int(durl.split('-episode-')[1].strip('/')) | |
else: | |
self.current_ep = self.start_ep = 1 | |
if '-mirror-' in durl: | |
self._mirror = int(durl.split('-mirror-')[1]) | |
else: | |
self._mirror = 0 | |
data = BeautifulSoup(requests.get(self.get_episode(self.current_ep, self._mirror)).text) | |
self._mirrortype = str(data.body.find('a', attrs={'class':'mirror-active'}).string) | |
def get_total_episodes(self): | |
if self._total_episodes < 0: | |
data = BeautifulSoup(requests.get(self.info_page).text) | |
eps = data.body.find('table', attrs={'id':'episode-list-entry-tbl'}) | |
self._total_episodes = int(eps('tr')[0].td.a['href'].split('-')[-1].strip('/')) | |
return self._total_episodes | |
def get_episode(self, episode, urlmirror=0): | |
if episode > self.get_total_episodes(): raise IndexError | |
aurl = self.baseurl + self.anime_name + '-episode-%s' % int(episode) | |
if urlmirror: | |
res = requests.head(aurl+'-mirror-'+str(urlmirror)+'/') | |
res.raise_for_status() | |
aurl += '-mirror-' + str(urlmirror) | |
else: # This is where I pick the best mirror right? | |
pass | |
return aurl + '/' | |
def get_video_link(self, episode, mirror=-1): | |
super(self.__class__, self).get_video_link(episode) | |
if mirror == -1: | |
mirror = self._mirror | |
data = BeautifulSoup(requests.get(self.get_episode(episode, mirror)).text) | |
odata = data.body.find('div', attrs={'id':'embbed-video'}).iframe['src'] | |
data2 = BeautifulSoup(requests.get(str(odata), headers=USER_AGENT_HEADER).text) | |
mirrortype = str(odata).strip('http://').strip('www.').split('.')[0] | |
try: | |
return re.search(self._mirror_video_reg[mirrortype], str(data2.text)).groups()[0] | |
except: | |
if not hasattr(self, '_other_mirrors'): | |
self._other_mirrors = self._get_other_mirrors(mirror) | |
else: | |
if mirror in self._other_mirrors: self._other_mirrors.pop(mirror) | |
if not self._other_mirrors: | |
raise RuntimeError("No available mirrors") | |
while self._other_mirrors: | |
for m in self._other_mirrors: | |
next_mirror = self._other_mirrors.get(m) | |
if next_mirror is not None: | |
break | |
print 'Mirror %s (%s) failed, trying mirror %s (%s)' % (mirror, mirrortype, m, next_mirror[0].lower()) | |
d = self.get_video_link(episode, m) | |
del self._other_mirrors | |
return d | |
def _get_other_mirrors(self, mirror): | |
data = BeautifulSoup(requests.get(self.get_episode(self.current_ep, mirror)).text) | |
mirs = data.body.findAll('a', attrs={'class':'mirror'}) | |
return {mirs.index(t)+1:(t.string, str(t['href'])) for t in mirs} | |
def get_class_dict(): | |
classes = inspect.getmembers(sys.modules[__name__], | |
lambda m: inspect.isclass(m) and issubclass(m, Anime) and m != Anime) | |
return {y.baseurl:y for x,y in classes} | |
def lazy(url): | |
cd = get_class_dict() | |
url = url.replace('http://www.', 'http://') | |
for path in cd: | |
if url.startswith(path): | |
return cd[path] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import time, itertools, webbrowser | |
import pyperclip | |
import anime | |
if __name__ == '__main__': | |
print 'Supported anime websites:' | |
for a in anime.get_class_dict(): | |
print ' ' + a | |
print 'Copy a valid video url to the clipboard and press enter.\n' | |
s = itertools.cycle('|/-\\|\\-/') | |
waited = False | |
while True: | |
cbtext = pyperclip.paste() | |
if cbtext and anime.lazy(cbtext): | |
print 'Valid url: %s\n' % cbtext | |
if waited: raw_input('Press enter to begin\n') | |
break | |
else: | |
print '\rWaiting for valid url %s\r' % s.next(), | |
waited = True | |
time.sleep(0.5) | |
CorrectAnime = anime.lazy(cbtext) | |
a = CorrectAnime(cbtext) | |
print 'Starting at episode %s/%s' % (a.current_ep, a.get_total_episodes()) | |
for ae in range(a.current_ep, a.get_total_episodes()+1): | |
webbrowser.open_new_tab(a.get_video_link(ae)) | |
a.pop_episode() | |
print 'Caching next video link...', | |
a.cache_video_link(a.current_ep) | |
print 'Done.\n' | |
if a.reached_end(): | |
print 'You have reached the end of the available episodes.' | |
break | |
raw_input('Press enter to open episode %s/%s' % (ae + 1, a.get_total_episodes())) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Rad thnx for this! I just wrote an animejoy py script that allows search and episode selection check it out you might like it