Added manga-py source
This commit is contained in:
12
manga-py-stable_1.x/manga_py/providers/1stkissmanga_com.py
Normal file
12
manga-py-stable_1.x/manga_py/providers/1stkissmanga_com.py
Normal file
@@ -0,0 +1,12 @@
|
||||
from .rawdevart_com import RawDevArtCom
|
||||
|
||||
|
||||
class FirstKissMangaCom(RawDevArtCom):
|
||||
_chapter_selector = r'/manga/[^/]+/chapter-(\d+(?:-\d+)?)'
|
||||
|
||||
def get_files(self):
|
||||
parser = self.html_fromstring(self.chapter)
|
||||
return self._images_helper(parser, '.page-break img[data-src]', attr='data-src')
|
||||
|
||||
|
||||
main = FirstKissMangaCom
|
||||
24
manga-py-stable_1.x/manga_py/providers/3asq_info.py
Normal file
24
manga-py-stable_1.x/manga_py/providers/3asq_info.py
Normal file
@@ -0,0 +1,24 @@
|
||||
from .authrone_com import AuthroneCom
|
||||
from .helpers.std import Std
|
||||
|
||||
|
||||
class ThreeAsqInfo(AuthroneCom, Std):
|
||||
_ch_selector = '.mng_det ul.lst > li > a.lst'
|
||||
|
||||
def get_chapter_index(self) -> str:
|
||||
return self.re.search(
|
||||
r'\.info/[^/]+/([^/]+)',
|
||||
self.chapter
|
||||
).group(1).replace('.', '-')
|
||||
|
||||
def get_main_content(self):
|
||||
return self._get_content('{}/{}/')
|
||||
|
||||
def get_manga_name(self) -> str:
|
||||
return self._get_name(r'\.info/([^/]+)')
|
||||
|
||||
def get_files(self):
|
||||
return list(set(super().get_files())) # remove doubles
|
||||
|
||||
|
||||
main = ThreeAsqInfo
|
||||
69
manga-py-stable_1.x/manga_py/providers/7sama_com.py
Normal file
69
manga-py-stable_1.x/manga_py/providers/7sama_com.py
Normal file
@@ -0,0 +1,69 @@
|
||||
from manga_py.provider import Provider
|
||||
from .helpers.std import Std
|
||||
|
||||
|
||||
class SevenSamaCom(Provider, Std):
|
||||
|
||||
def get_archive_name(self) -> str:
|
||||
self._vol_fill = True
|
||||
name = self.re.sub('[^a-zA-Z0-9]+', '_', self.chapter['chapter_name'])
|
||||
return self.normal_arc_name([
|
||||
self.chapter['number'],
|
||||
str(self.chapter_id),
|
||||
name
|
||||
])
|
||||
|
||||
def get_chapter_index(self) -> str:
|
||||
return self.chapter_id
|
||||
|
||||
def get_main_content(self):
|
||||
return self._get_content('{}/manga/{}')
|
||||
|
||||
def get_manga_name(self) -> str:
|
||||
return self._get_name('/manga/([^/]+)')
|
||||
|
||||
def get_chapters(self):
|
||||
idx = self.re.search(r'/manga/.+?/(\d+)', self.get_url()).group(1)
|
||||
chapters = []
|
||||
for i in range(1, 1000):
|
||||
content = self.http_get('{}/series/chapters_list.json?page={}&id_serie={}'.format(
|
||||
self.domain, i, idx
|
||||
), {'x-requested-with': 'XMLHttpRequest'})
|
||||
data = self.json.loads(content)
|
||||
if data['chapters'] is False:
|
||||
break
|
||||
chapters += self.__prepare_chapters(data['chapters'])
|
||||
return chapters
|
||||
|
||||
@staticmethod
|
||||
def __prepare_chapters(items):
|
||||
chapters = []
|
||||
for i in items:
|
||||
for k, j in i['releases'].items():
|
||||
chapter = i.copy()
|
||||
chapter['release'] = j
|
||||
chapter['release_id'] = k
|
||||
chapters.append(chapter)
|
||||
return chapters
|
||||
|
||||
def get_files(self):
|
||||
url = self.chapter_for_json()
|
||||
content = self.http_get('{}{}'.format(self.domain, url))
|
||||
api_key = self.re.search(r'this\.page\.identifier\s*=\s*[\'"](.+)[\'"]', content).group(1)
|
||||
url = '{}/leitor/pages/{}.json?key={}'.format(
|
||||
self.domain, self.chapter['release']['id_release'], api_key
|
||||
)
|
||||
images = self.json.loads(self.http_get(url, {'x-requested-with': 'XMLHttpRequest'}))
|
||||
return images['images']
|
||||
|
||||
def get_cover(self) -> str:
|
||||
return self._cover_from_content('.cover img.cover')
|
||||
|
||||
def book_meta(self) -> dict:
|
||||
pass
|
||||
|
||||
def chapter_for_json(self) -> str:
|
||||
return self.chapter['release']['link']
|
||||
|
||||
|
||||
main = SevenSamaCom
|
||||
67
manga-py-stable_1.x/manga_py/providers/8muses_com.py
Normal file
67
manga-py-stable_1.x/manga_py/providers/8muses_com.py
Normal file
@@ -0,0 +1,67 @@
|
||||
from manga_py.provider import Provider
|
||||
from .helpers import eight_muses_com
|
||||
from .helpers.std import Std
|
||||
|
||||
|
||||
class EightMusesCom(Provider, Std):
|
||||
_chapters = None
|
||||
chapter_selector = '.gallery a.c-tile[href^="/comics/"]'
|
||||
helper = None
|
||||
_images_path = 'image/fl'
|
||||
|
||||
def get_chapter_index(self) -> str:
|
||||
re = self.re.compile(r'/(?:album|picture)/([^/]+/[^/]+(?:/[^/]+)?)')
|
||||
ch = self.chapter
|
||||
if isinstance(ch, list) and len(ch) > 0:
|
||||
ch = ch[0]
|
||||
if isinstance(ch, dict):
|
||||
ch = ch.get('href')
|
||||
idx = re.search(ch).group(1)
|
||||
return '-'.join(idx.split('/'))
|
||||
|
||||
def get_main_content(self):
|
||||
return self.http_get(self.get_url())
|
||||
|
||||
def get_manga_name(self) -> str:
|
||||
return self._get_name('/album/([^/]+)')
|
||||
|
||||
def get_chapters(self):
|
||||
chapters = self._elements(self.chapter_selector)
|
||||
return self.helper.chapters(chapters)
|
||||
|
||||
def _parse_images(self, images) -> list:
|
||||
return ['{}/{}/{}'.format(
|
||||
self.domain,
|
||||
self._images_path,
|
||||
i.get('value')
|
||||
) for i in images if i.get('value')]
|
||||
|
||||
@staticmethod
|
||||
def _sort(items: dict) -> list:
|
||||
items = [items[i] for i in sorted(items, key=lambda x: int(x)) if len(items[i]) > 5]
|
||||
return list(set(items))
|
||||
|
||||
def get_files(self):
|
||||
images = {}
|
||||
_n = self.http().normalize_uri
|
||||
for n, i in enumerate(self.chapter):
|
||||
if n % 4 < 2:
|
||||
img = self.html_fromstring(_n(i.get('href')), '#imageName,#imageNextName')
|
||||
images[str(n)] = img[0]
|
||||
images[str(n + 2)] = img[1]
|
||||
return self._parse_images(self._sort(images))
|
||||
|
||||
def get_cover(self) -> str:
|
||||
pass
|
||||
|
||||
def prepare_cookies(self):
|
||||
self._chapters = []
|
||||
self._base_cookies()
|
||||
self.helper = eight_muses_com.EightMusesCom(self)
|
||||
|
||||
def book_meta(self) -> dict:
|
||||
# todo meta
|
||||
pass
|
||||
|
||||
|
||||
main = EightMusesCom
|
||||
63
manga-py-stable_1.x/manga_py/providers/README.md
Normal file
63
manga-py-stable_1.x/manga_py/providers/README.md
Normal file
@@ -0,0 +1,63 @@
|
||||
# All providers
|
||||
|
||||
### For template example, see _template.py
|
||||
|
||||
## Functions:
|
||||
|
||||
```python
|
||||
from manga_py.provider import Provider
|
||||
# from .helpers.std import Std
|
||||
|
||||
|
||||
class _Template(Provider):
|
||||
# class _Template(Provider, Std): # extends utils
|
||||
|
||||
def get_archive_name(self) -> str:
|
||||
pass
|
||||
|
||||
def get_chapter_index(self) -> str:
|
||||
pass
|
||||
|
||||
def get_main_content(self): # call once
|
||||
# return self._get_content('{}/manga/{}')
|
||||
pass
|
||||
|
||||
def prepare_cookies(self): # if site with cookie protect
|
||||
# self._storage['proxies'] = auto_proxy()
|
||||
|
||||
# self._storage['cookies'] = self.http().get_base_cookies(self.get_url()).get_dict() # base cookies
|
||||
pass
|
||||
|
||||
def get_manga_name(self) -> str:
|
||||
# return self._get_name('/manga/([^/]+)')
|
||||
return ''
|
||||
|
||||
def get_chapters(self): # call once
|
||||
# return self._elements('a.chapter')
|
||||
return []
|
||||
|
||||
def get_files(self): # call ever volume loop
|
||||
return []
|
||||
|
||||
def get_cover(self) -> str:
|
||||
# return self._cover_from_content('.cover img')
|
||||
pass
|
||||
|
||||
def book_meta(self) -> dict:
|
||||
"""
|
||||
:see http://acbf.wikia.com/wiki/Meta-data_Section_Definition
|
||||
:return {
|
||||
'author': str,
|
||||
'title': str,
|
||||
'annotation': str,
|
||||
'keywords': str,
|
||||
'cover': str,
|
||||
'rating': str,
|
||||
}
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
main = _Template
|
||||
|
||||
```
|
||||
18
manga-py-stable_1.x/manga_py/providers/_3asq_org.py
Normal file
18
manga-py-stable_1.x/manga_py/providers/_3asq_org.py
Normal file
@@ -0,0 +1,18 @@
|
||||
from .rawdevart_com import RawDevArtCom
|
||||
|
||||
|
||||
class ThreeAsqOrg(RawDevArtCom):
|
||||
|
||||
def get_chapter_index(self) -> str:
|
||||
return self.chapter.split('/')[-2]
|
||||
|
||||
def get_files(self):
|
||||
parser = self.html_fromstring(self.chapter)
|
||||
return self._images_helper(parser, 'img.wp-manga-chapter-img')
|
||||
|
||||
@property
|
||||
def chapter(self):
|
||||
return super().chapter + '?style=list'
|
||||
|
||||
|
||||
main = ThreeAsqOrg
|
||||
877
manga-py-stable_1.x/manga_py/providers/__init__.py
Normal file
877
manga-py-stable_1.x/manga_py/providers/__init__.py
Normal file
@@ -0,0 +1,877 @@
|
||||
import re
|
||||
import importlib
|
||||
|
||||
providers_list = {
|
||||
'1stkissmanga_com': [
|
||||
r'1stkissmanga\.com/manga/.',
|
||||
],
|
||||
'3asq_info': [
|
||||
r'3asq\.info/.',
|
||||
],
|
||||
'_3asq_org': [
|
||||
r'3asq\.org/.',
|
||||
],
|
||||
'7sama_com': [
|
||||
r'7sama\.com/manga/.',
|
||||
],
|
||||
# '8muses_com': [
|
||||
# r'8muses\.com/comics/album/.',
|
||||
# ],
|
||||
'ac_qq_com': [
|
||||
r'ac\.qq\.com/Comic.+?/id/\d',
|
||||
],
|
||||
'acomics_ru': [
|
||||
r'acomics\.ru/~.',
|
||||
],
|
||||
'adulto_seinagi_org': [
|
||||
r'adulto\.seinagi\.org/(series|read)/.',
|
||||
r'xanime-seduccion\.com/(series|read)/.',
|
||||
r'twistedhelscans\.com/(series|read)/.',
|
||||
r'reader\.evilflowers\.com/(series|read)/.',
|
||||
],
|
||||
'allhentai_ru': [
|
||||
r'allhentai\.ru/.',
|
||||
],
|
||||
'animextremist_com': [
|
||||
r'animextremist\.com/mangas-online/.',
|
||||
],
|
||||
'antisensescans_com': [
|
||||
r'antisensescans\.com/online/(series|read)/.',
|
||||
],
|
||||
'asmhentai_com': [
|
||||
r'asmhentai\.com/(g|gallery)/\d',
|
||||
],
|
||||
'atfbooru_ninja': [
|
||||
r'atfbooru\.ninja/posts.',
|
||||
],
|
||||
# 'authrone_com': [
|
||||
# r'authrone\.com/manga/.',
|
||||
# ],
|
||||
'bato_to': [
|
||||
r'bato\.to/(series|chapter)/\d',
|
||||
],
|
||||
'blogtruyen_com': [
|
||||
r'blogtruyen\.com/.',
|
||||
],
|
||||
'bns_shounen_ai_net': [
|
||||
r'bns\.shounen-ai\.net/read/(series|read)/.',
|
||||
],
|
||||
'boredomsociety_xyz': [
|
||||
r'boredomsociety\.xyz/(titles/info|reader)/\d',
|
||||
],
|
||||
'cdmnet_com_br': [
|
||||
r'cdmnet\.com\.br/titulos/.',
|
||||
],
|
||||
'chochox_com': [
|
||||
r'chochox\.com/.',
|
||||
],
|
||||
'choutensei_260mb_net': [
|
||||
r'choutensei\.260mb\.net/(series|read)/.',
|
||||
],
|
||||
'comicextra_com': [
|
||||
r'comicextra\.com/.',
|
||||
],
|
||||
# 'comico_co_id_content': [
|
||||
# r'comico\.co\.id/content\?contentId=\d',
|
||||
# ],
|
||||
'comico_co_id_titles': [
|
||||
r'comico\.co\.id/titles/\d',
|
||||
],
|
||||
'comic_webnewtype_com': [
|
||||
r'comic\.webnewtype\.com/contents/.',
|
||||
],
|
||||
'comico_jp': [
|
||||
r'comico\.jp(?:/challenge)?/(detail|articleList).+titleNo.',
|
||||
],
|
||||
'comicsandmanga_ru': [
|
||||
r'comicsandmanga\.ru/online-reading/.',
|
||||
],
|
||||
'comicvn_net': [
|
||||
r'comicvn\.net/truyen-tranh-online/.',
|
||||
],
|
||||
'cycomi_com': [
|
||||
r'cycomi\.com/fw/cycomibrowser/chapter/title/\d',
|
||||
],
|
||||
'danbooru_donmai_us': [
|
||||
r'danbooru\.donmai\.us/posts.',
|
||||
],
|
||||
'darkskyprojects_org': [
|
||||
r'darkskyprojects\.org/biblioteca/.',
|
||||
],
|
||||
'dejameprobar_es': [
|
||||
r'dejameprobar\.es/slide/.',
|
||||
r'menudo-fansub\.com/slide/.',
|
||||
r'npscan\.mangaea\.net/slide/.',
|
||||
r'snf\.mangaea\.net/slide/.',
|
||||
r'yuri-ism\.net/slide/.',
|
||||
],
|
||||
'desu_me': [
|
||||
r'desu\.me/manga/.',
|
||||
],
|
||||
'digitalteam1_altervista_org': [
|
||||
r'digitalteam1\.altervista\.org/reader/read/.',
|
||||
],
|
||||
# 'dm5_com': [
|
||||
# r'dm5\.com/manhua-.',
|
||||
# ],
|
||||
'doujins_com': [
|
||||
r'doujins\.com/gallery/.',
|
||||
r'doujin-moe\.us/gallery/.',
|
||||
],
|
||||
'e_hentai_org': [
|
||||
r'e-hentai\.org/g/\d',
|
||||
],
|
||||
'exhentai_org': [
|
||||
r'exhentai\.org/g/\d',
|
||||
],
|
||||
'fanfox_net': [
|
||||
r'fanfox\.net/manga/.',
|
||||
],
|
||||
'freeadultcomix_com': [
|
||||
r'freeadultcomix\.com/.',
|
||||
],
|
||||
'freemanga_to': [
|
||||
r'freemanga\.to/(manga|chapter)/.',
|
||||
],
|
||||
'funmanga_com': [
|
||||
r'funmanga\.com/.',
|
||||
],
|
||||
'gmanga_me': [
|
||||
r'gmanga\.me/mangas/.',
|
||||
],
|
||||
'gomanga_co': [
|
||||
r'gomanga\.co/reader/.',
|
||||
r'jaiminisbox\.com/reader/.',
|
||||
r'kobato\.hologfx\.com/reader/.',
|
||||
# r'atelierdunoir\.org/reader/.',
|
||||
r'seinagi\.org/reader/.',
|
||||
],
|
||||
'goodmanga_net': [
|
||||
r'goodmanga\.net/.',
|
||||
],
|
||||
'helveticascans_com': [
|
||||
r'helveticascans\.com/r/(series|read)/.',
|
||||
],
|
||||
'hakihome_com': [
|
||||
r'hakihome\.com/.',
|
||||
],
|
||||
'hatigarmscans_eu': [
|
||||
r'hatigarmscans\.eu/hs/(series|read).',
|
||||
r'hatigarmscans\.net/hs/(series|read).',
|
||||
r'hatigarmscans\.net/manga/.',
|
||||
],
|
||||
'heavenmanga_biz': [
|
||||
r'heavenmanga\.\w+/.',
|
||||
],
|
||||
'hentai2read_com': [
|
||||
r'hentai2read\.com/.',
|
||||
],
|
||||
'hentai_cafe': [
|
||||
r'hentai\.cafe/.',
|
||||
],
|
||||
'hentai_chan_me': [
|
||||
r'hentai-chan\.me/(related|manga|online)/.', # todo
|
||||
],
|
||||
'hentai_image_com': [
|
||||
r'hentai-image\.com/image/.',
|
||||
],
|
||||
'hentaihand_com': [
|
||||
r'hentaihand\.com/comic/\d',
|
||||
],
|
||||
'hentaifox_com': [
|
||||
r'hentaifox\.com/.',
|
||||
],
|
||||
'hentaihere_com': [
|
||||
r'hentaihere\.com/m/.',
|
||||
],
|
||||
'hentaiporns_net': [
|
||||
r'hentaiporns\.net/.'
|
||||
],
|
||||
'hentairead_com': [
|
||||
r'hentairead\.com/.',
|
||||
],
|
||||
'hitomi_la': [
|
||||
r'hitomi\.la/(galleries|reader)/.',
|
||||
],
|
||||
'hgamecg_com': [
|
||||
r'hgamecg\.com/index/category/\d',
|
||||
],
|
||||
'hitmanga_eu': [
|
||||
r'hitmanga\.eu/.',
|
||||
r'mymanga\.io/.',
|
||||
],
|
||||
'hocvientruyentranh_com': [
|
||||
r'hocvientruyentranh\.com/(manga|chapter)/.',
|
||||
],
|
||||
'hoducomics_com': [
|
||||
r'hoducomics\.com/webtoon/list/\d',
|
||||
r'hodu1\.com/webtoon/list/\d',
|
||||
],
|
||||
'hotchocolatescans_com': [
|
||||
r'hotchocolatescans\.com/fs/(series|read)/.',
|
||||
r'mangaichiscans\.mokkori\.fr/fs/(series|read)/.',
|
||||
r'taptaptaptaptap\.net/fs/(series|read)/.',
|
||||
],
|
||||
'riceballicious_info': [
|
||||
r'riceballicious\.info/fs/reader/(series|read)/.',
|
||||
],
|
||||
'rocaca_com': [
|
||||
r'rocaca\.com/manga/.',
|
||||
],
|
||||
'inmanga_com': [
|
||||
r'inmanga\.com/ver/manga/.',
|
||||
],
|
||||
'isekaiscan_com': [
|
||||
r'isekaiscan\.com/manga/.',
|
||||
],
|
||||
'japscan_com': [
|
||||
r'japscan\.to/.',
|
||||
],
|
||||
'jurnalu_ru': [
|
||||
r'jurnalu\.ru/online-reading/.',
|
||||
],
|
||||
'kissmanga_com': [
|
||||
r'kissmanga\.com/Manga/.',
|
||||
],
|
||||
'komikcast_com': [
|
||||
r'komikcast\.com/.',
|
||||
],
|
||||
'komikid_com': [
|
||||
r'komikid\.com/manga/.',
|
||||
r'mangazuki\.co/manga/.',
|
||||
r'mangaforest\.com/manga/.',
|
||||
r'mangadenizi\.com/.',
|
||||
r'mangadoor\.com/manga/.',
|
||||
r'manga\.fascans\.com/manga/.',
|
||||
r'mangadesu\.net/manga/.',
|
||||
r'mangahis\.com/manga/.',
|
||||
r'cmreader\.info/manga/.',
|
||||
r'rawmangaupdate\.com/manga/.',
|
||||
r'mangaraw\.online/manga/.',
|
||||
r'manhua-tr\.com/manga/.',
|
||||
r'manga-v2\.mangavadisi\.org/manga/.',
|
||||
r'universoyuri\.com/manga/.',
|
||||
r'digitalteam1\.altervista\.org/manga/.',
|
||||
# r'sosscanlation\.com/manga/.',
|
||||
r'komikgue\.com/manga/.',
|
||||
r'onma\.me/manga/.',
|
||||
],
|
||||
'kumanga_com': [
|
||||
r'kumanga\.com/manga/\d',
|
||||
],
|
||||
'lector_kirishimafansub_com': [
|
||||
r'lector\.kirishimafansub\.com/(lector/)?(series|read)/.',
|
||||
],
|
||||
'leitor_net': [
|
||||
r'leitor\.net/manga/.',
|
||||
],
|
||||
'leomanga_com': [
|
||||
r'leomanga\.com/manga/.',
|
||||
],
|
||||
'leviatanscans_com': [
|
||||
r'leviatanscans\.com/comics/\d'
|
||||
],
|
||||
'lhtranslation_com': [
|
||||
r'read\.lhtranslation\.com/(truyen|manga)-.',
|
||||
r'lhtranslation\.net/(truyen|manga)-.',
|
||||
],
|
||||
'lolibooru_moe': [
|
||||
r'lolibooru\.moe/post.',
|
||||
],
|
||||
'lolivault_net': [
|
||||
r'lolivault\.net/online/(series|read).',
|
||||
],
|
||||
'luscious_net': [
|
||||
r'luscious\.net/.+/album/.',
|
||||
r'luscious\.net/albums/.',
|
||||
],
|
||||
'mangapark_org': [
|
||||
r'mangapark\.org/(series|chapter)/', # is different!
|
||||
],
|
||||
'mang_as': [
|
||||
r'mang\.as/manga/.',
|
||||
],
|
||||
'manga_ae': [
|
||||
r'mangaae\.com/.',
|
||||
],
|
||||
'manga_fox_com': [
|
||||
r'manga-fox\.com/.',
|
||||
r'manga-here\.io/.',
|
||||
],
|
||||
'manga_mexat_com': [
|
||||
r'manga\.mexat\.com/category/.',
|
||||
],
|
||||
'manga_online_biz': [
|
||||
r'manga-online\.biz/.',
|
||||
],
|
||||
'manga_online_com_ua': [
|
||||
r'manga-online\.com\.ua/.+html',
|
||||
],
|
||||
'manga_room_com': [
|
||||
r'manga-room\.com/manga/.',
|
||||
],
|
||||
'manga_sh': [
|
||||
r'manga\.sh/comics/.',
|
||||
],
|
||||
'manga_tube_me': [
|
||||
r'manga-tube\.me/series/.',
|
||||
],
|
||||
'mangaarabteam_com': [
|
||||
r'mangaarabteam\.com/.',
|
||||
],
|
||||
'manga_tr_com': [
|
||||
r'manga-tr\.com/(manga|id)-.',
|
||||
],
|
||||
'mangabat_com': [
|
||||
r'mangabat\.com/(manga|chapter)/.',
|
||||
],
|
||||
'mangabb_co': [
|
||||
r'mangabb\.co/.',
|
||||
],
|
||||
'mangabox_me': [
|
||||
r'mangabox\.me/reader/.',
|
||||
],
|
||||
'mangachan_me': [
|
||||
r'mangachan\.me/(related|manga|online)/.',
|
||||
r'yaoichan\.me/(manga|online).',
|
||||
],
|
||||
'mangachan_me_download': [
|
||||
r'mangachan\.me/download/.',
|
||||
r'hentai-chan\.me/download/.',
|
||||
r'yaoichan\.me/download/.',
|
||||
],
|
||||
'mangacanblog_com': [
|
||||
r'mangacanblog\.com/.',
|
||||
],
|
||||
'mangaclub_ru': [
|
||||
r'mangaclub\.ru/.',
|
||||
],
|
||||
'mangadeep_com': [
|
||||
r'mangadeep\.com/.',
|
||||
r'manga99\.com/.',
|
||||
],
|
||||
'mangadex_org': [
|
||||
r'mangadex\.org/manga/.',
|
||||
],
|
||||
'mangadex_com': [
|
||||
r'mangadex\.com/(title|chapter)/.',
|
||||
r'mangadex\.org/(title|chapter)/.',
|
||||
],
|
||||
'mangadex_info': [
|
||||
r'mangadex\.info/manga/.',
|
||||
],
|
||||
'mangaeden_com': [
|
||||
r'mangaeden\.com/[^/]+/[^/]+-manga/.',
|
||||
r'perveden\.com/[^/]+/[^/]+-manga/.',
|
||||
],
|
||||
'mangafans_us': [ # MangaNeloCom
|
||||
r'mangafans\.us/manga/.',
|
||||
r'mangahot\.org/read-manga/.',
|
||||
],
|
||||
# 'mangaforall_com': [
|
||||
# r'mangaforall\.com/m/.',
|
||||
# ],
|
||||
'mangafreak_net_download': [
|
||||
r'mangafreak\.net/Manga/.',
|
||||
],
|
||||
'mangafull_org': [
|
||||
r'mangafull\.org/manga/.',
|
||||
],
|
||||
# 'mangago_me': [
|
||||
# r'mangago\.me/read-manga/.',
|
||||
# ],
|
||||
'mangahasu_se': [
|
||||
r'mangahasu\.se/.',
|
||||
],
|
||||
'mangaheaven_club': [
|
||||
r'mangaheaven\.club/read-manga/.',
|
||||
],
|
||||
'mangaheaven_xyz': [
|
||||
r'mangaheaven\.xyz/manga/.',
|
||||
],
|
||||
'mangahere_cc': [
|
||||
r'mangahere\.co/manga/.',
|
||||
r'mangahere\.cc/manga/.',
|
||||
],
|
||||
'mangahi_net': [
|
||||
r'mangahi\.net/.',
|
||||
],
|
||||
'mangaid_me': [
|
||||
r'mangaid\.co/manga/.',
|
||||
r'mangaid\.net/manga/.',
|
||||
r'mangaid\.me/manga/.',
|
||||
],
|
||||
'mangahome_com': [
|
||||
r'mangahome\.com/manga/.',
|
||||
],
|
||||
'mangahub_io': [
|
||||
r'mangahub\.io/(manga|chapter)/.',
|
||||
# r'mangareader\.site/(manga|chapter)/.',
|
||||
r'mangakakalot\.fun/(manga|chapter)/.',
|
||||
r'mangahere\.onl/(manga|chapter)/.',
|
||||
],
|
||||
'mangahub_ru': [
|
||||
r'mangahub\.ru/.',
|
||||
],
|
||||
'mangaindo_web_id': [
|
||||
r'mangaindo\.web\.id/.',
|
||||
],
|
||||
'mangainn_net': [
|
||||
r'mangainn\.net/.',
|
||||
],
|
||||
'mangajinnofansub_com': [ # normal
|
||||
r'mangajinnofansub\.com/lector/(series|read)/.',
|
||||
],
|
||||
'mangakakalot_com': [
|
||||
r'mangakakalot\.com/(manga|chapter)/.',
|
||||
],
|
||||
'mangakatana_com': [
|
||||
r'mangakatana\.com/manga/.',
|
||||
],
|
||||
'mangaku_web_id': [
|
||||
# r'mangaku\.web\.id/.',
|
||||
r'mangaku\.in/.',
|
||||
],
|
||||
'mangalib_me': [
|
||||
r'mangalib\.me/.',
|
||||
],
|
||||
'mangalife_us': [
|
||||
r'mangalife\.us/(read-online|manga)/.',
|
||||
],
|
||||
'mangamew_com': [
|
||||
r'mangamew\.com/(\w+-)?manga/.',
|
||||
],
|
||||
'mangamew_com_vn': [
|
||||
r'mangamew\.com/(\w+-)?truyen/.',
|
||||
],
|
||||
'manganelo_com': [
|
||||
r'manganelo\.com/(manga|chapter)/.',
|
||||
],
|
||||
'mangaon_net': [
|
||||
r'mangaon\.net/(manga-info|read-online)/.',
|
||||
],
|
||||
'mangaonline_com_br': [
|
||||
r'mangaonline\.com\.br/.',
|
||||
],
|
||||
'mangaonline_today': [
|
||||
r'mangaonline\.today/.',
|
||||
],
|
||||
'mangaonlinehere_com': [
|
||||
r'mangaonlinehere\.com/(manga-info|read-online)/.',
|
||||
],
|
||||
'mangapanda_com': [
|
||||
r'mangapanda\.com/.',
|
||||
],
|
||||
'mangapark_me': [
|
||||
r'mangapark\.me/manga/.',
|
||||
],
|
||||
'mangareader_net': [
|
||||
r'mangareader\.net/.',
|
||||
],
|
||||
'mangareader_site': [
|
||||
r'mangareader\.site',
|
||||
],
|
||||
'mangareader_xyz': [
|
||||
r'mangareader\.xyz/manga/.',
|
||||
r'mangareader\.xyz/.+?/chapter-\d',
|
||||
# r'mangafox\.cc/manga/.',
|
||||
# r'mangafox\.cc/.+?/chapter-\d',
|
||||
],
|
||||
'mangarock_com': [
|
||||
r'mangarock\.com/manga/.',
|
||||
],
|
||||
'mangarussia_com': [
|
||||
r'mangarussia\.com/(manga|chapter)/.',
|
||||
],
|
||||
'mangasaurus_com': [
|
||||
r'mangasaurus\.com/(manga|view).',
|
||||
],
|
||||
'mangaseeonline_us': [
|
||||
r'mangaseeonline\.us/(read-online|manga)/.',
|
||||
],
|
||||
'mangashiro_net': [
|
||||
r'mangashiro\.net/.',
|
||||
],
|
||||
'mangasupa_com': [
|
||||
r'mangasupa\.com/(manga|chapter)/.',
|
||||
],
|
||||
'mangasushi_net': [
|
||||
r'mangasushi\.net/manga/.',
|
||||
],
|
||||
'mangatail_com': [
|
||||
r'mangasail\.com/(manga|chapter|node|content)/.',
|
||||
r'mangasail\.co/(manga|chapter|node|content)/.',
|
||||
r'mangatail\.me/(manga|chapter|node|content)/.',
|
||||
],
|
||||
'mangatown_com': [
|
||||
r'mangatown\.com/manga/.',
|
||||
],
|
||||
'mangatrue_com': [
|
||||
r'mangatrue\.com/manga/.',
|
||||
r'mangaall\.com/manga/.',
|
||||
],
|
||||
'mangawindow_net': [
|
||||
r'mangawindow\.net/(series|chapter)/\d', # is different!
|
||||
],
|
||||
'mangax_net': [
|
||||
r'mangax\.net/\w/.',
|
||||
],
|
||||
'mangazuki_me': [
|
||||
r'mangazuki\.me/manga/.',
|
||||
r'mangazuki\.info/manga/.',
|
||||
r'mangazuki\.online/manga/.',
|
||||
],
|
||||
'manhuagui_com': [
|
||||
r'manhuagui\.com/comic/\d',
|
||||
],
|
||||
'manhuatai_com': [
|
||||
r'manhuatai\.com/.',
|
||||
],
|
||||
'manhwa_co': [
|
||||
r'manhwa\.co/.',
|
||||
],
|
||||
# 'manhwahentai_com': [
|
||||
# r'manhwahentai\.com/manhwa/.'
|
||||
# ],
|
||||
'merakiscans_com': [
|
||||
r'merakiscans\.com/manga/.',
|
||||
],
|
||||
'mintmanga_com': [
|
||||
r'mintmanga\.com/.',
|
||||
],
|
||||
'mngcow_co': [
|
||||
r'mngcow\.co/.',
|
||||
],
|
||||
'mngdoom_com': [
|
||||
r'mangadoom\.co/.',
|
||||
r'mngdoom\.com/.',
|
||||
],
|
||||
'mymangalist_org': [
|
||||
r'mymangalist.org/(read|chapter)-',
|
||||
],
|
||||
'myreadingmanga_info': [
|
||||
r'myreadingmanga\.info/.',
|
||||
],
|
||||
'neumanga_tv': [
|
||||
r'neumanga\.tv/manga/.',
|
||||
],
|
||||
'nhentai_net': [
|
||||
r'nhentai\.net/g/.',
|
||||
],
|
||||
'niadd_com': [
|
||||
r'niadd\.com/manga/.',
|
||||
],
|
||||
'nightow_net': [
|
||||
r'nightow\.net/online/\?manga=.',
|
||||
],
|
||||
'nineanime_com': [
|
||||
r'nineanime\.com/manga/.+\.html'
|
||||
],
|
||||
'ninemanga_com': [
|
||||
r'ninemanga\.com/(manga|chapter).',
|
||||
r'addfunny\.com/(manga|chapter).',
|
||||
],
|
||||
'noranofansub_com': [
|
||||
r'noranofansub\.com(/lector)?/(series/|read/)?.',
|
||||
],
|
||||
'nozominofansub_com': [ # mangazuki_co
|
||||
r'nozominofansub\.com/public(/index\.php)?/manga/.',
|
||||
r'godsrealmscan\.com/public(/index\.php)?/manga/.',
|
||||
],
|
||||
# 'nude_moon_me': [
|
||||
# r'nude-moon\.me/\d',
|
||||
# ],
|
||||
'otakusmash_com': [
|
||||
r'otakusmash\.com/.',
|
||||
r'mrsmanga\.com/.',
|
||||
r'mentalmanga\.com/.',
|
||||
r'mangasmash\.com/.',
|
||||
r'omgbeaupeep\.com/comics/.',
|
||||
],
|
||||
'otscans_com': [
|
||||
r'otscans\.com/foolslide/(series|read)/.',
|
||||
],
|
||||
'pecintakomik_com_manga': [
|
||||
r'pecintakomik\.com/manga/.',
|
||||
],
|
||||
'pecintakomik_com': [
|
||||
r'pecintakomik\.com/.',
|
||||
],
|
||||
'plus_comico_jp_manga': [
|
||||
r'plus\.comico\.jp/manga/\d',
|
||||
],
|
||||
'plus_comico_jp': [
|
||||
r'plus\.comico\.jp/store/\d',
|
||||
],
|
||||
'porncomix_info': [
|
||||
r'porncomix\.info/.',
|
||||
],
|
||||
'psychoplay_co': [
|
||||
r'psychoplay\.co/(series|read)/.',
|
||||
],
|
||||
'puzzmos_com': [
|
||||
r'puzzmos\.com/manga/.',
|
||||
],
|
||||
r'pururin_io': [
|
||||
r'pururin\.io/(gallery|read)/.',
|
||||
],
|
||||
'pzykosis666hfansub_com': [
|
||||
r'pzykosis666hfansub\.com/online/.',
|
||||
],
|
||||
'ravens_scans_com': [
|
||||
r'ravens-scans\.com(/lector)?/(serie/|read/).',
|
||||
],
|
||||
'raw_senmanga_com': [
|
||||
r'raw\.senmanga\.com/.',
|
||||
],
|
||||
'rawdevart_com': [
|
||||
r'rawdevart\.com/manga/.',
|
||||
],
|
||||
'rawlh_com': [
|
||||
r'lhscan\.net/(truyen|manga|read)-.',
|
||||
r'rawqq\.com/(truyen|manga|read)-.',
|
||||
r'rawqv\.com/(truyen|manga|read)-.',
|
||||
],
|
||||
'rawneko_com': [
|
||||
r'rawneko\.com/manga/.',
|
||||
],
|
||||
'read_egscans_com': [
|
||||
r'read\.egscans\.com/.',
|
||||
],
|
||||
'read_powermanga_org': [
|
||||
r'lector\.dangolinenofansub\.com/(series|read)/.',
|
||||
r'read\.powermanga\.org/(series|read)/.',
|
||||
# r'read\.yagami\.me/(series|read)/.',
|
||||
r'reader\.kireicake\.com/(series|read)/.',
|
||||
r'reader\.shoujosense\.com/(series|read)/.',
|
||||
r'reader\.whiteoutscans\.com/(series|read)/.',
|
||||
r'slide\.world-three\.org/(series|read)/.',
|
||||
r'manga\.animefrontline\.com/(series|read)/.',
|
||||
r'reader\.s2smanga\.com/(series|read)/.',
|
||||
r'reader\.seaotterscans\.com/(series|read)/.',
|
||||
r'reader\.idkscans\.com/(series|read)/.',
|
||||
r'reader\.thecatscans\.com/(series|read)/.',
|
||||
r'reader\.deathtollscans\.net/(series|read)/.',
|
||||
r'lector\.ytnofan\.com/(series|read)/.',
|
||||
r'reader\.jokerfansub\.com/(series|read)/.',
|
||||
r'lector\.patyscans\.com/(series|read)/.',
|
||||
r'truecolorsscans\.miocio\.org/(series|read)/.',
|
||||
r'reader\.letitgo\.scans\.today/(series|read)/.',
|
||||
r'reader\.fos-scans\.com/(series|read)/.',
|
||||
r'reader\.serenade\.moe/(series|read)/.',
|
||||
r'reader\.vortex-scans\.com/(series|read)/.',
|
||||
r'reader\.roseliascans\.com/(series|read)/.',
|
||||
r'reader\.silentsky-scans\.net/(series|read)/.',
|
||||
r'hoshiscans\.shounen-ai\.net/(series|read)/.',
|
||||
r'digitalteamreader\.netsons\.org/(series|read)/.',
|
||||
r'reader\.manga-download\.org/(series|read)/.',
|
||||
],
|
||||
'read_yagami_me': [
|
||||
r'read\.yagami\.me/series/\w',
|
||||
],
|
||||
# 'readcomicbooksonline_org_manga': [ # todo #168
|
||||
# r'readcomicbooksonline\.net/manga/.',
|
||||
# r'readcomicbooksonline\.org/manga/.',
|
||||
# ],
|
||||
# 'readcomicbooksonline_org': [
|
||||
# r'readcomicbooksonline\.net/.',
|
||||
# r'readcomicbooksonline\.org/.',
|
||||
# ],
|
||||
'comicpunch_net_manga': [
|
||||
r'comicpunch\.net/asiancomics/.',
|
||||
],
|
||||
'comicpunch_net': [
|
||||
r'comicpunch\.net/.',
|
||||
],
|
||||
'reader_championscans_com': [
|
||||
r'reader\.championscans\.com/(series|read)/.',
|
||||
],
|
||||
'reader_imangascans_org': [
|
||||
r'reader\.imangascans\.org/.',
|
||||
],
|
||||
# 'readhentaimanga_com': [
|
||||
# r'readhentaimanga\.com/.',
|
||||
# ],
|
||||
'readcomiconline_to': [
|
||||
r'readcomiconline\.to/Comic/.',
|
||||
],
|
||||
'readcomicsonline_ru': [
|
||||
r'readcomicsonline\.ru/comic/.',
|
||||
],
|
||||
'readmanga_me': [
|
||||
r'readmanga\.me/.',
|
||||
],
|
||||
'readmanga_eu': [
|
||||
r'readmanga\.eu/manga/\d+/.',
|
||||
],
|
||||
'readmng_com': [
|
||||
r'readmng\.com/.',
|
||||
],
|
||||
'readms_net': [
|
||||
r'readms\.net/(r|manga)/.',
|
||||
],
|
||||
'remanga_org': [
|
||||
r'remanga\.org/manga/.',
|
||||
],
|
||||
'santosfansub_com': [
|
||||
r'santosfansub\.com/Slide/.',
|
||||
],
|
||||
'selfmanga_ru': [
|
||||
r'selfmanga\.ru/.',
|
||||
],
|
||||
'senmanga_com': [
|
||||
r'senmanga\.com/.',
|
||||
],
|
||||
'shakai_ru': [
|
||||
r'shakai\.ru/manga.*?/\d',
|
||||
],
|
||||
'shogakukan_co_jp': [
|
||||
r'shogakukan\.co\.jp/books/\d',
|
||||
r'shogakukan\.co\.jp/magazines/series/\d',
|
||||
],
|
||||
'shogakukan_tameshiyo_me': [
|
||||
r'shogakukan\.tameshiyo\.me/\d',
|
||||
],
|
||||
'siberowl_com': [
|
||||
r'siberowl\.com/mangas/.',
|
||||
],
|
||||
'sleepypandascans_co': [
|
||||
r'sleepypandascans\.co/(Series|Reader)/.',
|
||||
],
|
||||
#'somanga_net': [
|
||||
# r'somanga\.net/(leitor|manga)/.',
|
||||
# r'somangas\.net/(leitor|manga)/.',
|
||||
#],
|
||||
'subapics_com': [
|
||||
# r'subapics\.com/manga/.',
|
||||
# r'subapics\.com/.+-chapter-.',
|
||||
r'mangakita\.net/manga/.',
|
||||
r'mangakita\.net/.+-chapter-.',
|
||||
r'komikstation\.com/manga/.',
|
||||
r'komikstation\.com/.+-chapter-.',
|
||||
r'mangavy\.com/manga/.',
|
||||
r'mangavy\.com/.+-chapter-.',
|
||||
r'mangakid\.net/manga/.',
|
||||
r'mangakid\.net/.+-chapter-.',
|
||||
],
|
||||
'submanga_online': [
|
||||
r'submanga\.online/manga/.',
|
||||
],
|
||||
'sunday_webry_com': [
|
||||
r'sunday-webry\.com/series/\d',
|
||||
],
|
||||
'taadd_com': [
|
||||
r'taadd\.com/(book|chapter)/.',
|
||||
],
|
||||
'tapas_io': [
|
||||
r'tapas\.io/episode/\d',
|
||||
r'tapas\.io/series/\w',
|
||||
],
|
||||
'tenmanga_com': [
|
||||
r'tenmanga\.com/(book|chapter)/.',
|
||||
],
|
||||
'tmofans_com': [
|
||||
r'tmofans\.com/library/manga/\d',
|
||||
],
|
||||
'translate_webtoons_com': [
|
||||
r'translate\.webtoons\.com/webtoonVersion\?webtoonNo.',
|
||||
],
|
||||
'trashscanlations_com': [
|
||||
r'trashscanlations\.com/series/.',
|
||||
],
|
||||
'tonarinoyj_jp': [
|
||||
r'tonarinoyj\.jp/episode/.',
|
||||
],
|
||||
'toonkor_co': [
|
||||
r'toonkor\.co/.',
|
||||
],
|
||||
'triplesevenscans_com': [
|
||||
r'sensescans\.com/reader/(series|read)/.',
|
||||
r'triplesevenscans\.com/reader/(series|read)/.',
|
||||
r'cm-scans\.shounen-ai\.net/reader/(series|read)/.',
|
||||
r'yaoislife\.shounen-ai\.net/reader/(series|read)/.',
|
||||
r'fujoshibitches\.shounen-ai\.net/reader/(series|read)/.',
|
||||
],
|
||||
'truyen_vnsharing_site': [
|
||||
r'truyen\.vnsharing\.site/index/read/.',
|
||||
],
|
||||
'truyenchon_com': [
|
||||
r'truyenchon\.com/truyen/.',
|
||||
r'nettruyen\.com/truyen-tranh/.',
|
||||
],
|
||||
'truyentranhtuan_com': [
|
||||
r'truyentranhtuan\.com/.',
|
||||
],
|
||||
'tsumino_com': [
|
||||
r'tsumino\.com/Book/Info/\d',
|
||||
r'tsumino\.com/Read/View/\d',
|
||||
],
|
||||
# 'tumangaonline_com': [
|
||||
# r'tumangaonline\.com/.',
|
||||
# r'tumangaonline\.me/.',
|
||||
# ],
|
||||
'unionmangas_net': [
|
||||
r'unionmangas\.cc/(leitor|manga)/.',
|
||||
r'unionmangas\.net/(leitor|manga)/.',
|
||||
r'unionmangas\.site/(leitor|manga)/.',
|
||||
],
|
||||
'viz_com': [
|
||||
r'viz\.com/shonenjump/chapters/.',
|
||||
],
|
||||
'web_ace_jp': [
|
||||
r'web-ace\.jp/youngaceup/contents/\d',
|
||||
],
|
||||
'webtoon_bamtoki_com': [
|
||||
r'webtoon\.bamtoki\.com/.',
|
||||
r'webtoon\.bamtoki\.se/.',
|
||||
],
|
||||
'webtoons_com': [
|
||||
r'webtoons\.com/[^/]+/[^/]+/.',
|
||||
],
|
||||
'webtoontr_com': [
|
||||
r'webtoontr\.com/_/.',
|
||||
],
|
||||
'westmanga_info': [
|
||||
r'westmanga\.info/.',
|
||||
],
|
||||
'whitecloudpavilion_com': [
|
||||
r'whitecloudpavilion\.com/manga/free/manga/.',
|
||||
],
|
||||
'wiemanga_com': [
|
||||
r'wiemanga\.com/(manga|chapter)/.',
|
||||
],
|
||||
'wmanga_ru': [
|
||||
r'wmanga\.ru/starter/manga_.',
|
||||
],
|
||||
'yande_re': [
|
||||
r'yande\.re/post.',
|
||||
],
|
||||
'zeroscans_com': [
|
||||
r'zeroscans\.com/manga/.',
|
||||
r'manhwareader\.com/manga/.',
|
||||
],
|
||||
'zingbox_me': [
|
||||
r'zingbox\.me/.',
|
||||
],
|
||||
'zip_read_com': [
|
||||
r'zip-read\.com/.',
|
||||
],
|
||||
'zmanga_net': [
|
||||
r'zmanga\.net/.',
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
def __check_provider(provider, url):
|
||||
items = [r'\b' + i for i in provider]
|
||||
reg = '(?:' + '|'.join(items) + ')'
|
||||
return re.search(reg, url)
|
||||
|
||||
|
||||
def get_provider(url):
|
||||
fromlist = 'manga_py.providers'
|
||||
for i in providers_list:
|
||||
if __check_provider(providers_list[i], url):
|
||||
provider = importlib.import_module('%s.%s' % (fromlist, i))
|
||||
return provider.main
|
||||
return False
|
||||
50
manga-py-stable_1.x/manga_py/providers/_template.py
Normal file
50
manga-py-stable_1.x/manga_py/providers/_template.py
Normal file
@@ -0,0 +1,50 @@
|
||||
from manga_py.provider import Provider
|
||||
from .helpers.std import Std
|
||||
|
||||
|
||||
class _Template(Provider, Std):
|
||||
|
||||
def get_archive_name(self) -> str:
|
||||
pass
|
||||
|
||||
def get_chapter_index(self) -> str:
|
||||
pass
|
||||
|
||||
def get_main_content(self):
|
||||
pass
|
||||
|
||||
def get_manga_name(self) -> str:
|
||||
return ''
|
||||
|
||||
def get_chapters(self):
|
||||
# return self._elements('a.chapter')
|
||||
return []
|
||||
|
||||
def get_files(self):
|
||||
return []
|
||||
|
||||
def get_cover(self) -> str:
|
||||
# return self._cover_from_content('.cover img')
|
||||
pass
|
||||
|
||||
def book_meta(self) -> dict:
|
||||
"""
|
||||
:see http://acbf.wikia.com/wiki/Meta-data_Section_Definition
|
||||
return {
|
||||
'author': str,
|
||||
'title': str,
|
||||
'annotation': str,
|
||||
'keywords': str,
|
||||
'cover': str,
|
||||
'rating': str,
|
||||
}
|
||||
"""
|
||||
pass
|
||||
|
||||
def chapter_for_json(self) -> str:
|
||||
# overload std param, if need
|
||||
# return self.chapter
|
||||
pass
|
||||
|
||||
|
||||
main = _Template
|
||||
52
manga-py-stable_1.x/manga_py/providers/ac_qq_com.py
Normal file
52
manga-py-stable_1.x/manga_py/providers/ac_qq_com.py
Normal file
@@ -0,0 +1,52 @@
|
||||
from manga_py.crypt import AcQqComCrypt
|
||||
from manga_py.provider import Provider
|
||||
from .helpers.std import Std
|
||||
|
||||
|
||||
class AcQqCom(Provider, Std):
|
||||
_decoder = None
|
||||
_re = None
|
||||
|
||||
def get_chapter_index(self) -> str:
|
||||
return self.re.search(r'/cid/(\d+)', self.chapter).group(1)
|
||||
|
||||
def get_main_content(self):
|
||||
content = self._storage.get('main_content', None)
|
||||
if content is not None:
|
||||
return content
|
||||
idx = self._get_name(r'/id/(\d+)')
|
||||
return self.http_get('{}/Comic/comicInfo/id/{}'.format(self.domain, idx))
|
||||
|
||||
def get_manga_name(self) -> str:
|
||||
return self.text_content(self.content, '.works-intro-title strong', 0)
|
||||
|
||||
def get_chapters(self):
|
||||
return self._elements('.chapter-page-all li a')[::-1]
|
||||
|
||||
def get_files(self):
|
||||
content = self.http_get(self.chapter)
|
||||
data = self._re.search(content).group(1)
|
||||
data = self._decoder.decode(data)
|
||||
return [i.get('url') for i in data.get('picture', [])][0:1]
|
||||
|
||||
def get_cover(self) -> str:
|
||||
return self._cover_from_content('.works-cover img')
|
||||
|
||||
def prepare_cookies(self):
|
||||
self._re = self.re.compile(r'var\s+DATA\s*=\s*[\'"](.*?)[\'"]')
|
||||
self._decoder = AcQqComCrypt(self)
|
||||
self._base_cookies()
|
||||
|
||||
def book_meta(self) -> dict:
|
||||
result = {
|
||||
'author': self.text_content(self.content, '.works-intro-digi em'),
|
||||
'rating': self.text_content(self.content, 'p.ui-left strong'),
|
||||
'cover': self.get_cover(),
|
||||
'annotation': self.text_content(self.content, '.works-intro-short'),
|
||||
'language': 'cn',
|
||||
}
|
||||
|
||||
return result
|
||||
|
||||
|
||||
main = AcQqCom
|
||||
49
manga-py-stable_1.x/manga_py/providers/acomics_ru.py
Normal file
49
manga-py-stable_1.x/manga_py/providers/acomics_ru.py
Normal file
@@ -0,0 +1,49 @@
|
||||
from manga_py.provider import Provider
|
||||
from .helpers.std import Std
|
||||
|
||||
|
||||
class AComicsRu(Provider, Std):
|
||||
|
||||
def get_archive_name(self) -> str:
|
||||
return 'archive'
|
||||
|
||||
def get_chapter_index(self) -> str:
|
||||
return '0'
|
||||
|
||||
def get_main_content(self):
|
||||
return self._get_content('{}/~{}')
|
||||
|
||||
def get_manga_name(self) -> str:
|
||||
return self._get_name(r'\.ru/~([^/]+)')
|
||||
|
||||
def get_chapters(self):
|
||||
return ['~' + self.manga_name]
|
||||
|
||||
def get_files(self):
|
||||
pages_max = self.text_content(self.content, 'span.issueNumber').split('/')[1]
|
||||
_min = self._params['skip_volumes']
|
||||
_max = self._params['max_volumes']
|
||||
if _max > 0 and _min > 0:
|
||||
_max += _min - 1
|
||||
|
||||
if _max == 0:
|
||||
_max = int(pages_max)
|
||||
|
||||
images = []
|
||||
for i in range(_min, _max):
|
||||
parser = self.document_fromstring(self._get_content('{}/~{}/%d' % (i + 1)))
|
||||
images += self._images_helper(parser, '#mainImage')
|
||||
|
||||
return images
|
||||
|
||||
def get_cover(self) -> str:
|
||||
return self._cover_from_content('header.serial a img')
|
||||
|
||||
def book_meta(self) -> dict:
|
||||
pass
|
||||
|
||||
def prepare_cookies(self):
|
||||
self.update_cookies({'ageRestrict': '21'})
|
||||
|
||||
|
||||
main = AComicsRu
|
||||
@@ -0,0 +1,9 @@
|
||||
from .read_powermanga_org import ReadPowerMangaOrg
|
||||
|
||||
|
||||
class AdultoSeinagiOrg(ReadPowerMangaOrg):
|
||||
_name_re = '[^/]/[^/]+/([^/]+)/'
|
||||
_content_str = '{}/series/{}/'
|
||||
|
||||
|
||||
main = AdultoSeinagiOrg
|
||||
64
manga-py-stable_1.x/manga_py/providers/allhentai_ru.py
Normal file
64
manga-py-stable_1.x/manga_py/providers/allhentai_ru.py
Normal file
@@ -0,0 +1,64 @@
|
||||
from manga_py.provider import Provider
|
||||
from .helpers.std import Std
|
||||
|
||||
|
||||
class AllHentaiRu(Provider, Std):
|
||||
|
||||
def get_archive_name(self):
|
||||
name = self.re.search('/.+/([^/]+/[^/]+)/?', self.chapter)
|
||||
return self.normal_arc_name({'vol': name.group(1).split('/', 2)})
|
||||
|
||||
def get_chapter_index(self):
|
||||
name = self.re.search('/.+/(?:vol)?([^/]+/[^/]+)/?', self.chapter)
|
||||
return name.group(1).replace('/', '-')
|
||||
|
||||
def get_main_content(self):
|
||||
return self._get_content('{}/{}?mature=1&mtr=1')
|
||||
|
||||
def get_manga_name(self) -> str:
|
||||
return self._get_name(r'\.ru/([^/]+)')
|
||||
|
||||
def get_chapters(self):
|
||||
return self._elements('.expandable .cTable tr > td > a')
|
||||
|
||||
def get_files(self):
|
||||
_uri = self.http().normalize_uri(self.chapter)
|
||||
content = self.http_get(_uri)
|
||||
result = self.re.search(r'var pictures.+?(\[\{.+\}\])', content, self.re.M)
|
||||
if not result:
|
||||
return []
|
||||
content = result.group(1).replace("'", '"')
|
||||
content = self.re.sub('(\w*):([^/])', r'"\1":\2', content)
|
||||
return [i['url'] for i in self.json.loads(content)]
|
||||
|
||||
def get_cover(self):
|
||||
return self._cover_from_content('.picture-fotorama > img')
|
||||
|
||||
def save_file(self, idx=None, callback=None, url=None, in_arc_name=None):
|
||||
_path = None
|
||||
try:
|
||||
_path = super().save_file(idx, callback, url, in_arc_name)
|
||||
except AttributeError:
|
||||
pass
|
||||
if _path is None:
|
||||
for i in ['a', 'b', 'c']:
|
||||
try:
|
||||
_path, idx, _url = self._save_file_params_helper(url, idx)
|
||||
_url = self.re.sub(r'//\w\.', '//%s.' % i, url)
|
||||
|
||||
self.http().download_file(_url, _path, idx)
|
||||
callable(callback) and callback()
|
||||
self.after_file_save(_path, idx)
|
||||
|
||||
self._archive.lazy_add(_path)
|
||||
break
|
||||
except AttributeError:
|
||||
pass
|
||||
return _path
|
||||
|
||||
def book_meta(self) -> dict:
|
||||
# todo meta
|
||||
pass
|
||||
|
||||
|
||||
main = AllHentaiRu
|
||||
46
manga-py-stable_1.x/manga_py/providers/animextremist_com.py
Normal file
46
manga-py-stable_1.x/manga_py/providers/animextremist_com.py
Normal file
@@ -0,0 +1,46 @@
|
||||
from manga_py.provider import Provider
|
||||
from .helpers import animextremist_com
|
||||
from .helpers.std import Std
|
||||
|
||||
|
||||
class AnimeXtremistCom(Provider, Std):
|
||||
helper = None
|
||||
prefix = '/mangas-online/'
|
||||
|
||||
def get_chapter_index(self) -> str:
|
||||
chapter = self.chapter
|
||||
idx = self.re.search(r'(.+?-\d+)', chapter[0])
|
||||
return idx.group(1) if idx else '0'
|
||||
|
||||
def get_main_content(self):
|
||||
return self._get_content('{}%s{}/' % self.prefix)
|
||||
|
||||
def get_manga_name(self) -> str:
|
||||
return self._get_name(r'{}([^/]+)'.format(self.prefix))
|
||||
|
||||
def get_chapters(self):
|
||||
ch = self.helper.get_chapters()
|
||||
return ch[::-1]
|
||||
|
||||
def get_files(self):
|
||||
chapter = self.chapter
|
||||
items = self.helper.sort_images(chapter[1])
|
||||
images = []
|
||||
for i in items:
|
||||
img = self.helper.get_page_image(i, 'img#photo')
|
||||
img and images.append(img)
|
||||
return images
|
||||
|
||||
def prepare_cookies(self):
|
||||
self.helper = animextremist_com.AnimeXtremistCom(self)
|
||||
|
||||
def get_cover(self) -> str:
|
||||
pass
|
||||
# return self._cover_from_content('.cover img')
|
||||
|
||||
def book_meta(self) -> dict:
|
||||
# todo meta
|
||||
pass
|
||||
|
||||
|
||||
main = AnimeXtremistCom
|
||||
@@ -0,0 +1,9 @@
|
||||
from .read_powermanga_org import ReadPowerMangaOrg
|
||||
|
||||
|
||||
class AntiSenseScansCom(ReadPowerMangaOrg):
|
||||
_name_re = '/online/[^/]+/([^/]+)/'
|
||||
_content_str = '{}/online/series/{}/'
|
||||
|
||||
|
||||
main = AntiSenseScansCom
|
||||
45
manga-py-stable_1.x/manga_py/providers/asmhentai_com.py
Normal file
45
manga-py-stable_1.x/manga_py/providers/asmhentai_com.py
Normal file
@@ -0,0 +1,45 @@
|
||||
from manga_py.provider import Provider
|
||||
from .helpers.std import Std
|
||||
|
||||
|
||||
class AsmHentaiCom(Provider, Std):
|
||||
|
||||
def get_archive_name(self) -> str:
|
||||
return 'archive'
|
||||
|
||||
def get_chapter_index(self) -> str:
|
||||
return '0'
|
||||
|
||||
def get_main_content(self):
|
||||
return self.http_get(self.get_url())
|
||||
|
||||
def get_manga_name(self) -> str:
|
||||
title = self.text_content(self.content, '.info > h1,title')
|
||||
if ~title.find(' Page '):
|
||||
title = self.re.search(r'(.+) Page ', title).group(1)
|
||||
return title
|
||||
|
||||
def get_chapters(self):
|
||||
url = self.get_url()
|
||||
if ~url.find('/g/'):
|
||||
url = self._elements('.gallery > div > a')[0].get('href')
|
||||
return [url]
|
||||
|
||||
def get_files(self):
|
||||
content = self.http_get(self.chapter)
|
||||
src = self.re.search(r'\$\(\[[\'"]//(.+)/[\'"]', content).group(1)
|
||||
pages = self.re.search(r'var +Pages ?=.*?(\d+)', content).group(1)
|
||||
result = []
|
||||
http = self.re.search('(https?):', self.get_url()).group(1)
|
||||
for i in range(int(pages)):
|
||||
result.append('{}://{}/{}.jpg'.format(http, src, 1 + i))
|
||||
return result
|
||||
|
||||
def get_cover(self) -> str:
|
||||
return self._cover_from_content('.cover > a > img')
|
||||
|
||||
def book_meta(self) -> dict:
|
||||
pass
|
||||
|
||||
|
||||
main = AsmHentaiCom
|
||||
8
manga-py-stable_1.x/manga_py/providers/atfbooru_ninja.py
Normal file
8
manga-py-stable_1.x/manga_py/providers/atfbooru_ninja.py
Normal file
@@ -0,0 +1,8 @@
|
||||
from .danbooru_donmai_us import DanbooruDonmaiUs
|
||||
|
||||
|
||||
class AtfBooruNinja(DanbooruDonmaiUs):
|
||||
_archive_prefix = 'atfbooru'
|
||||
|
||||
|
||||
main = AtfBooruNinja
|
||||
43
manga-py-stable_1.x/manga_py/providers/authrone_com.py
Normal file
43
manga-py-stable_1.x/manga_py/providers/authrone_com.py
Normal file
@@ -0,0 +1,43 @@
|
||||
from .helpers.std import Std
|
||||
from .mangaonline_today import MangaOnlineToday
|
||||
|
||||
|
||||
class AuthroneCom(MangaOnlineToday, Std):
|
||||
_ch_selector = '.mng_det ul.lst > li > a'
|
||||
|
||||
def get_archive_name(self) -> str:
|
||||
idx = self.re.search('/manga/[^/]+/([^/]+/[^/]+)', self.chapter).group(1).split('.', 2)
|
||||
if len(idx) > 1:
|
||||
return 'vol_{:0>3}-{}_{}'.format(idx[0], *idx[1].split('/'))
|
||||
return 'vol_{:0>3}-0-{}'.format(*idx[0].split('/'))
|
||||
|
||||
def get_chapter_index(self) -> str:
|
||||
return self.re.search('/manga/[^/]+/([^/]+)', self.chapter).group(1)
|
||||
|
||||
def get_main_content(self):
|
||||
return self._get_content('{}/manga/{}')
|
||||
|
||||
def get_manga_name(self) -> str:
|
||||
return self._get_name('/manga/([^/]+)')
|
||||
|
||||
def get_chapters(self): # need sorting chapters: /manga/love_stage/
|
||||
items = self._elements(self._ch_selector)
|
||||
pages = self._elements('ul.lst + ul.pgg li:last-child > a')
|
||||
patern = r'list/(\d+)/'
|
||||
if pages and len(pages):
|
||||
link = pages[-1].get('href')
|
||||
page = self.re.search(patern, link).group(1)
|
||||
for i in range(2, int(page) + 1):
|
||||
page_link = self.re.sub(patern, 'list/%d/' % i, link)
|
||||
items += self._elements(self._ch_selector, self.http_get(page_link))
|
||||
return items
|
||||
|
||||
def get_cover(self) -> str:
|
||||
return self._cover_from_content('#sct_content img.cvr')
|
||||
|
||||
def book_meta(self) -> dict:
|
||||
# todo meta
|
||||
pass
|
||||
|
||||
|
||||
main = AuthroneCom
|
||||
65
manga-py-stable_1.x/manga_py/providers/bato_to.py
Normal file
65
manga-py-stable_1.x/manga_py/providers/bato_to.py
Normal file
@@ -0,0 +1,65 @@
|
||||
from manga_py.provider import Provider
|
||||
from .helpers.std import Std
|
||||
|
||||
|
||||
class BatoTo(Provider, Std):
|
||||
|
||||
def get_chapter_index(self) -> str:
|
||||
return '{}-{}'.format(
|
||||
self.chapter_id,
|
||||
self.chapter[1],
|
||||
)
|
||||
|
||||
def get_main_content(self):
|
||||
url = self.get_url()
|
||||
if ~url.find('/chapter/'):
|
||||
url = self.html_fromstring(url, '.nav-path .nav-title > a', 0).get('href')
|
||||
return self.http_get(url)
|
||||
|
||||
def get_manga_name(self) -> str:
|
||||
selector = '.nav-path .nav-title > a,.title-set .item-title > a'
|
||||
content = self.http_get(self.get_url())
|
||||
return self.text_content(content, selector, 0)
|
||||
|
||||
def get_chapters(self):
|
||||
items = self._elements('.main > .item > a')
|
||||
n = self.http().normalize_uri
|
||||
result = []
|
||||
for i in items:
|
||||
title = i.cssselect('b')[0].text_content().strip(' \n\t\r')
|
||||
if ~title.find('DELETED'): # SKIP DELETED
|
||||
continue
|
||||
result.append((
|
||||
n(i.get('href')),
|
||||
title,
|
||||
))
|
||||
return result
|
||||
# [(
|
||||
# n(i.get('href')),
|
||||
# i.cssselect('b')[0].text_content().strip(' \n\t\r'),
|
||||
# )]
|
||||
|
||||
@staticmethod
|
||||
def _sort_files(data):
|
||||
keys = sorted(data, key=lambda _: int(_))
|
||||
return [data[i] for i in keys]
|
||||
|
||||
def get_files(self):
|
||||
data = self.re.search(r'\simages\s*=\s*({.+});', self.http_get(self.chapter[0]))
|
||||
try:
|
||||
return self._sort_files(self.json.loads(data.group(1)))
|
||||
except ValueError:
|
||||
return []
|
||||
|
||||
def get_cover(self) -> str:
|
||||
return self._cover_from_content('.attr-cover img')
|
||||
|
||||
def book_meta(self) -> dict:
|
||||
# todo meta
|
||||
pass
|
||||
|
||||
def chapter_for_json(self):
|
||||
return self.chapter[0]
|
||||
|
||||
|
||||
main = BatoTo
|
||||
40
manga-py-stable_1.x/manga_py/providers/blogtruyen_com.py
Normal file
40
manga-py-stable_1.x/manga_py/providers/blogtruyen_com.py
Normal file
@@ -0,0 +1,40 @@
|
||||
from manga_py.provider import Provider
|
||||
from .helpers.std import Std
|
||||
|
||||
|
||||
class BlogTruyenCom(Provider, Std):
|
||||
|
||||
def get_chapter_index(self) -> str:
|
||||
idx = self.re.search(r'\.com/c(\d+)/', self.chapter)
|
||||
return '{}-{}'.format(self.chapter_id, idx.group(1))
|
||||
|
||||
def get_main_content(self):
|
||||
url = self._test_main_url(self.get_url())
|
||||
return self.http_get(self.http().normalize_uri(url))
|
||||
|
||||
def _test_main_url(self, url):
|
||||
if ~url.find('.com/c'):
|
||||
selector = '.breadcrumbs a + a'
|
||||
url = self.html_fromstring(url, selector, 0).get('href')
|
||||
return url
|
||||
|
||||
def get_manga_name(self) -> str:
|
||||
url = self._test_main_url(self.get_url())
|
||||
return self.re.search(r'/\d+/([^/]+)', url).group(1)
|
||||
|
||||
def get_chapters(self):
|
||||
return self._elements('#list-chapters .title > a')
|
||||
|
||||
def get_files(self):
|
||||
items = self.html_fromstring(self.chapter, '#content img')
|
||||
return [i.get('src') for i in items]
|
||||
|
||||
def get_cover(self) -> str:
|
||||
return self._cover_from_content('.thumbnail img')
|
||||
|
||||
def book_meta(self) -> dict:
|
||||
# todo meta
|
||||
pass
|
||||
|
||||
|
||||
main = BlogTruyenCom
|
||||
@@ -0,0 +1,9 @@
|
||||
from .read_powermanga_org import ReadPowerMangaOrg
|
||||
|
||||
|
||||
class BnsShounenAiNet(ReadPowerMangaOrg):
|
||||
_name_re = '/read/[^/]+/([^/]+)/'
|
||||
_content_str = '{}/read/series/{}/'
|
||||
|
||||
|
||||
main = BnsShounenAiNet
|
||||
47
manga-py-stable_1.x/manga_py/providers/boredomsociety_xyz.py
Normal file
47
manga-py-stable_1.x/manga_py/providers/boredomsociety_xyz.py
Normal file
@@ -0,0 +1,47 @@
|
||||
from manga_py.provider import Provider
|
||||
from .helpers.std import Std
|
||||
|
||||
|
||||
class BoredomSocietyXyz(Provider, Std):
|
||||
def get_chapter_index(self) -> str:
|
||||
return self.re.search(
|
||||
r'/reader/\d+/(\d+(?:\.\d+)?)',
|
||||
self.chapter
|
||||
).group(1).replace('.', '-')
|
||||
|
||||
def get_main_content(self):
|
||||
idx = self.re.search(
|
||||
'/(?:titles/info|reader)/(\d+)',
|
||||
self.get_url()
|
||||
).group(1)
|
||||
return self.http_get('{}/titles/info/{}'.format(
|
||||
self.domain,
|
||||
idx
|
||||
))
|
||||
|
||||
def get_manga_name(self) -> str:
|
||||
return self.text_content(self.content, 'h2')
|
||||
|
||||
def get_chapters(self):
|
||||
return self._elements('a.titlesinfo_chaptertitle')
|
||||
|
||||
def get_files(self):
|
||||
parser = self.html_fromstring(self.chapter)
|
||||
images = self._images_helper(parser, 'img.reader_mangaimage')
|
||||
n = self.http().normalize_uri
|
||||
return [n(i) for i in images]
|
||||
|
||||
def get_cover(self) -> str:
|
||||
return self._cover_from_content('img.titlesinfo_coverimage')
|
||||
|
||||
def book_meta(self) -> dict:
|
||||
pass
|
||||
|
||||
def prepare_cookies(self):
|
||||
# enable "all-images-on-page"
|
||||
self.http_post('{}/module/reader/ajax.php'.format(self.domain), data={
|
||||
'readingtype': 'all'
|
||||
})
|
||||
|
||||
|
||||
main = BoredomSocietyXyz
|
||||
73
manga-py-stable_1.x/manga_py/providers/cdmnet_com_br.py
Normal file
73
manga-py-stable_1.x/manga_py/providers/cdmnet_com_br.py
Normal file
@@ -0,0 +1,73 @@
|
||||
from lxml import html
|
||||
|
||||
from manga_py.provider import Provider
|
||||
from .helpers.std import Std
|
||||
|
||||
|
||||
class CdmNetComBr(Provider, Std):
|
||||
|
||||
def get_archive_name(self) -> str:
|
||||
url = self.chapter
|
||||
idx = self.get_chapter_index()
|
||||
if ~url.find('/manga/'):
|
||||
return 'vol_{:0>3}'.format(idx)
|
||||
if ~url.find('/novel/'):
|
||||
return 'novel_{:0>3}'.format(idx)
|
||||
|
||||
def get_chapter_index(self) -> str:
|
||||
re = self.re.compile('/titulos/[^/]+/[^/]+/[^/]+/([^/]+)')
|
||||
return re.search(self.chapter).group(1)
|
||||
|
||||
def get_main_content(self):
|
||||
return self._get_content('{}/titulos/{}')
|
||||
|
||||
def get_manga_name(self) -> str:
|
||||
return self._get_name(r'/titulos/([^/]+)')
|
||||
|
||||
def get_chapters(self):
|
||||
return self._elements('.ui .content .table td > a')
|
||||
|
||||
def save_file(self, idx=None, callback=None, url=None, in_arc_name=None):
|
||||
if ~url.find('/manga/'):
|
||||
return super().save_file(idx, callback, url, in_arc_name)
|
||||
if ~url.find('/novel/'):
|
||||
_path, idx, _url = self._save_file_params_helper(url, idx)
|
||||
_path += '.html'
|
||||
element = self.html_fromstring(url, '.novel-chapter', 0)
|
||||
with open(_path, 'wb') as f:
|
||||
f.write(html.tostring(element))
|
||||
callable(callback) and callback()
|
||||
self.after_file_save(_path, idx)
|
||||
self._archive.add_file(_path, in_arc_name)
|
||||
return _path
|
||||
|
||||
def _manga(self):
|
||||
file_type = '.jpg'
|
||||
content = self.http_get(self.chapter)
|
||||
re_suffix = self.re.compile(r'urlSulfix\s*=\s*[\'"](.+)[\'"]\s*;')
|
||||
re_images = self.re.compile(r'pages\s*=\s*(\[.+\])\s*;')
|
||||
suffix = re_suffix.search(content).group(1)
|
||||
images = re_images.search(content).group(1)
|
||||
images = self.re.sub("'", '"', images)
|
||||
images = self.json.loads(self.re.sub(r'",\]', '"]', images))
|
||||
|
||||
self.log(['{}{}{}'.format(suffix, i, file_type) for i in images])
|
||||
|
||||
return ['{}{}{}'.format(suffix, i, file_type) for i in images]
|
||||
|
||||
def get_files(self):
|
||||
if ~self.chapter.find('/manga/'):
|
||||
return self._manga()
|
||||
if ~self.chapter.find('/novel/'):
|
||||
return [self.chapter]
|
||||
return []
|
||||
|
||||
def get_cover(self) -> str:
|
||||
return self._cover_from_content('.content .description img.image')
|
||||
|
||||
def book_meta(self) -> dict:
|
||||
# todo meta
|
||||
pass
|
||||
|
||||
|
||||
main = CdmNetComBr
|
||||
36
manga-py-stable_1.x/manga_py/providers/chochox_com.py
Normal file
36
manga-py-stable_1.x/manga_py/providers/chochox_com.py
Normal file
@@ -0,0 +1,36 @@
|
||||
from manga_py.provider import Provider
|
||||
from .helpers.std import Std
|
||||
|
||||
|
||||
class ChoChoxCom(Provider, Std):
|
||||
|
||||
def get_archive_name(self) -> str:
|
||||
return 'archive'
|
||||
|
||||
def get_chapter_index(self) -> str:
|
||||
return '0'
|
||||
|
||||
def get_main_content(self):
|
||||
return self._get_content('{}/{}')
|
||||
|
||||
def get_manga_name(self) -> str:
|
||||
return self._get_name(r'\.com/([^/]+)')
|
||||
|
||||
def get_chapters(self):
|
||||
return [b'']
|
||||
|
||||
def get_files(self):
|
||||
return [i.get('src') for i in self._elements('img.alignnone')]
|
||||
|
||||
def get_cover(self) -> str:
|
||||
pass
|
||||
|
||||
def book_meta(self) -> dict:
|
||||
# todo meta
|
||||
pass
|
||||
|
||||
def chapter_for_json(self):
|
||||
return self.get_url()
|
||||
|
||||
|
||||
main = ChoChoxCom
|
||||
@@ -0,0 +1,10 @@
|
||||
from .adulto_seinagi_org import AdultoSeinagiOrg
|
||||
|
||||
|
||||
class ChouTensei260mbNet(AdultoSeinagiOrg):
|
||||
def prepare_cookies(self):
|
||||
self._storage['cookies'][' __test'] = '9f148766d926b07a85683d7a6cd50150'
|
||||
super().prepare_cookies()
|
||||
|
||||
|
||||
main = ChouTensei260mbNet
|
||||
@@ -0,0 +1,35 @@
|
||||
from manga_py.provider import Provider
|
||||
from .helpers.std import Std
|
||||
|
||||
|
||||
class ComicWebNewTypeCom(Provider, Std):
|
||||
|
||||
def get_chapter_index(self) -> str:
|
||||
re = self.re.compile('/contents/[^/]+/([^/]+)')
|
||||
return re.search(self.chapter).group(1)
|
||||
|
||||
def get_main_content(self):
|
||||
return self._get_content('{}/contents/{}/')
|
||||
|
||||
def get_manga_name(self) -> str:
|
||||
return self._get_name('/contents/([^/]+)')
|
||||
|
||||
def get_chapters(self):
|
||||
return self._elements('#episodeList li.ListCard a')
|
||||
|
||||
def get_files(self):
|
||||
url = self.chapter
|
||||
items = self.http_get(url + 'json/', headers={'x-requested-with': 'XMLHttpRequest'})
|
||||
imgs = self.json.loads(items)
|
||||
imgs = [self.re.sub(r'jpg.+', 'jpg', img) for img in imgs]
|
||||
return imgs
|
||||
|
||||
def get_cover(self) -> str:
|
||||
return self._cover_from_content('.WorkSummary-content img')
|
||||
|
||||
def book_meta(self) -> dict:
|
||||
# todo meta
|
||||
pass
|
||||
|
||||
|
||||
main = ComicWebNewTypeCom
|
||||
39
manga-py-stable_1.x/manga_py/providers/comicextra_com.py
Normal file
39
manga-py-stable_1.x/manga_py/providers/comicextra_com.py
Normal file
@@ -0,0 +1,39 @@
|
||||
from manga_py.provider import Provider
|
||||
from .helpers.std import Std
|
||||
|
||||
|
||||
class ComicExtraCom(Provider, Std):
|
||||
|
||||
def get_chapter_index(self) -> str:
|
||||
idx = self.re.search(r'/chapter-(.+)', self.chapter)
|
||||
if idx:
|
||||
return '{}-{}'.format(self.chapter_id, idx.group(1))
|
||||
return str(self.chapter_id)
|
||||
|
||||
def get_main_content(self):
|
||||
return self._get_content('{}/comic/{}')
|
||||
|
||||
def get_manga_name(self):
|
||||
url = self.get_url()
|
||||
test = self.re.search('/comic/([^/]+)', url)
|
||||
if test:
|
||||
return test.group(1)
|
||||
return self.re.search('/([^/]+)/chapter', url).group(1)
|
||||
|
||||
def get_chapters(self):
|
||||
return self._elements('#list td a')
|
||||
|
||||
def get_files(self):
|
||||
url = self.chapter + '/full'
|
||||
items = self.html_fromstring(url, '.chapter-container img.chapter_img')
|
||||
return [i.get('src') for i in items]
|
||||
|
||||
def get_cover(self):
|
||||
return self._cover_from_content('.movie-image img')
|
||||
|
||||
def book_meta(self) -> dict:
|
||||
# todo meta
|
||||
pass
|
||||
|
||||
|
||||
main = ComicExtraCom
|
||||
@@ -0,0 +1,42 @@
|
||||
from .comico_co_id_titles import ComicoCoIdTitles
|
||||
from .helpers.std import Std
|
||||
|
||||
|
||||
class ComicoCoIdContent(ComicoCoIdTitles, Std): # maybe
|
||||
__origin_url = None
|
||||
|
||||
def get_archive_name(self) -> str:
|
||||
return '0'
|
||||
|
||||
def get_chapter_index(self) -> str:
|
||||
re = self.re.compile(r'/title/(\d+)')
|
||||
return re.search(self.chapter).group(1)
|
||||
|
||||
def get_main_content(self):
|
||||
idx = self.re.search(r'contentId=(\d+)', self.get_url())
|
||||
return self.http_get('{}/content?contentId={}'.format(
|
||||
self.domain,
|
||||
idx.group(1)
|
||||
))
|
||||
|
||||
def get_manga_name(self) -> str:
|
||||
return 'Fake'
|
||||
|
||||
def prepare_cookies(self):
|
||||
self.__origin_url = self.get_url()
|
||||
|
||||
def get_chapters(self):
|
||||
pass
|
||||
# return self._elements('.contlst-container .contlst-item > a')
|
||||
|
||||
def get_files(self):
|
||||
return []
|
||||
|
||||
def get_cover(self) -> str:
|
||||
pass
|
||||
|
||||
def chapter_for_json(self):
|
||||
return self.get_url()
|
||||
|
||||
|
||||
main = ComicoCoIdContent
|
||||
@@ -0,0 +1,71 @@
|
||||
from time import time
|
||||
|
||||
from manga_py.provider import Provider
|
||||
from .helpers.std import Std
|
||||
|
||||
|
||||
class ComicoCoIdTitles(Provider, Std):
|
||||
_url = None
|
||||
|
||||
def get_chapter_index(self) -> str:
|
||||
return str(self.chapter.get('id', '0'))
|
||||
|
||||
def _manga_id(self):
|
||||
idx = self.re.search(r'/titles/(\d+)', self.get_url())
|
||||
return idx.group(1)
|
||||
|
||||
def get_main_content(self):
|
||||
self._url = '{}/titles/{}'.format(
|
||||
self.domain,
|
||||
self._manga_id(),
|
||||
)
|
||||
return self.http_get(self._url)
|
||||
|
||||
def get_manga_name(self) -> str:
|
||||
h2 = self.document_fromstring(self.content, '.con > h2', 0)
|
||||
return '{} - {}'.format(
|
||||
h2.text_content(),
|
||||
self._manga_id()
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def __parse_page(content):
|
||||
items = []
|
||||
for i in content.get('data', {}).get('list', []):
|
||||
if i.get('salePolicy', {}).get('isFree', False):
|
||||
items.append(i)
|
||||
return items
|
||||
|
||||
def get_chapters(self):
|
||||
items = []
|
||||
for page in range(1, 10):
|
||||
content = self.http_get('{}/chapters?page={}&_={}'.format(
|
||||
self._url,
|
||||
page,
|
||||
int(time()),
|
||||
))
|
||||
try:
|
||||
content = self.json.loads(content)
|
||||
if content.get('header', {}).get('resultCode', -1) < 0:
|
||||
break
|
||||
items += self.__parse_page(content)
|
||||
except Exception:
|
||||
break
|
||||
return items
|
||||
|
||||
def get_files(self):
|
||||
parser = self.html_fromstring('{}/chapters/{}'.format(
|
||||
self._url,
|
||||
self.chapter.get('id'),
|
||||
), '._view', 0)
|
||||
return self._images_helper(parser, '._image')
|
||||
|
||||
def get_cover(self) -> str:
|
||||
return self._cover_from_content('.bg_img_small img')
|
||||
|
||||
def book_meta(self) -> dict:
|
||||
# todo meta
|
||||
pass
|
||||
|
||||
|
||||
main = ComicoCoIdTitles
|
||||
50
manga-py-stable_1.x/manga_py/providers/comico_jp.py
Normal file
50
manga-py-stable_1.x/manga_py/providers/comico_jp.py
Normal file
@@ -0,0 +1,50 @@
|
||||
from sys import stderr
|
||||
|
||||
from manga_py.provider import Provider
|
||||
from .helpers.std import Std
|
||||
|
||||
|
||||
class ComicoJp(Provider, Std):
|
||||
|
||||
def get_chapter_index(self) -> str:
|
||||
idx = self.re.search(r'articleNo=(\d+)', self.chapter)
|
||||
if idx:
|
||||
return '{}-{}'.format(self.chapter_id, idx.group(1))
|
||||
return str(self.chapter_id)
|
||||
|
||||
def get_main_content(self):
|
||||
title_no = self.re.search(r'\.jp/.+titleNo=(\d+)', self.get_url())
|
||||
if title_no:
|
||||
content = self.http_post('{}/api/getArticleList.nhn'.format(self.domain), data={
|
||||
'titleNo': title_no.group(1)
|
||||
})
|
||||
try:
|
||||
return self.json.loads(content).get('result', {}).get('list', [])
|
||||
except TypeError:
|
||||
pass
|
||||
return []
|
||||
|
||||
def get_manga_name(self):
|
||||
content = self.http_get(self.get_url())
|
||||
name = self.text_content(content, 'title')
|
||||
return name[:name.rfind('|')].strip(' \n\t\r')
|
||||
|
||||
def get_chapters(self):
|
||||
# TODO: see i['freeFlg'] Y = true, W = false #19
|
||||
items = [i['articleDetailUrl'] for i in self.content if i['freeFlg'] == 'Y']
|
||||
self.log('Free chapters count: %d' % len(items), file=stderr)
|
||||
return items[::-1]
|
||||
|
||||
def get_files(self):
|
||||
items = self.html_fromstring(self.chapter, '.comic-image._comicImage > img.comic-image__image')
|
||||
return [i.get('src') for i in items]
|
||||
|
||||
def get_cover(self):
|
||||
pass
|
||||
|
||||
def book_meta(self) -> dict:
|
||||
# todo meta
|
||||
pass
|
||||
|
||||
|
||||
main = ComicoJp
|
||||
29
manga-py-stable_1.x/manga_py/providers/comicpunch_net.py
Normal file
29
manga-py-stable_1.x/manga_py/providers/comicpunch_net.py
Normal file
@@ -0,0 +1,29 @@
|
||||
from manga_py.provider import Provider
|
||||
from .helpers.std import Std
|
||||
from urllib import parse
|
||||
|
||||
|
||||
class ComicPunchNet(Provider, Std):
|
||||
|
||||
def get_chapter_index(self) -> str:
|
||||
return self.re.search(r'[-/]((?:Annual|Issue|Chapter)-\w+)', self.chapter).group(1)
|
||||
|
||||
def get_main_content(self):
|
||||
return self.http_get(self.get_url())
|
||||
|
||||
def get_manga_name(self) -> str:
|
||||
return self.text_content(self.content, '.page-title')
|
||||
|
||||
def get_chapters(self):
|
||||
return self._elements('.chapter > a')
|
||||
|
||||
def get_files(self):
|
||||
parser = self.html_fromstring(self.chapter + '?q=fullchapter')
|
||||
base_url = parser.cssselect('base[href]')[0].get('href')
|
||||
return [parse.urljoin(base_url, i) for i in self._images_helper(parser, 'img.picture')]
|
||||
|
||||
def get_cover(self) -> str:
|
||||
return self._cover_from_content('.pic .series')
|
||||
|
||||
|
||||
main = ComicPunchNet
|
||||
@@ -0,0 +1,27 @@
|
||||
from manga_py.provider import Provider
|
||||
from .helpers.std import Std
|
||||
|
||||
|
||||
class ComicPunchNetManga(Provider, Std):
|
||||
def get_chapter_index(self) -> str:
|
||||
re = self.re.compile(r'/chapter_(\d+(?:\.\d+)?)')
|
||||
return re.search(self.chapter).group(1).replace('.', '-')
|
||||
|
||||
def get_main_content(self):
|
||||
return self.http_get(self.get_url())
|
||||
|
||||
def get_manga_name(self) -> str:
|
||||
return self.text_content(self.content, '.page-title')
|
||||
|
||||
def get_chapters(self):
|
||||
return self._elements('.manga_chapter a')
|
||||
|
||||
def get_files(self):
|
||||
parser = self.html_fromstring(self.chapter)
|
||||
return self._images_helper(parser, 'img.picture')
|
||||
|
||||
def get_cover(self) -> str:
|
||||
return self._cover_from_content('.field-name-field-pic img')
|
||||
|
||||
|
||||
main = ComicPunchNetManga
|
||||
50
manga-py-stable_1.x/manga_py/providers/comicsandmanga_ru.py
Normal file
50
manga-py-stable_1.x/manga_py/providers/comicsandmanga_ru.py
Normal file
@@ -0,0 +1,50 @@
|
||||
from manga_py.provider import Provider
|
||||
from .helpers.std import Std
|
||||
|
||||
|
||||
class ComicsAndMangaRu(Provider, Std):
|
||||
|
||||
def get_archive_name(self) -> str:
|
||||
index = self.get_chapter_index()
|
||||
return 'vol_{:0>3}'.format(index)
|
||||
|
||||
def get_chapter_index(self) -> str:
|
||||
return self.re.search(r'.+/[^/]+?(\d+)$', self.chapter).group(1)
|
||||
|
||||
def get_main_content(self):
|
||||
name = self.re.search('/(online-reading/[^/]+/[^/]+)', self.get_url())
|
||||
return self.http_get('{}/{}'.format(self.domain, name.group(1)))
|
||||
|
||||
def get_manga_name(self):
|
||||
name = self.re.search('/online-reading/[^/]+/([^/]+)', self.get_url())
|
||||
return name.group(1)
|
||||
|
||||
def get_chapters(self):
|
||||
selector = '.MagList > .MagListLine > a'
|
||||
items = self.document_fromstring(self.content, selector)
|
||||
return items[::-1]
|
||||
|
||||
def get_files(self):
|
||||
img_selector = 'a > img'
|
||||
nu = self.http().normalize_uri
|
||||
uri = nu(self.chapter)
|
||||
parser = self.html_fromstring(uri, '.ForRead', 0)
|
||||
pages = parser.cssselect('.navigation select')[0].cssselect('option + option')
|
||||
images = self._images_helper(parser, img_selector)
|
||||
|
||||
for i in pages:
|
||||
uri = '{}/{}'.format(nu(self.chapter.rstrip('/')), i.get('value'))
|
||||
parser = self.html_fromstring(uri, '.ForRead', 0)
|
||||
images += self._images_helper(parser, img_selector)
|
||||
|
||||
return images
|
||||
|
||||
def get_cover(self):
|
||||
pass # TODO
|
||||
|
||||
def book_meta(self) -> dict:
|
||||
# todo meta
|
||||
pass
|
||||
|
||||
|
||||
main = ComicsAndMangaRu
|
||||
55
manga-py-stable_1.x/manga_py/providers/comicvn_net.py
Normal file
55
manga-py-stable_1.x/manga_py/providers/comicvn_net.py
Normal file
@@ -0,0 +1,55 @@
|
||||
from manga_py.provider import Provider
|
||||
from .helpers.std import Std
|
||||
|
||||
|
||||
class ComicNnNet(Provider, Std):
|
||||
|
||||
def get_archive_name(self) -> str:
|
||||
return self.get_chapter_index()
|
||||
|
||||
def get_chapter_index(self) -> str: # todo
|
||||
re = self.re.compile('/truyen-tranh-online/[^/]+/([^/]+)')
|
||||
return re.search(self.chapter).group(1)
|
||||
|
||||
def get_main_content(self):
|
||||
return self._get_content('{}/truyen-tranh-online/{}')
|
||||
|
||||
def _iframe_hook(self, url):
|
||||
content = self.html_fromstring(url)
|
||||
iframe = content.cssselect('iframe')
|
||||
if iframe:
|
||||
url = iframe[0].get('src')
|
||||
self.log('Iframe!\n' + url)
|
||||
return self.html_fromstring(url)
|
||||
|
||||
def get_manga_name(self) -> str:
|
||||
name = self._get_name(r'/truyen-tranh-online/([^/]+)')
|
||||
if self.re.search('.+-\d+', name):
|
||||
return name
|
||||
a = self._iframe_hook(self.get_url())
|
||||
self._params['url'] = a.cssselect('.sub-bor h1 a')[0].get('href')
|
||||
return self.get_manga_name()
|
||||
|
||||
def get_chapters(self):
|
||||
return self._elements('.manga-chapter-head + ul li > a')
|
||||
|
||||
def get_files(self):
|
||||
content = self._iframe_hook(self.chapter)
|
||||
files = content.cssselect('textarea#txtarea img')
|
||||
if files:
|
||||
n = self.http().normalize_uri
|
||||
return [n(i.get('src')) for i in files]
|
||||
return []
|
||||
|
||||
def prepare_cookies(self):
|
||||
self._base_cookies()
|
||||
|
||||
def get_cover(self) -> str:
|
||||
return self._cover_from_content('.manga-detail .row img')
|
||||
|
||||
def book_meta(self) -> dict:
|
||||
# todo meta
|
||||
pass
|
||||
|
||||
|
||||
main = ComicNnNet
|
||||
58
manga-py-stable_1.x/manga_py/providers/cycomi_com.py
Normal file
58
manga-py-stable_1.x/manga_py/providers/cycomi_com.py
Normal file
@@ -0,0 +1,58 @@
|
||||
from manga_py.provider import Provider
|
||||
from .helpers.std import Std
|
||||
|
||||
|
||||
class CycomiCom(Provider, Std):
|
||||
@staticmethod
|
||||
def remove_not_ascii(value):
|
||||
return value
|
||||
|
||||
def get_chapter_index(self) -> str:
|
||||
return self.chapter[1]
|
||||
|
||||
def get_main_content(self):
|
||||
idx = self.re.search(
|
||||
r'/title/(\d+)',
|
||||
self.get_url()
|
||||
).group(1)
|
||||
|
||||
url = '{}/fw/cycomibrowser/chapter/title/{}'.format(
|
||||
self.domain,
|
||||
idx
|
||||
)
|
||||
|
||||
return self.http_get(url)
|
||||
|
||||
def get_manga_name(self) -> str:
|
||||
return self.text_content(self.content, '.title-texts h3')
|
||||
|
||||
def get_chapters(self):
|
||||
selector = 'a.chapter-item:not(.is-preread)'
|
||||
items = []
|
||||
n = self.http().normalize_uri
|
||||
for el in self._elements(selector, self.content):
|
||||
title = el.cssselect('p.chapter-title')[0]
|
||||
title = title.text_content().strip(' \n\r\t\0')
|
||||
episode_id = self.re.sub(r'.+pages/(.+)', r'\1', n(el.get('href')))
|
||||
title = episode_id + '_' + title
|
||||
items.append((n(el.get('href')), title))
|
||||
return items
|
||||
|
||||
def get_files(self):
|
||||
content = self.http_get(self.chapter[0])
|
||||
parser = self.document_fromstring(content)
|
||||
selector = '.comic-image'
|
||||
return self._images_helper(parser, selector)
|
||||
|
||||
def get_cover(self) -> str:
|
||||
return self._cover_from_content('.title-image-container img')
|
||||
|
||||
def chapter_for_json(self):
|
||||
return self.chapter[1]
|
||||
|
||||
def book_meta(self) -> dict:
|
||||
# todo meta
|
||||
pass
|
||||
|
||||
|
||||
main = CycomiCom
|
||||
99
manga-py-stable_1.x/manga_py/providers/danbooru_donmai_us.py
Normal file
99
manga-py-stable_1.x/manga_py/providers/danbooru_donmai_us.py
Normal file
@@ -0,0 +1,99 @@
|
||||
from manga_py.provider import Provider
|
||||
from .helpers.std import Std
|
||||
|
||||
|
||||
class DanbooruDonmaiUs(Provider, Std):
|
||||
_is_tag = False
|
||||
_archive_prefix = 'danbooru_'
|
||||
_manga_name = None
|
||||
|
||||
def get_archive_name(self) -> str:
|
||||
if self.chapter:
|
||||
return 'page_{:0>2}'.format(self.chapter)
|
||||
return 'archive'
|
||||
|
||||
def get_chapter_index(self) -> str:
|
||||
if self.chapter:
|
||||
return str(self.chapter)
|
||||
return '0'
|
||||
|
||||
def get_main_content(self):
|
||||
return self.http_get(self.get_url())
|
||||
|
||||
def get_manga_name(self) -> str:
|
||||
if ~self.get_url().find('tags='):
|
||||
self._is_tag = True
|
||||
self._manga_name = self._get_name(r'[\?&]tags=([^&]+)')
|
||||
else:
|
||||
self._manga_name = self._get_name(r'/posts/(\d+)')
|
||||
return self._archive_prefix + self._manga_name
|
||||
|
||||
def get_chapters(self): # pragma: no cover
|
||||
if self._is_tag:
|
||||
pages = self._elements('.paginator .current-page > span')
|
||||
images_on_page = len(self._elements('#posts > div > article'))
|
||||
if pages:
|
||||
count = self.html_fromstring('{}/counts/posts?tags={}'.format(
|
||||
self.domain,
|
||||
self.manga_name,
|
||||
), '#a-posts', 0).text_content()
|
||||
page = self.re.search(r'\n\s+(\d+)', count).group(1)
|
||||
max_page = int(int(page) / images_on_page) + 1
|
||||
if max_page > 1001:
|
||||
self.log('1000 pages maximum!')
|
||||
max_page = 1000
|
||||
return range(1, max_page)[::-1]
|
||||
return [1]
|
||||
|
||||
def _tag_images(self): # pragma: no cover
|
||||
url = '{}/posts?tags={}&page={}'.format(
|
||||
self.domain,
|
||||
self._manga_name,
|
||||
self.chapter,
|
||||
)
|
||||
parser = self.html_fromstring(url, '#posts article a')
|
||||
n = self.http().normalize_uri
|
||||
images = []
|
||||
for i in parser:
|
||||
images += self._post_image(n(i.get('href')))
|
||||
return images
|
||||
|
||||
def _post_image(self, url): # pragma: no cover
|
||||
if isinstance(url, str):
|
||||
parser = self.html_fromstring(url)
|
||||
else:
|
||||
parser = url
|
||||
|
||||
full_size = parser.cssselect('#image-resize-notice a')
|
||||
if full_size:
|
||||
return [full_size[0].get('href')]
|
||||
return [parser.cssselect('#image')[0].get('src')]
|
||||
|
||||
def _post_images(self, url): # pragma: no cover
|
||||
parser = self.html_fromstring(url)
|
||||
links = parser.cssselect('#has-parent-relationship-preview article a')
|
||||
if links:
|
||||
images = []
|
||||
n = self.http().normalize_uri
|
||||
for i in links:
|
||||
images += self._post_image(n(i.get('href')))
|
||||
return images
|
||||
return self._post_image(parser)
|
||||
|
||||
def get_files(self):
|
||||
if self._is_tag:
|
||||
return self._tag_images()
|
||||
return self._post_images(self.get_url())
|
||||
|
||||
def get_cover(self) -> str:
|
||||
pass
|
||||
|
||||
def book_meta(self) -> dict:
|
||||
# todo meta
|
||||
pass
|
||||
|
||||
def chapter_for_json(self):
|
||||
return self.get_url()
|
||||
|
||||
|
||||
main = DanbooruDonmaiUs
|
||||
@@ -0,0 +1,37 @@
|
||||
from manga_py.provider import Provider
|
||||
from .helpers.std import Std
|
||||
|
||||
|
||||
class DarkSkyProjectsOrg(Provider, Std):
|
||||
|
||||
def get_archive_name(self) -> str:
|
||||
return self.normal_arc_name({'vol': [
|
||||
self.chapter_id,
|
||||
self.get_chapter_index()
|
||||
]})
|
||||
|
||||
def get_chapter_index(self) -> str:
|
||||
return self.re.search('/biblioteca/[^/]+/([^/]+)', self.chapter).group(1)
|
||||
|
||||
def get_main_content(self):
|
||||
return self._get_content('{}/biblioteca/{}')
|
||||
|
||||
def get_manga_name(self) -> str:
|
||||
return self._get_name('/biblioteca/([^/]+)')
|
||||
|
||||
def get_chapters(self):
|
||||
return self._elements('.chapters h5 a')
|
||||
|
||||
def get_files(self):
|
||||
parser = self.html_fromstring(self.chapter)
|
||||
return self._images_helper(parser, 'data-src')
|
||||
|
||||
def get_cover(self) -> str:
|
||||
return self._cover_from_content('.boxed > .img-responsive')
|
||||
|
||||
def book_meta(self) -> dict:
|
||||
# todo meta
|
||||
pass
|
||||
|
||||
|
||||
main = DarkSkyProjectsOrg
|
||||
@@ -0,0 +1,9 @@
|
||||
from .helveticascans_com import HelveticaScansCom
|
||||
|
||||
|
||||
class DejameProbarEs(HelveticaScansCom):
|
||||
_name_re = '/slide/[^/]+/([^/]+)/'
|
||||
_content_str = '{}/slide/series/{}/'
|
||||
|
||||
|
||||
main = DejameProbarEs
|
||||
41
manga-py-stable_1.x/manga_py/providers/desu_me.py
Normal file
41
manga-py-stable_1.x/manga_py/providers/desu_me.py
Normal file
@@ -0,0 +1,41 @@
|
||||
from manga_py.provider import Provider
|
||||
from .helpers.std import Std
|
||||
|
||||
|
||||
class DesuMe(Provider, Std):
|
||||
|
||||
def get_archive_name(self) -> str:
|
||||
idx = self.get_chapter_index().split('-')
|
||||
return self.normal_arc_name({'vol': idx[0], 'ch': idx[1]})
|
||||
|
||||
def get_chapter_index(self) -> str:
|
||||
result = self.re.search(r'/vol(\d+)/ch(\d+)', self.chapter).groups()
|
||||
return '{}-{}'.format(result[0], result[1])
|
||||
|
||||
def get_main_content(self):
|
||||
return self._get_content('{}/manga/{}')
|
||||
|
||||
def get_chapters(self):
|
||||
return self._elements('#animeView ul h4 > a.tips')
|
||||
|
||||
def get_manga_name(self) -> str:
|
||||
return self._get_name('/manga/([^/]+)')
|
||||
|
||||
def get_files(self):
|
||||
content = self.http_get(self.domain + self.chapter)
|
||||
result = self.re.search(r'images:\s?(\[\[.+\]\])', content, self.re.M)
|
||||
if not result:
|
||||
return []
|
||||
root_url = self.re.search(r'dir:\s?"([^"]*)"', content).group(1).replace(r'\/', '/')
|
||||
|
||||
return [root_url + i[0] for i in self.json.loads(result.group(1))]
|
||||
|
||||
def get_cover(self):
|
||||
return self._cover_from_content('.c-poster > img')
|
||||
|
||||
def book_meta(self) -> dict:
|
||||
# todo meta
|
||||
pass
|
||||
|
||||
|
||||
main = DesuMe
|
||||
@@ -0,0 +1,51 @@
|
||||
from .read_powermanga_org import ReadPowerMangaOrg
|
||||
|
||||
|
||||
class DigitalTeam1AltervistaOrg(ReadPowerMangaOrg):
|
||||
__title = None
|
||||
_name_re = '/reader/[^/]+/([^/]+)'
|
||||
_content_str = '{}/reader/read/{}/'
|
||||
_chapters_selector = '.chapter_list li > div > a'
|
||||
|
||||
def get_chapters(self):
|
||||
self.__title = self.text_content(self.content, 'title')
|
||||
return super().get_chapters()
|
||||
|
||||
def __parse_json(self, data) -> list:
|
||||
items = []
|
||||
for n, i in enumerate(data[0]):
|
||||
items.append('{}/reader{}{}{}{}'.format(
|
||||
self.domain,
|
||||
data[2], # path
|
||||
i['name'], # image index
|
||||
data[1][n], # image hash
|
||||
i['ex'] # image extension
|
||||
))
|
||||
return items
|
||||
|
||||
def get_files(self):
|
||||
chapter = self.re.search('/(\d+)/', self.chapter).group(1)
|
||||
data = {
|
||||
'info[manga]': self.manga_name,
|
||||
'info[chapter]': chapter,
|
||||
'info[ch_sub]': '0', # todo: watch this
|
||||
'info[title]': self.__title,
|
||||
}
|
||||
json = self.json.loads(self.http_post(
|
||||
'{}/reader/c_i'.format(self.domain),
|
||||
data=data,
|
||||
headers={'X-Requested-With': 'XMLHttpRequest'}
|
||||
))
|
||||
|
||||
if isinstance(json, str): # DO NOT TOUCH THIS!
|
||||
json = self.json.loads(json)
|
||||
|
||||
if json:
|
||||
return self.__parse_json(json)
|
||||
return []
|
||||
|
||||
def get_cover(self) -> str:
|
||||
return self._cover_from_content('.cover img')
|
||||
|
||||
|
||||
main = DigitalTeam1AltervistaOrg
|
||||
111
manga-py-stable_1.x/manga_py/providers/dm5_com.py
Normal file
111
manga-py-stable_1.x/manga_py/providers/dm5_com.py
Normal file
@@ -0,0 +1,111 @@
|
||||
from urllib.parse import quote_plus
|
||||
|
||||
import execjs
|
||||
|
||||
from manga_py.fs import is_file
|
||||
from manga_py.provider import Provider
|
||||
from .helpers.std import Std
|
||||
|
||||
|
||||
class Dm5Com(Provider, Std):
|
||||
def get_chapter_index(self) -> str:
|
||||
re = self.re.compile(r'[^\d+](\d+)')
|
||||
return re.search(self.chapter[1]).group(1)
|
||||
|
||||
def get_main_content(self):
|
||||
content = self._storage.get('main_content', None)
|
||||
if content is None:
|
||||
if self.get_url().find('/manhua-'):
|
||||
# normal url
|
||||
name = self._get_name('/manhua-([^/]+)')
|
||||
else:
|
||||
# chapter url
|
||||
selector = '.title .right-arrow > a'
|
||||
name = self.html_fromstring(self.get_url(), selector, 0)
|
||||
name = self._get_name('/manhua-([^/]+)', name.get('href'))
|
||||
content = self.http_get('{}/manhua-{}/'.format(
|
||||
self.domain,
|
||||
name
|
||||
))
|
||||
return content
|
||||
|
||||
def get_manga_name(self) -> str:
|
||||
title = self.text_content(self.content, '.info .title')
|
||||
if title:
|
||||
return title
|
||||
re = self.re.search('/manhua-([^/]+)', self.get_url())
|
||||
return re.group(1)
|
||||
|
||||
def get_chapters(self):
|
||||
items = self._elements('ul.detail-list-select')
|
||||
if not items:
|
||||
return []
|
||||
items = items[0].cssselect('li > a')
|
||||
n = self.http().normalize_uri
|
||||
return [(n(i.get('href')), i.text_content()) for i in items]
|
||||
|
||||
def get_files(self): # fixme
|
||||
content = self.http_get(self.chapter[0])
|
||||
parser = self.document_fromstring(content)
|
||||
pages = parser.cssselect('.chapterpager a')
|
||||
if pages:
|
||||
pages = int(pages[-1].text_content().strip())
|
||||
else:
|
||||
pages = 1
|
||||
s = lambda k: self.re.search(r'%s\s*=[\s"]*(.+?)[\s"]*;' % k, content).group(1)
|
||||
key = parser.cssselect('#dm5_key')[0].get('value')
|
||||
cid = s(r'\bDM5_CID')
|
||||
mid = s(r'\bDM5_MID')
|
||||
sign = s(r'\bDM5_VIEWSIGN')
|
||||
sign_dt = quote_plus(s(r'\bDM5_VIEWSIGN_DT'))
|
||||
chapter_idx = self.re.search(r'/(m\d+)', self.chapter[0]).group(1)
|
||||
url = '{}/{}/chapterfun.ashx?cid={}&page={}&key={}&language=1>k=6&_cid={}&_mid={}&_dt={}&_sign={}'
|
||||
items = []
|
||||
for page in range(pages):
|
||||
data = self.http_get(url.format(
|
||||
self.domain, chapter_idx,
|
||||
cid, page + 1, key, cid,
|
||||
mid, sign_dt, sign,
|
||||
), headers=self._get_headers())
|
||||
item_url = execjs.eval(data)
|
||||
if item_url:
|
||||
items += item_url
|
||||
return items
|
||||
|
||||
def save_file(self, idx=None, callback=None, url=None, in_arc_name=None):
|
||||
self._storage['referer'] = self.chapter[0]
|
||||
_path, idx, _url = self._save_file_params_helper(url, idx)
|
||||
|
||||
if not is_file(_path):
|
||||
self.http(True).download_file(_url, _path, idx)
|
||||
callable(callback) and callback()
|
||||
self.after_file_save(_path, idx)
|
||||
self._archive.lazy_add(_path)
|
||||
return _path
|
||||
|
||||
@staticmethod
|
||||
def _get_headers():
|
||||
return {'Cache-mode': 'no-cache', 'X-Requested-With': 'XMLHttpRequest'}
|
||||
|
||||
def get_cover(self) -> str:
|
||||
return self._cover_from_content('.banner_detail_form .cover > img')
|
||||
|
||||
def book_meta(self) -> dict:
|
||||
rating = self.text_content(self.content, '.right .score', 0)
|
||||
rating = self.re.search(r'(\d\d?\.\d)', rating).group(1)
|
||||
author = self.text_content(self.content, '.banner_detail_form .info .subtitle a')
|
||||
anno = self.text_content(self.content, '.banner_detail_form .info .content')
|
||||
return {
|
||||
'author': author,
|
||||
'title': self.get_manga_name(),
|
||||
'annotation': anno,
|
||||
'keywords': str,
|
||||
'cover': self.get_cover(),
|
||||
'rating': rating,
|
||||
}
|
||||
|
||||
def chapter_for_json(self):
|
||||
return self.chapter[0]
|
||||
|
||||
|
||||
main = Dm5Com
|
||||
38
manga-py-stable_1.x/manga_py/providers/doujins_com.py
Normal file
38
manga-py-stable_1.x/manga_py/providers/doujins_com.py
Normal file
@@ -0,0 +1,38 @@
|
||||
from manga_py.provider import Provider
|
||||
from .helpers.std import Std
|
||||
|
||||
|
||||
class DoujinsCom(Provider, Std):
|
||||
img_selector = '#image-container img.doujin'
|
||||
|
||||
def get_archive_name(self) -> str:
|
||||
return 'archive'
|
||||
|
||||
def get_chapter_index(self) -> str:
|
||||
return '0'
|
||||
|
||||
def get_main_content(self):
|
||||
return self._get_content('{}/gallery/{}')
|
||||
|
||||
def get_manga_name(self) -> str:
|
||||
return self._get_name('/gallery/([^/]+)')
|
||||
|
||||
def get_chapters(self):
|
||||
return [b'']
|
||||
|
||||
def get_files(self):
|
||||
items = self.document_fromstring(self.content, self.img_selector)
|
||||
return [i.get('data-file').replace('&', '&') for i in items]
|
||||
|
||||
def get_cover(self) -> str:
|
||||
return self._cover_from_content(self.img_selector)
|
||||
|
||||
def book_meta(self) -> dict:
|
||||
# todo meta
|
||||
pass
|
||||
|
||||
def chapter_for_json(self):
|
||||
return self.get_url()
|
||||
|
||||
|
||||
main = DoujinsCom
|
||||
67
manga-py-stable_1.x/manga_py/providers/e_hentai_org.py
Normal file
67
manga-py-stable_1.x/manga_py/providers/e_hentai_org.py
Normal file
@@ -0,0 +1,67 @@
|
||||
from lxml.html import HtmlElement
|
||||
|
||||
from manga_py.provider import Provider
|
||||
from .helpers import e_hentai_org
|
||||
from .helpers.std import Std
|
||||
from time import sleep
|
||||
|
||||
|
||||
class EHentaiOrg(Provider, Std):
|
||||
helper = None
|
||||
|
||||
def save_file(self, idx=None, callback=None, url=None, in_arc_name=None):
|
||||
_url = None
|
||||
if isinstance(url, HtmlElement):
|
||||
_url = self.helper.get_image(url)
|
||||
else:
|
||||
_url = url
|
||||
return super().save_file(idx=idx, callback=callback, url=_url, in_arc_name=in_arc_name)
|
||||
|
||||
def get_chapter_index(self) -> str:
|
||||
return str(self.chapter_id)
|
||||
|
||||
def get_main_content(self):
|
||||
return self.http_get(self.helper.get_url())
|
||||
|
||||
def get_manga_name(self) -> str:
|
||||
return self._get_name('/g/([^/]+/[^/?]+)').replace('/', '-')
|
||||
|
||||
def prepare_cookies(self):
|
||||
self.helper = e_hentai_org.EHentaiOrg(self)
|
||||
self.http().cookies['nw'] = "1" # issue #178
|
||||
self.http().cookies['nm'] = "1" # issue #178
|
||||
|
||||
def get_chapters(self):
|
||||
parser = self.document_fromstring(self.content)
|
||||
max_idx = self.helper.get_pages_count(parser)
|
||||
self.log('Please, wait...\n')
|
||||
return list(range(max_idx, -1, -1))
|
||||
|
||||
def get_files(self):
|
||||
url = self.helper.get_url() + '?p='
|
||||
selector = '#gdt div[class^=gdt] a'
|
||||
idx = self.chapter
|
||||
if idx == 0:
|
||||
content = self.content
|
||||
else:
|
||||
content = self.http_get('{}{}'.format(url, idx))
|
||||
pages = self.document_fromstring(content, selector)
|
||||
|
||||
n = self.http().normalize_uri
|
||||
f = self.document_fromstring
|
||||
|
||||
images = []
|
||||
for page in pages:
|
||||
_url = n(page.get('href'))
|
||||
images.append(n(f(self.http_get(_url), '#img', 0).get('src')))
|
||||
sleep(.1)
|
||||
return images
|
||||
|
||||
def get_cover(self) -> str:
|
||||
return self._cover_from_content('#gd1 > div')
|
||||
|
||||
def chapter_for_json(self):
|
||||
return self.get_url()
|
||||
|
||||
|
||||
main = EHentaiOrg
|
||||
82
manga-py-stable_1.x/manga_py/providers/exhentai_org.py
Normal file
82
manga-py-stable_1.x/manga_py/providers/exhentai_org.py
Normal file
@@ -0,0 +1,82 @@
|
||||
from sys import exit
|
||||
from time import sleep
|
||||
|
||||
from manga_py.fs import get_util_home_path, path_join, is_file, unlink
|
||||
from .e_hentai_org import EHentaiOrg
|
||||
|
||||
|
||||
from lxml.html import HtmlElement
|
||||
|
||||
|
||||
class ExHentaiOrg(EHentaiOrg):
|
||||
__uri = 'https://forums.e-hentai.org/index.php?act=Login&CODE={}'
|
||||
cookie_file = None
|
||||
|
||||
def prepare_cookies(self):
|
||||
super().prepare_cookies()
|
||||
|
||||
self.cookie_file = path_join(get_util_home_path(), 'cookies_exhentai.dat')
|
||||
if is_file(self.cookie_file):
|
||||
with open(self.cookie_file, 'r') as r:
|
||||
self._storage['cookies'] = self.json.loads(r.read())
|
||||
self.http().cookies = self._storage['cookies'].copy()
|
||||
else:
|
||||
action, method, form_data = self.prepare_form()
|
||||
content = self.http().requests(action, data=form_data, method=method.lower())
|
||||
if not ~content.text.find('You are now logged in as:'):
|
||||
self.log('Wrong password?')
|
||||
sleep(.1)
|
||||
exit()
|
||||
else:
|
||||
with open(self.cookie_file, 'w') as w:
|
||||
w.write(self.json.dumps(self._storage['cookies']))
|
||||
|
||||
sleep(5)
|
||||
|
||||
if not self.check_panda():
|
||||
self.log('Panda detected. Please, try again')
|
||||
exit(1)
|
||||
|
||||
def prepare_form(self):
|
||||
# Login on e-hentai!
|
||||
name = self.quest([], 'Request login on e-hentai.org')
|
||||
password = self.quest_password('Request password on e-hentai.org\n')
|
||||
|
||||
selectors = [
|
||||
'input[type="hidden"]',
|
||||
'input[checked]',
|
||||
'input[type="submit"]',
|
||||
]
|
||||
|
||||
form_data = {
|
||||
'UserName': name,
|
||||
'PassWord': password,
|
||||
}
|
||||
prepare = self.http_get(self.__uri.format('00'))
|
||||
parser = self.document_fromstring(prepare, 'form[name="LOGIN"]')[0] # type: HtmlElement
|
||||
action = parser.get('action', self.__uri.format('01'))
|
||||
method = parser.get('method', 'get')
|
||||
for i in parser.cssselect(','.join(selectors)): # type: HtmlElement
|
||||
form_data[i.get('name')] = i.get('value')
|
||||
|
||||
return action, method, form_data
|
||||
|
||||
def check_panda(self):
|
||||
success = True
|
||||
req = self.http().requests('https://exhentai.org/', method='head')
|
||||
if ~req.headers['Content-Type'].find('image/'):
|
||||
"""
|
||||
if authorization was not successful
|
||||
"""
|
||||
self.log('Sad panda detected')
|
||||
# self.log('Cookies:\n')
|
||||
# self.log(self.http().cookies, '\n')
|
||||
self.http().cookies = {}
|
||||
unlink(self.cookie_file)
|
||||
success = False
|
||||
req.close()
|
||||
|
||||
return success
|
||||
|
||||
|
||||
main = ExHentaiOrg
|
||||
99
manga-py-stable_1.x/manga_py/providers/fanfox_net.py
Normal file
99
manga-py-stable_1.x/manga_py/providers/fanfox_net.py
Normal file
@@ -0,0 +1,99 @@
|
||||
from manga_py.crypt.base_lib import BaseLib
|
||||
from manga_py.provider import Provider
|
||||
from .helpers.std import Std
|
||||
|
||||
|
||||
class MangaFoxMe(Provider, Std):
|
||||
|
||||
def get_archive_name(self) -> str:
|
||||
groups = self._ch_parser()
|
||||
ch = groups[1].replace('.', '-')
|
||||
vol = ['0']
|
||||
if groups[0]:
|
||||
vol = [groups[0]]
|
||||
return self.normal_arc_name({'vol': vol, 'ch': ch})
|
||||
|
||||
def _ch_parser(self):
|
||||
selector = r'/manga/[^/]+/(?:v([^/]+)/)?c([^/]+)/'
|
||||
groups = self.re.search(selector, self.chapter).groups()
|
||||
return groups
|
||||
|
||||
def get_chapter_index(self) -> str:
|
||||
groups = self._ch_parser()
|
||||
idx = groups[1].replace('.', '-')
|
||||
if not ~idx.find('-'):
|
||||
idx = idx + '-0'
|
||||
if groups[0]:
|
||||
return '{}-{}'.format(idx, groups[0])
|
||||
return idx
|
||||
|
||||
def get_main_content(self):
|
||||
return self._get_content('{}/manga/{}')
|
||||
|
||||
def get_manga_name(self) -> str:
|
||||
return self._get_name('/manga/([^/]+)/?')
|
||||
|
||||
def get_chapters(self):
|
||||
return self._elements('[id^="list-"] a[href]')
|
||||
|
||||
def _get_links(self, content):
|
||||
js = self.re.search(r'eval\((function\b.+)\((\'[\w ].+)\)\)', content).groups()
|
||||
return BaseLib.exec_js('m = ' + js[0], 'm(' + js[1] + ')')
|
||||
|
||||
def _one_link_helper(self, content, page):
|
||||
cid = self.re.search(r'chapterid\s*=\s*(\d+)', content).group(1)
|
||||
base_url = self.chapter[0:self.chapter.rfind('/')]
|
||||
links = self._get_links(content)
|
||||
key = ''.join(self.re.findall(r'\'(\w)\'', links))
|
||||
return self.http_get('{}/chapterfun.ashx?cid={}&page={}&key={}'.format(
|
||||
base_url,
|
||||
cid,
|
||||
page,
|
||||
key
|
||||
))
|
||||
|
||||
def _parse_links(self, data):
|
||||
base_path = self.re.search(r'pix="(.+?)"', data).group(1)
|
||||
images = self.re.findall(r'"(/\w.+?)"', data)
|
||||
return [base_path + i for i in images]
|
||||
|
||||
def _get_links_page_to_page(self, content):
|
||||
last_page = self.document_fromstring(content, '.pager-list-left > span > a:nth-last-child(2)', 0)
|
||||
links = []
|
||||
for i in range(0, int(int(last_page.get('data-page')) / 2 + .5)):
|
||||
data = self._one_link_helper(content, (i * 2) + 1)
|
||||
links += self._parse_links(self._get_links(data))
|
||||
return links
|
||||
|
||||
def get_files(self):
|
||||
content = self.http_get(self.chapter)
|
||||
links = self._get_links(content)
|
||||
|
||||
n = self.http().normalize_uri
|
||||
|
||||
if ~links.find('key='):
|
||||
# chapters data example: http://fanfox.net/manga/the_hero_is_overpowered_but_overly_cautious/c001/chapterfun.ashx?cid=567602&page=6&key=6b5367d728d445a8
|
||||
return self._get_links_page_to_page(content)
|
||||
|
||||
if ~links.find('token='):
|
||||
links_array = self.re.search(r'(\[.+?\])', links)
|
||||
links_array = links_array.group(1).replace('\'', '"')
|
||||
links_data = self.json.loads(links_array)
|
||||
return [n(i) for i in links_data]
|
||||
|
||||
data = self.re.search(r'\w=(\[.+\])', links).group(1)
|
||||
data = self.json.loads(data.replace("'", '"'))
|
||||
return [n(i) for i in data]
|
||||
|
||||
def get_cover(self):
|
||||
return self._cover_from_content('img.detail-info-cover-img')
|
||||
|
||||
def book_meta(self) -> dict:
|
||||
# todo meta
|
||||
pass
|
||||
|
||||
def prepare_cookies(self):
|
||||
self.http().cookies['isAdult'] = '1'
|
||||
|
||||
|
||||
main = MangaFoxMe
|
||||
50
manga-py-stable_1.x/manga_py/providers/freeadultcomix_com.py
Normal file
50
manga-py-stable_1.x/manga_py/providers/freeadultcomix_com.py
Normal file
@@ -0,0 +1,50 @@
|
||||
from manga_py.provider import Provider
|
||||
from .helpers.std import Std
|
||||
|
||||
|
||||
class FreeAdultComixCom(Provider, Std):
|
||||
|
||||
def get_archive_name(self) -> str:
|
||||
return 'archive'
|
||||
|
||||
def get_chapter_index(self) -> str:
|
||||
return '0'
|
||||
|
||||
def get_main_content(self):
|
||||
return self._get_content('{}/{}')
|
||||
|
||||
def get_manga_name(self) -> str:
|
||||
return self._get_name(r'\.com/([^/]+)')
|
||||
|
||||
def get_chapters(self):
|
||||
return [b'']
|
||||
|
||||
def _external_images(self): # https://freeadultcomix.com/star-vs-the-forces-of-sex-iii-croc/
|
||||
links = self._elements('.single-post p > a[target="_blank"] > img')
|
||||
items = []
|
||||
re = self.re.compile(r'(.+/)th(/.+)')
|
||||
for i in links:
|
||||
g = re.search(i.get('src')).groups()
|
||||
items.append('{}/i/{}/0.jpg'.format(*g))
|
||||
return items
|
||||
|
||||
def get_files(self):
|
||||
images = self._elements('.single-post p > img[class*="wp-image-"]')
|
||||
if not len(images):
|
||||
items = self._external_images()
|
||||
else:
|
||||
items = [i.get('src') for i in images]
|
||||
return items
|
||||
|
||||
def get_cover(self) -> str:
|
||||
pass
|
||||
|
||||
def book_meta(self) -> dict:
|
||||
# todo meta
|
||||
pass
|
||||
|
||||
def chapter_for_json(self):
|
||||
return self.get_url()
|
||||
|
||||
|
||||
main = FreeAdultComixCom
|
||||
38
manga-py-stable_1.x/manga_py/providers/freemanga_to.py
Normal file
38
manga-py-stable_1.x/manga_py/providers/freemanga_to.py
Normal file
@@ -0,0 +1,38 @@
|
||||
from manga_py.provider import Provider
|
||||
from .helpers.std import Std
|
||||
|
||||
|
||||
class FreeMangaTo(Provider, Std):
|
||||
|
||||
def get_chapter_index(self) -> str:
|
||||
re = self.re.compile(r'[Cc]hapter\s(\d+(?:\.\d+)?)')
|
||||
chapter = re.search(self.chapter[0]).group(1)
|
||||
return chapter.replace('.', '-')
|
||||
|
||||
def get_main_content(self):
|
||||
return self._get_content('{}/manga/{}')
|
||||
|
||||
def get_manga_name(self) -> str:
|
||||
return self._get_name('/(?:manga|chapter)/([^/]+)')
|
||||
|
||||
def get_chapters(self):
|
||||
items = self._elements('.readIcon a')
|
||||
n = self.http().normalize_uri
|
||||
return [(i.text_content(), n(i.get('href'))) for i in items]
|
||||
|
||||
def get_files(self):
|
||||
content = self.http_get(self.chapter[1])
|
||||
images = self.re.search(r'image:\s*(\[.+\])', content)
|
||||
return self.json.loads(images.group(1))
|
||||
|
||||
def get_cover(self) -> str:
|
||||
return self._cover_from_content('.tooltips > img')
|
||||
|
||||
def book_meta(self) -> dict:
|
||||
pass
|
||||
|
||||
def chapter_for_json(self) -> str:
|
||||
return self.chapter[1]
|
||||
|
||||
|
||||
main = FreeMangaTo
|
||||
35
manga-py-stable_1.x/manga_py/providers/funmanga_com.py
Normal file
35
manga-py-stable_1.x/manga_py/providers/funmanga_com.py
Normal file
@@ -0,0 +1,35 @@
|
||||
from manga_py.provider import Provider
|
||||
from .helpers.std import Std
|
||||
|
||||
|
||||
class FunMangaCom(Provider, Std):
|
||||
|
||||
def _get_chapter_idx(self):
|
||||
re = self.re.compile(r'\.com/[^/]+/([^/]+)')
|
||||
return re.search(self.chapter).group(1)
|
||||
|
||||
def get_chapter_index(self) -> str:
|
||||
return self._get_chapter_idx().replace('.', '-')
|
||||
|
||||
def get_main_content(self):
|
||||
return self._get_content('{}/{}')
|
||||
|
||||
def get_manga_name(self) -> str:
|
||||
return self._get_name(r'\.com/([^/]+)')
|
||||
|
||||
def get_chapters(self):
|
||||
items = self._elements('.chapter-list li > a')
|
||||
return [i.get('href') + '/all-pages' for i in items]
|
||||
|
||||
def get_files(self):
|
||||
items = self.html_fromstring(self.chapter, '.content-inner > img.img-responsive')
|
||||
return [i.get('src') for i in items]
|
||||
|
||||
def get_cover(self):
|
||||
return self._cover_from_content('img.img-responsive.mobile-img')
|
||||
|
||||
def prepare_cookies(self):
|
||||
self.cf_protect(self.get_url())
|
||||
|
||||
|
||||
main = FunMangaCom
|
||||
23
manga-py-stable_1.x/manga_py/providers/gmanga_me.py
Normal file
23
manga-py-stable_1.x/manga_py/providers/gmanga_me.py
Normal file
@@ -0,0 +1,23 @@
|
||||
from .gomanga_co import GoMangaCo
|
||||
|
||||
|
||||
class GMangaMe(GoMangaCo):
|
||||
_name_re = '/mangas/([^/]+)'
|
||||
_content_str = '{}/mangas/{}'
|
||||
_chapters_selector = 'a.chapter-link'
|
||||
|
||||
def get_chapter_index(self) -> str:
|
||||
selector = r'/mangas/[^/]+/(\d+/[^/]+)'
|
||||
idx = self.re.search(selector, self.chapter).group(1)
|
||||
return idx.replace('/', '-')
|
||||
|
||||
def _get_json_selector(self, content):
|
||||
return r'1:\salphanumSort\((\[.+\])\)'
|
||||
|
||||
def get_cover(self) -> str:
|
||||
image = self.re.search(r'"image"\s?:\s?"(.+)",', self.content)
|
||||
if image:
|
||||
return image.group(1)
|
||||
|
||||
|
||||
main = GMangaMe
|
||||
56
manga-py-stable_1.x/manga_py/providers/gomanga_co.py
Normal file
56
manga-py-stable_1.x/manga_py/providers/gomanga_co.py
Normal file
@@ -0,0 +1,56 @@
|
||||
from manga_py.provider import Provider
|
||||
from .helpers.std import Std
|
||||
|
||||
|
||||
class GoMangaCo(Provider, Std):
|
||||
_name_re = '/reader/[^/]+/([^/]+)/'
|
||||
_content_str = '{}/reader/series/{}/'
|
||||
_chapters_selector = '.list .element .title a'
|
||||
_chapter_re = r'/rea\w+/[^/]+/[^/]+/(?:[^/]+/)?(\d+/\d+(?:/\d+)?)'
|
||||
|
||||
_go_chapter_content = ''
|
||||
|
||||
def get_chapter_index(self) -> str:
|
||||
group = self.re.search(self._chapter_re, self.chapter).group(1)
|
||||
return group.replace('/', '-')
|
||||
|
||||
def get_main_content(self):
|
||||
return self._get_content(self._content_str)
|
||||
|
||||
def get_manga_name(self) -> str:
|
||||
return self._get_name(self._name_re)
|
||||
|
||||
def get_chapters(self):
|
||||
return self._elements(self._chapters_selector)
|
||||
|
||||
def _get_json_selector(self, content):
|
||||
idx = self.re.search(r'page_width\s=\sparseInt\((\w+)\[', content).group(1)
|
||||
return r'var\s{}\s*=\s*(\[.+\])'.format(idx)
|
||||
|
||||
def get_files(self):
|
||||
self._go_chapter_content = self.http_get(self.chapter)
|
||||
selector = self._get_json_selector(self._go_chapter_content)
|
||||
items = self.json.loads(self.re.search(selector, self._go_chapter_content).group(1))
|
||||
return [i.get('url') for i in items]
|
||||
|
||||
def get_cover(self) -> str:
|
||||
return self._cover_from_content('.cover img')
|
||||
|
||||
def prepare_cookies(self):
|
||||
url = self.get_url()
|
||||
self.cf_protect(url)
|
||||
data = {'adult': 'true'}
|
||||
try:
|
||||
response = self.http().requests(method='post', data=data, url=url)
|
||||
cookies = response.cookies.items()
|
||||
for i in cookies:
|
||||
self._storage['cookies'][i[0]] = i[1]
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
def book_meta(self) -> dict:
|
||||
# todo meta
|
||||
pass
|
||||
|
||||
|
||||
main = GoMangaCo
|
||||
53
manga-py-stable_1.x/manga_py/providers/goodmanga_net.py
Normal file
53
manga-py-stable_1.x/manga_py/providers/goodmanga_net.py
Normal file
@@ -0,0 +1,53 @@
|
||||
from manga_py.provider import Provider
|
||||
from .helpers.std import Std
|
||||
|
||||
|
||||
class GoodMangaNet(Provider, Std):
|
||||
|
||||
def get_chapter_index(self) -> str:
|
||||
return self.re.search(r'/chapter/(\d+)', self.chapter).group(1)
|
||||
|
||||
def get_main_content(self):
|
||||
url = self.get_url()
|
||||
if ~url.find('/chapter/'):
|
||||
url = self.html_fromstring(url, '#manga_head h3 > a', 0).get('href')
|
||||
_id = self.re.search(r'net/(\d+/[^/]+)', url).group(1)
|
||||
return self.http_get('{}/{}'.format(self.domain, _id))
|
||||
|
||||
def get_manga_name(self) -> str:
|
||||
url = self.get_url()
|
||||
reg = r'/([^/]+)/chapter/|net/\d+/([^/]+)'
|
||||
groups = self.re.search(reg, url).groups()
|
||||
return groups[0] if groups[0] else groups[1]
|
||||
|
||||
@staticmethod
|
||||
def get_chapters_links(parser):
|
||||
return [i.get('href') for i in parser.cssselect('#chapters li > a')]
|
||||
|
||||
def get_chapters(self):
|
||||
selector = '#chapters li > a'
|
||||
chapters = self._elements(selector)
|
||||
pagination = self._elements('.pagination li > button[href]')
|
||||
for i in pagination:
|
||||
chapters += self._elements(selector, self.http_get(i.get('href')))
|
||||
return chapters
|
||||
|
||||
def get_files(self):
|
||||
img_selector = '#manga_viewer > a > img'
|
||||
parser = self.html_fromstring(self.chapter)
|
||||
images = self._images_helper(parser, img_selector)
|
||||
pages = self._first_select_options(parser, '#asset_2 select.page_select', True)
|
||||
for i in pages:
|
||||
_parser = self.html_fromstring(i.get('value'))
|
||||
images += self._images_helper(_parser, img_selector)
|
||||
return images
|
||||
|
||||
def get_cover(self):
|
||||
pass # TODO
|
||||
|
||||
def book_meta(self) -> dict:
|
||||
# todo meta
|
||||
pass
|
||||
|
||||
|
||||
main = GoodMangaNet
|
||||
47
manga-py-stable_1.x/manga_py/providers/hakihome_com.py
Normal file
47
manga-py-stable_1.x/manga_py/providers/hakihome_com.py
Normal file
@@ -0,0 +1,47 @@
|
||||
from manga_py.provider import Provider
|
||||
from .helpers.std import Std
|
||||
|
||||
|
||||
class HakiHomeCom(Provider, Std):
|
||||
|
||||
def get_chapter_index(self) -> str:
|
||||
selector = '.+/([^/]+)/'
|
||||
idx = self.re.search(selector, self.chapter)
|
||||
return idx.group(1)
|
||||
|
||||
def get_main_content(self):
|
||||
selector = r'(https?://[^/]+/[^/]+/[^/]+-\d+/)'
|
||||
url = self.re.search(selector, self.get_url())
|
||||
return self.http_get(url.group(1))
|
||||
|
||||
def get_manga_name(self) -> str:
|
||||
url = self.get_url()
|
||||
selector = r'\.com/[^/]+/(.+?)-\d+/'
|
||||
return self.re.search(selector, url).group(1)
|
||||
|
||||
def get_chapters(self):
|
||||
return self._elements('.listing a.readchap')
|
||||
|
||||
def get_files(self):
|
||||
img_selector = '#con img'
|
||||
n = self.http().normalize_uri
|
||||
uri = n(self.chapter)
|
||||
parser = self.html_fromstring(uri, '#contentchap', 0)
|
||||
pages = self._first_select_options(parser, '#botn span > select[onchange]')
|
||||
images = self._images_helper(parser, img_selector)
|
||||
|
||||
for i in pages:
|
||||
parser = self.html_fromstring(n(i.get('value')), '#contentchap', 0)
|
||||
images += self._images_helper(parser, img_selector)
|
||||
|
||||
return images
|
||||
|
||||
def get_cover(self) -> str:
|
||||
return self._cover_from_content('.noidung img')
|
||||
|
||||
def book_meta(self) -> dict:
|
||||
# todo meta
|
||||
pass
|
||||
|
||||
|
||||
main = HakiHomeCom
|
||||
23
manga-py-stable_1.x/manga_py/providers/hatigarmscans_eu.py
Normal file
23
manga-py-stable_1.x/manga_py/providers/hatigarmscans_eu.py
Normal file
@@ -0,0 +1,23 @@
|
||||
from .gomanga_co import GoMangaCo
|
||||
|
||||
|
||||
class HatigarmScansEu(GoMangaCo):
|
||||
_name_re = '/manga/([^/]+)'
|
||||
_content_str = '{}/manga/{}/'
|
||||
_chapters_selector = '.chapters [class^="chapter-title"] a'
|
||||
|
||||
def get_chapter_index(self) -> str:
|
||||
url = self.chapter
|
||||
index_re = r'/manga/[^/]+/(?:chapter-)?(\d+(?:\.\d+)?)'
|
||||
group = self.re.search(index_re, url).group(1)
|
||||
return group.replace('.', '-')
|
||||
|
||||
def prepare_cookies(self):
|
||||
pass
|
||||
|
||||
def get_files(self):
|
||||
parser = self.html_fromstring(self.chapter)
|
||||
return self._images_helper(parser, '#all .img-responsive', 'data-src')
|
||||
|
||||
|
||||
main = HatigarmScansEu
|
||||
48
manga-py-stable_1.x/manga_py/providers/heavenmanga_biz.py
Normal file
48
manga-py-stable_1.x/manga_py/providers/heavenmanga_biz.py
Normal file
@@ -0,0 +1,48 @@
|
||||
from manga_py.provider import Provider
|
||||
from .helpers.std import Std
|
||||
|
||||
|
||||
class HeavenMangaBiz(Provider, Std):
|
||||
|
||||
def get_chapter_index(self) -> str:
|
||||
try:
|
||||
return self.re.search(r'-chap-(\d+(?:-\d+)?)', self.chapter).group(1)
|
||||
except Exception as e:
|
||||
if self.re.search(r'-chap$', self.chapter):
|
||||
return '0'
|
||||
raise e
|
||||
|
||||
def get_main_content(self):
|
||||
return self._get_content('{}/{}/')
|
||||
|
||||
def get_manga_name(self) -> str:
|
||||
s = self.domain[self.domain.rfind('.'):]
|
||||
selector = r'\%s/([^/]+)'
|
||||
if ~self.get_url().find('-chap-'):
|
||||
selector += '-chap-'
|
||||
return self._get_name(selector % s)
|
||||
|
||||
def get_chapters(self):
|
||||
selector = '.chapters-wrapper h2.chap > a'
|
||||
pages = self._elements('a.next.page-numbers')
|
||||
items = self._elements(selector)
|
||||
if pages:
|
||||
pages = self.re.search(r'/page-(\d+)', pages[-1].get('href')).group(1)
|
||||
for i in range(1, int(pages)):
|
||||
url = '{}/{}/page-{}'.format(self.domain, self.manga_name, i + 1)
|
||||
items += self._elements(selector, self.http_get(url))
|
||||
return items
|
||||
|
||||
def get_files(self):
|
||||
parser = self.html_fromstring(self.chapter)
|
||||
return self._images_helper(parser, '.chapter-content img')
|
||||
|
||||
def get_cover(self) -> str:
|
||||
return self._cover_from_content('.comic-info .thumb > img')
|
||||
|
||||
def book_meta(self) -> dict:
|
||||
# todo meta
|
||||
pass
|
||||
|
||||
|
||||
main = HeavenMangaBiz
|
||||
72
manga-py-stable_1.x/manga_py/providers/helpers/_http2.py
Normal file
72
manga-py-stable_1.x/manga_py/providers/helpers/_http2.py
Normal file
@@ -0,0 +1,72 @@
|
||||
class Http2:
|
||||
provider = None
|
||||
path_join = None
|
||||
is_file = None
|
||||
chapters = None
|
||||
chapters_count = 0
|
||||
|
||||
def __init__(self, provider):
|
||||
from manga_py.fs import path_join, is_file
|
||||
self.provider = provider
|
||||
self.path_join = path_join
|
||||
self.is_file = is_file
|
||||
|
||||
def _get_name(self, idx):
|
||||
return self.path_join(
|
||||
self.provider._params.get('destination'),
|
||||
self.provider._storage['manga_name'],
|
||||
'{:0>3}-{}.{}'.format(
|
||||
idx, self.provider.get_archive_name(),
|
||||
self.provider._archive_type()
|
||||
)
|
||||
)
|
||||
|
||||
def __download(self, idx, name, url):
|
||||
_min, _max = self._min_max_calculate()
|
||||
self.provider._info.add_volume(
|
||||
self.provider.chapter,
|
||||
self.provider.get_archive_path()
|
||||
)
|
||||
|
||||
self.provider.progress(self.chapters_count, idx)
|
||||
|
||||
if idx < _min or (idx >= _max > 0) or self.is_file(name):
|
||||
return False
|
||||
|
||||
if not self.provider._simulate:
|
||||
try:
|
||||
self.provider.http().download_file(url, name, idx)
|
||||
except Exception as e:
|
||||
self.provider._info.set_last_volume_error(e)
|
||||
|
||||
def _min_max_calculate(self):
|
||||
_min = self.provider._params.get('skip_volumes', 0)
|
||||
_max = self.provider._params.get('max_volumes', 0)
|
||||
self.chapters_count = len(self.chapters)
|
||||
if _max > 0 or _min > 0:
|
||||
if _max < self.chapters_count:
|
||||
_max = self.chapters_count - _max
|
||||
else:
|
||||
_max = 0
|
||||
self.chapters_count = self.chapters_count - _min - _max
|
||||
if _max > 0 and _min > 0:
|
||||
_max += _min - 1
|
||||
return _min, _max
|
||||
|
||||
def download_archives(self, chapters=None):
|
||||
if chapters is None:
|
||||
chapters = self.provider._storage['chapters']
|
||||
self.chapters = chapters
|
||||
for idx, url in enumerate(chapters):
|
||||
self.provider.before_download_chapter()
|
||||
self.provider._storage['current_chapter'] = idx
|
||||
name = self._get_name(idx)
|
||||
idx, url, name = self.before_download(idx, url, name)
|
||||
self.__download(idx, name, url)
|
||||
self.after_download(idx, name)
|
||||
|
||||
def before_download(self, idx, url, _path):
|
||||
return idx, url, _path
|
||||
|
||||
def after_download(self, idx, _path):
|
||||
pass
|
||||
@@ -0,0 +1,81 @@
|
||||
from manga_py.provider import Provider
|
||||
|
||||
|
||||
class AnimeXtremistCom:
|
||||
provider = None
|
||||
path = None
|
||||
|
||||
def __init__(self, provider: Provider):
|
||||
self.provider = provider
|
||||
self.path = provider.get_url()
|
||||
|
||||
@staticmethod
|
||||
def build_path(item):
|
||||
return item[0] + item[1]
|
||||
|
||||
@staticmethod
|
||||
def __sort(item, selector):
|
||||
_re = selector.search(item)
|
||||
if _re:
|
||||
return int(_re.group(1))
|
||||
return 0
|
||||
|
||||
def sort_items(self, items):
|
||||
r = self.provider.re.compile(r'.+?-(\d+)')
|
||||
return sorted(items, key=lambda i: self.__sort(i[0], r))
|
||||
|
||||
def sort_images(self, items):
|
||||
r = self.provider.re.compile(r'.+/.+-(\d+)[^/]*\.html')
|
||||
return sorted(items, key=lambda i: self.__sort(i, r))
|
||||
|
||||
def _chapters(self, url=None):
|
||||
a = 'li + li > a'
|
||||
if url:
|
||||
items = self.provider.html_fromstring(url, a)
|
||||
else:
|
||||
items = self.provider.document_fromstring(self.provider.content, a)
|
||||
return items
|
||||
|
||||
# http://animextremist.com/mangas-online/99love/
|
||||
def _chapters_with_dirs(self, items):
|
||||
result = []
|
||||
for i in items:
|
||||
href = i.get('href')
|
||||
url = '{}{}'.format(self.path, href)
|
||||
result += [(href, ['{}{}'.format(
|
||||
url,
|
||||
a.get('href')
|
||||
) for a in self._chapters(url)])]
|
||||
return result
|
||||
|
||||
@staticmethod
|
||||
def _rebuild_dict_to_tuple(_dict):
|
||||
result = []
|
||||
for i in _dict:
|
||||
result += [(i, [a for a in _dict[i]])]
|
||||
return result
|
||||
|
||||
# http://animextremist.com/mangas-online/onepiece-manga/
|
||||
def _chapters_without_dirs(self, items):
|
||||
result = {}
|
||||
r = self.provider.re.compile(r'(.+?-\d+)') # todo
|
||||
for i in items:
|
||||
href = i.get('href')
|
||||
key = self.provider.re.search(r, href).group(1)
|
||||
if result.get(key) is None:
|
||||
result[key] = []
|
||||
result[key].append('{}{}'.format(self.path, href))
|
||||
return self._rebuild_dict_to_tuple(result)
|
||||
|
||||
def get_chapters(self):
|
||||
items = self._chapters()
|
||||
if len(items) and items[0].get('href').find('.html') < 0:
|
||||
items = self._chapters_with_dirs(items)
|
||||
else:
|
||||
items = self._chapters_without_dirs(items)
|
||||
return self.sort_items(items)
|
||||
|
||||
def get_page_image(self, src, selector, attr='src') -> str:
|
||||
image = self.provider.html_fromstring(src, selector)
|
||||
if image and len(image):
|
||||
return image[0].get(attr)
|
||||
@@ -0,0 +1,30 @@
|
||||
from manga_py.provider import Provider
|
||||
|
||||
|
||||
class EHentaiOrg:
|
||||
provider = None
|
||||
|
||||
def __init__(self, provider: Provider):
|
||||
self.provider = provider
|
||||
|
||||
def get_pages_count(self, parser):
|
||||
selector = '.gtb table.ptt td[onclick] > a'
|
||||
paginate = parser.cssselect(selector)
|
||||
max_idx = 0
|
||||
for i in paginate:
|
||||
idx = self.provider.re.search(r'\?p=(\d+)', i.get('href'))
|
||||
max_idx = max(max_idx, int(idx.group(1)))
|
||||
return max_idx
|
||||
|
||||
def get_image(self, i):
|
||||
url = i.get('href')
|
||||
src = self.provider.html_fromstring(url, 'img#img', 0)
|
||||
return src.get('src')
|
||||
|
||||
def get_url(self):
|
||||
url = self.provider.get_url()
|
||||
if ~url.find('?'):
|
||||
url = url[:url.find('?')]
|
||||
if ~url.find('#'):
|
||||
url = url[:url.find('#')]
|
||||
return url
|
||||
@@ -0,0 +1,26 @@
|
||||
from manga_py.provider import Provider
|
||||
|
||||
|
||||
class EightMusesCom:
|
||||
provider = None
|
||||
|
||||
def __init__(self, provider: Provider):
|
||||
self.provider = provider
|
||||
self._n = provider.http().normalize_uri
|
||||
|
||||
def is_images_page(self, parser) -> bool:
|
||||
if not parser:
|
||||
return False
|
||||
return self.provider.re.search(r'/\d+$', parser[0].get('href')) is not None
|
||||
|
||||
def parser(self, url, selector):
|
||||
return self.provider.html_fromstring(self._n(url), selector)
|
||||
|
||||
def chapters(self, parser) -> list:
|
||||
if self.is_images_page(parser):
|
||||
return [parser]
|
||||
items = []
|
||||
selector = self.provider.chapter_selector
|
||||
for i in parser:
|
||||
items += self.chapters(self.parser(i.get('href'), selector))
|
||||
return items
|
||||
@@ -0,0 +1,50 @@
|
||||
from urllib.parse import urlparse
|
||||
|
||||
from manga_py.http.url_normalizer import normalize_uri
|
||||
from manga_py.provider import Provider
|
||||
|
||||
|
||||
class JavZipOrg:
|
||||
parser = None
|
||||
url = None
|
||||
domain = None
|
||||
|
||||
def __init__(self, parser: Provider):
|
||||
self.parser = parser
|
||||
url = parser.chapter
|
||||
if parser.re.search(r'jav-zip\.org', url):
|
||||
self.url = url
|
||||
_ = urlparse(url)
|
||||
self.domain = _.scheme + '://' + _.netloc
|
||||
|
||||
def _parse_id(self):
|
||||
return self.parser.re.search('/.p=(\d+)', self.url).group(1)
|
||||
|
||||
def parse_images(self, content):
|
||||
images = []
|
||||
for i in content.cssselect('img'):
|
||||
src = normalize_uri(i.get('src'), self.url)
|
||||
images.append(src)
|
||||
return images
|
||||
|
||||
def get(self, step):
|
||||
url = '{}/wp-admin/admin-ajax.php?post={}&action=get_content&step={}'
|
||||
url = url.format(self.domain, self._parse_id, step)
|
||||
content = self.parser.json.loads(self.parser.http_get(url))
|
||||
content = self.parser.document_fromstring(content['mes'])
|
||||
allow_more = True
|
||||
if len(content.cssselect('a.view-more')) < 1:
|
||||
allow_more = False
|
||||
return allow_more, content
|
||||
|
||||
def get_images(self):
|
||||
if not self.url:
|
||||
return []
|
||||
images = []
|
||||
step = 0
|
||||
allow_more = True
|
||||
while allow_more:
|
||||
allow_more, content = self.get(step)
|
||||
step += 50 # constant
|
||||
images += self.parse_images(content)
|
||||
return images
|
||||
53
manga-py-stable_1.x/manga_py/providers/helpers/nine_manga.py
Normal file
53
manga-py-stable_1.x/manga_py/providers/helpers/nine_manga.py
Normal file
@@ -0,0 +1,53 @@
|
||||
from abc import ABCMeta
|
||||
from time import sleep
|
||||
from urllib.parse import unquote
|
||||
|
||||
from requests import get
|
||||
|
||||
from manga_py.provider import Provider
|
||||
|
||||
|
||||
class NineHelper(Provider, metaclass=ABCMeta):
|
||||
img_server = 'https://ta1.taadd.com'
|
||||
|
||||
def re_name(self, url):
|
||||
return self.re.search(r'/manga/(.+)\.html', url)
|
||||
|
||||
@staticmethod
|
||||
def normalize_name(name, normalize):
|
||||
if normalize:
|
||||
name = unquote(name)
|
||||
return name
|
||||
|
||||
def parse_img_uri(self, url):
|
||||
return self.re.search('://[^/]+/(.+)', url).group(1)
|
||||
|
||||
def get_img_server(self, content):
|
||||
server = self.re.search(r'img_url\s?=\s?"([^"]+)', content)
|
||||
if server:
|
||||
return server.group(1)
|
||||
return self.img_server
|
||||
|
||||
def get_files_on_page(self, content):
|
||||
result = self.document_fromstring(content, 'em a.pic_download')
|
||||
if not result:
|
||||
return []
|
||||
images = []
|
||||
pic_url = self.get_img_server(content)
|
||||
for i in result:
|
||||
src = self.parse_img_uri(i.get('href'))
|
||||
images.append('{}/{}'.format(pic_url, src))
|
||||
return images
|
||||
|
||||
def _get_page_content(self, url):
|
||||
sleep(.6)
|
||||
return get(
|
||||
url,
|
||||
headers={
|
||||
'Accept-Language': 'ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3',
|
||||
'Referer': '',
|
||||
} # fix guard
|
||||
).text
|
||||
|
||||
def prepare_cookies(self):
|
||||
self._storage['cookies'].setdefault('__cfduid', '1a2b3c4d5e')
|
||||
150
manga-py-stable_1.x/manga_py/providers/helpers/std.py
Normal file
150
manga-py-stable_1.x/manga_py/providers/helpers/std.py
Normal file
@@ -0,0 +1,150 @@
|
||||
from requests import get
|
||||
from time import sleep
|
||||
|
||||
|
||||
class Std:
|
||||
_vol_fill = False
|
||||
|
||||
def get_archive_name(self) -> str:
|
||||
idx = self.get_chapter_index()
|
||||
self._vol_fill = True
|
||||
return self.normal_arc_name({'vol': idx.split('-')})
|
||||
|
||||
def _elements(self, selector, content=None) -> list:
|
||||
if not content:
|
||||
content = self.content
|
||||
return self.document_fromstring(content, selector)
|
||||
|
||||
def _cover_from_content(self, selector, attr='src') -> str:
|
||||
image = self._elements(selector)
|
||||
if image is not None and len(image):
|
||||
return self.http().normalize_uri(image[0].get(attr))
|
||||
|
||||
@staticmethod
|
||||
def _first_select_options(parser, selector, skip_first=True) -> list:
|
||||
options = 'option'
|
||||
if skip_first:
|
||||
options = 'option + option'
|
||||
select = parser.cssselect(selector)
|
||||
if select:
|
||||
return select[0].cssselect(options)
|
||||
return []
|
||||
|
||||
@classmethod
|
||||
def _images_helper(cls, parser, selector, attr='src') -> list:
|
||||
image = parser.cssselect(selector)
|
||||
return [i.get(attr).strip(' \r\n\t\0') for i in image]
|
||||
|
||||
@classmethod
|
||||
def _idx_to_x2(cls, idx, default=0) -> list:
|
||||
return [
|
||||
str(idx[0]),
|
||||
str(default if len(idx) < 2 or not idx[1] else idx[1])
|
||||
]
|
||||
|
||||
@staticmethod
|
||||
def _join_groups(idx, glue='-') -> str:
|
||||
result = []
|
||||
for i in idx:
|
||||
if i:
|
||||
result.append(i)
|
||||
return glue.join(result)
|
||||
|
||||
def _get_name(self, selector, url=None) -> str:
|
||||
if url is None:
|
||||
url = self.get_url()
|
||||
return self.re.search(selector, url).group(1)
|
||||
|
||||
def _get_content(self, tpl) -> str:
|
||||
return self.http_get(tpl.format(self.domain, self.manga_name))
|
||||
|
||||
def _base_cookies(self, url=None):
|
||||
if url is None:
|
||||
url = self.get_url()
|
||||
cookies = self.http().get_base_cookies(url)
|
||||
self._storage['cookies'] = cookies.get_dict()
|
||||
|
||||
def parse_background(self, image) -> str:
|
||||
selector = r'background.+?url\([\'"]?([^\s]+?)[\'"]?\)'
|
||||
url = self.re.search(selector, image.get('style'))
|
||||
return self.http().normalize_uri(url.group(1))
|
||||
|
||||
@property
|
||||
def manga_name(self) -> str:
|
||||
name = self._storage.get('manga_name', None)
|
||||
if name is None:
|
||||
name = self.get_manga_name()
|
||||
return name
|
||||
|
||||
def normal_arc_name(self, idx):
|
||||
if isinstance(idx, str):
|
||||
idx = [idx]
|
||||
if isinstance(idx, list):
|
||||
self._vol_fill = True
|
||||
return self.__normal_name_list(idx)
|
||||
if isinstance(idx, dict):
|
||||
return self.__normal_name_dict(idx)
|
||||
raise DeprecationWarning('Wrong arc name type: %s' % type(idx))
|
||||
|
||||
@staticmethod
|
||||
def __fill(var, fmt: str = '-{}'):
|
||||
if isinstance(var, str):
|
||||
var = [var]
|
||||
return (fmt * len(var)).format(*var).lstrip('-')
|
||||
|
||||
def __normal_name_list(self, idx: list):
|
||||
fmt = 'vol_{:0>3}'
|
||||
if len(idx) > 1:
|
||||
fmt += '-{}' * (len(idx) - 1)
|
||||
elif self._vol_fill and self._zero_fill:
|
||||
idx.append('0')
|
||||
fmt += '-{}'
|
||||
return fmt.format(*idx)
|
||||
|
||||
def __normal_name_dict(self, idx: dict):
|
||||
vol = idx.get('vol', None)
|
||||
ch = idx.get('ch', None)
|
||||
result = ''
|
||||
if vol:
|
||||
if isinstance(vol, str):
|
||||
vol = [vol]
|
||||
result = self.__normal_name_list(vol)
|
||||
if ch:
|
||||
result += '-ch_' + self.__fill(ch)
|
||||
|
||||
if self._with_manga_name:
|
||||
name = self._params.get('name', '')
|
||||
if not len(name):
|
||||
name = self.manga_name
|
||||
|
||||
result = '%s-%s' % (name, result)
|
||||
|
||||
return result
|
||||
|
||||
def text_content(self, content, selector, idx: int = 0, strip: bool = True):
|
||||
doc = self.document_fromstring(content, selector)
|
||||
if not doc:
|
||||
return None
|
||||
text = doc[idx].text_content()
|
||||
if strip:
|
||||
text = text.strip()
|
||||
return text
|
||||
|
||||
def _download(self, file_name, url, method):
|
||||
# clean file downloader
|
||||
now_try_count = 0
|
||||
while now_try_count < 5:
|
||||
with open(file_name, 'wb') as out_file:
|
||||
now_try_count += 1
|
||||
response = get(url, timeout=60, allow_redirects=True)
|
||||
if response.status_code >= 400:
|
||||
self.http().debug and self.log('ERROR! Code {}\nUrl: {}'.format(
|
||||
response.status_code,
|
||||
url,
|
||||
))
|
||||
sleep(2)
|
||||
continue
|
||||
out_file.write(response.content)
|
||||
response.close()
|
||||
out_file.close()
|
||||
break
|
||||
41
manga-py-stable_1.x/manga_py/providers/helpers/tapas_io.py
Normal file
41
manga-py-stable_1.x/manga_py/providers/helpers/tapas_io.py
Normal file
@@ -0,0 +1,41 @@
|
||||
from manga_py.meta import __downloader_uri__
|
||||
from manga_py.provider import Provider
|
||||
|
||||
|
||||
class TapasIo:
|
||||
provider = None
|
||||
|
||||
def __init__(self, provider: Provider):
|
||||
self.provider = provider
|
||||
|
||||
def _content(self, content):
|
||||
type = content.get('type', None)
|
||||
if type == 'DEFAULT':
|
||||
return self._type_default(content)
|
||||
|
||||
def _error(self, content):
|
||||
self.provider.log('\r\nERROR!\r\nCode: {}\r\nType: {}\r\nPlease, send url to developer ({})'.format(
|
||||
content['code'],
|
||||
content['type'],
|
||||
__downloader_uri__
|
||||
))
|
||||
|
||||
def _type_default(self, content):
|
||||
items = self.provider.document_fromstring(content.get('data', {}).get('html', '<html></html>'), '.art-image')
|
||||
return [i.get('src') for i in items]
|
||||
|
||||
def chapter_url(self):
|
||||
return '{}/episode/view/{}'.format(
|
||||
self.provider.domain,
|
||||
self.provider.chapter['id']
|
||||
)
|
||||
|
||||
def parse_chapter_content(self):
|
||||
content = self.provider.json.loads(self.provider.http_get(self.chapter_url()))
|
||||
if content['code'] != 200:
|
||||
self._error(content)
|
||||
return []
|
||||
_content = self._content(content)
|
||||
if _content is None:
|
||||
self._error(content)
|
||||
return _content
|
||||
@@ -0,0 +1,53 @@
|
||||
from manga_py.crypt import Puzzle
|
||||
from manga_py.fs import get_temp_path, rename
|
||||
from manga_py.provider import Provider
|
||||
|
||||
|
||||
class TonariNoYjJp:
|
||||
provider = None
|
||||
div_num = 4
|
||||
multiply = 8
|
||||
matrix = None
|
||||
temp_path = None
|
||||
|
||||
def __init__(self, provider: Provider):
|
||||
self.provider = provider
|
||||
self.temp_path = get_temp_path('__image_matrix{}.png')
|
||||
matrix = {}
|
||||
for i in range(self.div_num * self.div_num):
|
||||
matrix[i] = (i % self.div_num) * self.div_num + int(i / self.div_num)
|
||||
self.matrix = matrix
|
||||
|
||||
def _chapter_api_content(self, idx) -> dict:
|
||||
api = '{}/api/viewer/readable_products?current_readable_product_id={}&' \
|
||||
'number_since=99&number_until=-1&read_more_num=100&type=episode'
|
||||
content = self.provider.http_get(api.format(self.provider.domain, idx))
|
||||
if content[0] == '{':
|
||||
return self.provider.json.loads(content)
|
||||
return {}
|
||||
|
||||
def _check_need_next_chapter(self, next_url):
|
||||
if next_url:
|
||||
test = self.provider.re.search('number_since=(\d+)', next_url).group(1)
|
||||
if int(test) > 1:
|
||||
return True
|
||||
return False
|
||||
|
||||
def get_chapters(self, idx) -> list:
|
||||
content = self._chapter_api_content(idx)
|
||||
items = self.provider.document_fromstring(content.get('html', '<html></html>'), '.series-episode-list-thumb')
|
||||
need_more = self._check_need_next_chapter(content.get('nextUrl', None))
|
||||
if need_more:
|
||||
items += self.get_chapters(content.get('nextUrl'))
|
||||
re = self.provider.re.compile(r'/episode-thumbnail/(\d+)')
|
||||
return [re.search(i.get('src')).group(1) for i in items]
|
||||
|
||||
def solve_image(self, path, idx):
|
||||
try:
|
||||
solver = Puzzle(self.div_num, self.div_num, self.matrix, self.multiply)
|
||||
solver.need_copy_orig = True
|
||||
_ = self.temp_path.format(idx)
|
||||
solver.de_scramble(path, _)
|
||||
rename(_, path)
|
||||
except Exception:
|
||||
pass
|
||||
@@ -0,0 +1,29 @@
|
||||
from requests import Session
|
||||
|
||||
from manga_py.base_classes import WebDriver
|
||||
from manga_py.provider import Provider
|
||||
|
||||
|
||||
class TsuminoCom:
|
||||
provider = None
|
||||
|
||||
def __init__(self, provider: Provider):
|
||||
self.provider = provider
|
||||
|
||||
def get_cookies(self, url):
|
||||
web_driver = WebDriver()
|
||||
driver = web_driver.get_driver()
|
||||
driver.get(url)
|
||||
iframe = driver.find_element_by_css_selector(".g-recaptcha iframe")
|
||||
src = self.provider.http_get(iframe.get_attribute('src'))
|
||||
driver.close()
|
||||
|
||||
g_token = self.provider.html_fromstring(src).cssselect('#recaptcha-token')
|
||||
session = Session()
|
||||
h = session.post('{}/Read/AuthProcess'.format(self.provider.domain), data={
|
||||
'g-recaptcha-response': g_token[0].get('value'),
|
||||
'Id': 1,
|
||||
'Page': 1,
|
||||
})
|
||||
session.close()
|
||||
return h.cookies
|
||||
@@ -0,0 +1,9 @@
|
||||
from .gomanga_co import GoMangaCo
|
||||
|
||||
|
||||
class HelveticaScansCom(GoMangaCo):
|
||||
_name_re = '/r/[^/]+/([^/]+)/'
|
||||
_content_str = '{}/r/series/{}/'
|
||||
|
||||
|
||||
main = HelveticaScansCom
|
||||
36
manga-py-stable_1.x/manga_py/providers/hentai2read_com.py
Normal file
36
manga-py-stable_1.x/manga_py/providers/hentai2read_com.py
Normal file
@@ -0,0 +1,36 @@
|
||||
from manga_py.provider import Provider
|
||||
from .helpers.std import Std
|
||||
|
||||
|
||||
class Hentai2ReadCom(Provider, Std):
|
||||
images_cdn = 'https://static.hentaicdn.com/hentai'
|
||||
|
||||
def get_chapter_index(self) -> str:
|
||||
chapter = self.chapter
|
||||
idx = self.re.search('.+/([^/]+)/', chapter)
|
||||
return '-'.join(idx.group(1).split('.'))
|
||||
|
||||
def get_main_content(self):
|
||||
return self._get_content('{}/{}/')
|
||||
|
||||
def get_manga_name(self) -> str:
|
||||
return self._get_name(r'\.com/([^/]+)')
|
||||
|
||||
def get_chapters(self):
|
||||
return self._elements('li .chapter-row')
|
||||
|
||||
def get_files(self):
|
||||
content = self.http_get(self.chapter)
|
||||
selector = r'\'images\'\s*:\s*(\[.+\])'
|
||||
items = self.json.loads(self.re.search(selector, content).group(1))
|
||||
return ['{}{}'.format(self.images_cdn, i) for i in items]
|
||||
|
||||
def get_cover(self) -> str:
|
||||
return self._cover_from_content('.ribbon-primary .border-black-op')
|
||||
|
||||
def book_meta(self) -> dict:
|
||||
# todo meta
|
||||
pass
|
||||
|
||||
|
||||
main = Hentai2ReadCom
|
||||
21
manga-py-stable_1.x/manga_py/providers/hentai_cafe.py
Normal file
21
manga-py-stable_1.x/manga_py/providers/hentai_cafe.py
Normal file
@@ -0,0 +1,21 @@
|
||||
from .gomanga_co import GoMangaCo
|
||||
|
||||
from .helpers.std import Std
|
||||
|
||||
|
||||
class HentaiCafe(GoMangaCo, Std):
|
||||
_name_re = r'\.cafe(?:/manga/read)?/([^/]+)/'
|
||||
_content_str = '{}/{}/'
|
||||
_chapters_selector = '.content .last .x-btn' # TODO
|
||||
|
||||
def get_archive_name(self) -> str:
|
||||
return 'archive_{:0>2}'.format(self.chapter_id)
|
||||
|
||||
def get_chapter_index(self) -> str:
|
||||
return str(self.chapter_id)
|
||||
|
||||
def get_cover(self) -> str:
|
||||
return self._cover_from_content('.entry-content img')
|
||||
|
||||
|
||||
main = HentaiCafe
|
||||
48
manga-py-stable_1.x/manga_py/providers/hentai_chan_me.py
Normal file
48
manga-py-stable_1.x/manga_py/providers/hentai_chan_me.py
Normal file
@@ -0,0 +1,48 @@
|
||||
from shutil import copy
|
||||
|
||||
from manga_py.fs import is_file, storage, root_path, path_join
|
||||
from .mangachan_me import MangaChanMe
|
||||
|
||||
|
||||
class HentaiChanMe(MangaChanMe):
|
||||
|
||||
def get_chapter_index(self) -> str:
|
||||
return str(self.chapter_id)
|
||||
|
||||
def _login(self, **kwargs):
|
||||
url = self.domain + '/index.php'
|
||||
# login = kwargs.get('login', '')
|
||||
# password = kwargs.get('password', '')
|
||||
login = self.quest([], 'Please, input login')
|
||||
password = self.quest_password('Please, input password')
|
||||
method = kwargs.get('method', 'post')
|
||||
data = {'login_name': login, 'login_password': password, 'image': 'Вход', 'login': 'submit'}
|
||||
response = self.http().requests(method=method, data=data, url=url)
|
||||
cookies = {}
|
||||
for i in response.cookies.items():
|
||||
cookies[i[0]] = i[1]
|
||||
return cookies
|
||||
|
||||
def prepare_cookies(self):
|
||||
_storage = storage('.passwords.json')
|
||||
if not is_file(_storage):
|
||||
copy(path_join(root_path(), 'manga_py', '.passwords.json.dist'), _storage)
|
||||
file = open(_storage, 'r').read()
|
||||
data = self.json.loads(file).get('hentai_chan_me', {})
|
||||
cookies = self._login(**data)
|
||||
for i in cookies:
|
||||
self._storage['cookies'][i] = cookies[i]
|
||||
|
||||
def get_chapters(self):
|
||||
name = self.re.search(self._full_name_selector, self.get_url())
|
||||
url = '{}/related/{}'.format(self.domain, name.group(1))
|
||||
chapters = self.html_fromstring(url, '.related .related_info > h2 a')
|
||||
nu = self.http().normalize_uri
|
||||
return [nu(i.get('href').replace('/manga/', '/online/')) for i in chapters]
|
||||
|
||||
def book_meta(self) -> dict:
|
||||
# todo meta
|
||||
pass
|
||||
|
||||
|
||||
main = HentaiChanMe
|
||||
52
manga-py-stable_1.x/manga_py/providers/hentai_image_com.py
Normal file
52
manga-py-stable_1.x/manga_py/providers/hentai_image_com.py
Normal file
@@ -0,0 +1,52 @@
|
||||
from manga_py.provider import Provider
|
||||
from .helpers.std import Std
|
||||
|
||||
|
||||
class HentaiImageCom(Provider, Std):
|
||||
|
||||
def get_archive_name(self) -> str:
|
||||
return 'archive'
|
||||
|
||||
def get_chapter_index(self) -> str:
|
||||
return '0'
|
||||
|
||||
def get_main_content(self):
|
||||
return self._get_content('{}/image/{}')
|
||||
|
||||
def get_manga_name(self) -> str:
|
||||
return self._get_name('/image/([^/]+)')
|
||||
|
||||
def get_chapters(self):
|
||||
return [b'']
|
||||
|
||||
def _pages(self, parser):
|
||||
pages = parser.cssselect('#paginator')
|
||||
if pages:
|
||||
href = pages[0].cssselect('span > a')[-1].get('href')
|
||||
page = self.re.search(r'/page/(\d+)', href)
|
||||
return range(2, int(page.group(1)) + 1)
|
||||
return []
|
||||
|
||||
def get_files(self):
|
||||
parser = self.document_fromstring(self.content)
|
||||
pages = self._pages(parser)
|
||||
selector = '#display_image_detail div > a > img'
|
||||
images = self._images_helper(parser, selector)
|
||||
for i in pages:
|
||||
content = self._get_content('{}/image/{}/page/%d' % i)
|
||||
parser = self.document_fromstring(content)
|
||||
images += self._images_helper(parser, selector)
|
||||
return images
|
||||
|
||||
def get_cover(self) -> str:
|
||||
pass
|
||||
|
||||
def book_meta(self) -> dict:
|
||||
# todo meta
|
||||
pass
|
||||
|
||||
def chapter_for_json(self):
|
||||
return self.get_url()
|
||||
|
||||
|
||||
main = HentaiImageCom
|
||||
48
manga-py-stable_1.x/manga_py/providers/hentaifox_com.py
Normal file
48
manga-py-stable_1.x/manga_py/providers/hentaifox_com.py
Normal file
@@ -0,0 +1,48 @@
|
||||
from manga_py.provider import Provider
|
||||
from .helpers.std import Std
|
||||
|
||||
|
||||
class HentaiFoxCom(Provider, Std):
|
||||
_idx_re = r'/g(?:allery)?/(\d+)'
|
||||
_url_str = '{}/gallery/{}/'
|
||||
_name_selector = '.info h1'
|
||||
_archive_prefix = 'HentaiFox_'
|
||||
|
||||
def get_archive_name(self) -> str:
|
||||
return self.get_chapter_index()
|
||||
|
||||
def get_chapter_index(self) -> str:
|
||||
return self._archive_prefix + 'archive'
|
||||
|
||||
def get_main_content(self):
|
||||
idx = self._get_name(self._idx_re)
|
||||
url = self._url_str.format(self.domain, idx)
|
||||
return self.http_get(url)
|
||||
|
||||
def get_manga_name(self) -> str:
|
||||
return self.text_content(self.content, self._name_selector)
|
||||
|
||||
def get_chapters(self):
|
||||
return [b'']
|
||||
|
||||
def get_files(self):
|
||||
pages = self._elements('.gallery .preview_thumb a')
|
||||
items = []
|
||||
n = self.http().normalize_uri
|
||||
for i in pages:
|
||||
url = self.html_fromstring(n(i.get('href')), '#gimg', 0).get('src')
|
||||
items.append(n(url))
|
||||
return items
|
||||
|
||||
def get_cover(self) -> str:
|
||||
return self._cover_from_content('.cover img,#cover img')
|
||||
|
||||
def book_meta(self) -> dict:
|
||||
# todo meta
|
||||
pass
|
||||
|
||||
def chapter_for_json(self):
|
||||
return self.get_url()
|
||||
|
||||
|
||||
main = HentaiFoxCom
|
||||
17
manga-py-stable_1.x/manga_py/providers/hentaihand_com.py
Normal file
17
manga-py-stable_1.x/manga_py/providers/hentaihand_com.py
Normal file
@@ -0,0 +1,17 @@
|
||||
from .hentaifox_com import HentaiFoxCom
|
||||
|
||||
|
||||
class HentaiHandCom(HentaiFoxCom):
|
||||
_idx_re = r'/comic/(\d+)'
|
||||
_url_str = '{}/comic/{}/'
|
||||
_name_selector = '#info h1'
|
||||
_archive_prefix = 'HentaiHand_'
|
||||
|
||||
def get_files(self):
|
||||
parser = self.document_fromstring(self.content)
|
||||
images = self._images_helper(parser, 'a.gallerythumb > img')
|
||||
re = self.re.compile(r'(.+/images/)(\d+)')
|
||||
return ['{}full/{}.jpg'.format(*re.search(i).groups()) for i in images]
|
||||
|
||||
|
||||
main = HentaiHandCom
|
||||
43
manga-py-stable_1.x/manga_py/providers/hentaihere_com.py
Normal file
43
manga-py-stable_1.x/manga_py/providers/hentaihere_com.py
Normal file
@@ -0,0 +1,43 @@
|
||||
from manga_py.provider import Provider
|
||||
from .helpers.std import Std
|
||||
|
||||
|
||||
class HentaiHereCom(Provider, Std):
|
||||
_cdn = 'https://hentaicdn.com/hentai'
|
||||
|
||||
def get_chapter_index(self) -> str:
|
||||
chapter = self.chapter
|
||||
idx = self.re.search('/m/[^/]+/([^/]+(?:/[^/]+))', chapter)
|
||||
return idx.group(1).replace('/', '-')
|
||||
|
||||
def get_main_content(self):
|
||||
url = self.re.search('(/m/[^/]+)', self.get_url())
|
||||
url = '{}{}'.format(self.domain, url.group(1))
|
||||
return self.http_get(url)
|
||||
|
||||
def get_manga_name(self) -> str:
|
||||
selector = 'span.hide[itemscope] span[itemprop="name"]'
|
||||
name = self.document_fromstring(self.content, selector)
|
||||
if not name:
|
||||
selector = '#detail span[itemprop="title"]'
|
||||
name = self.document_fromstring(self.content, selector)
|
||||
return name[0].text_content().strip()
|
||||
|
||||
def get_chapters(self):
|
||||
return self._elements('ul.arf-list > li > a')
|
||||
|
||||
def get_files(self):
|
||||
chapter = self.chapter
|
||||
content = self.http_get(chapter)
|
||||
items = self.re.search(r'_imageList\s*=\s*(\[".+"\])', content).group(1)
|
||||
return [self._cdn + i for i in self.json.loads(items)]
|
||||
|
||||
def get_cover(self) -> str:
|
||||
return self._cover_from_content('#cover img')
|
||||
|
||||
def book_meta(self) -> dict:
|
||||
# todo meta
|
||||
pass
|
||||
|
||||
|
||||
main = HentaiHereCom
|
||||
35
manga-py-stable_1.x/manga_py/providers/hentaiporns_net.py
Normal file
35
manga-py-stable_1.x/manga_py/providers/hentaiporns_net.py
Normal file
@@ -0,0 +1,35 @@
|
||||
from manga_py.provider import Provider
|
||||
from .helpers.std import Std
|
||||
from sys import stderr
|
||||
|
||||
|
||||
class HentaiPornsNet(Provider, Std):
|
||||
|
||||
def get_archive_name(self) -> str:
|
||||
return 'archive'
|
||||
|
||||
def get_chapter_index(self) -> str:
|
||||
return '0'
|
||||
|
||||
def get_main_content(self):
|
||||
url = self.get_url()
|
||||
if ~url.find('/tag/'):
|
||||
self.log('Please, use target url', file=stderr)
|
||||
exit(1)
|
||||
return self.http_get(self.get_url())
|
||||
|
||||
def get_manga_name(self) -> str:
|
||||
return self._get_name(r'//[^/]+/([^/]+)')
|
||||
|
||||
def get_chapters(self):
|
||||
return [b'']
|
||||
|
||||
def get_files(self):
|
||||
parser = self.document_fromstring(self.content)
|
||||
return self._images_helper(parser, '.gallery-item a', 'href')
|
||||
|
||||
def get_cover(self) -> str:
|
||||
return self._cover_from_content('.post-thumbnail img')
|
||||
|
||||
|
||||
main = HentaiPornsNet
|
||||
11
manga-py-stable_1.x/manga_py/providers/hentairead_com.py
Normal file
11
manga-py-stable_1.x/manga_py/providers/hentairead_com.py
Normal file
@@ -0,0 +1,11 @@
|
||||
from .helpers.std import Std
|
||||
from .readhentaimanga_com import ReadHentaiMangaCom
|
||||
|
||||
|
||||
class HentaiReadCom(ReadHentaiMangaCom, Std):
|
||||
|
||||
def get_chapters(self):
|
||||
return self._elements('.read-now a.lst')
|
||||
|
||||
|
||||
main = HentaiReadCom
|
||||
60
manga-py-stable_1.x/manga_py/providers/hgamecg_com.py
Normal file
60
manga-py-stable_1.x/manga_py/providers/hgamecg_com.py
Normal file
@@ -0,0 +1,60 @@
|
||||
from manga_py.provider import Provider
|
||||
from .helpers.std import Std
|
||||
|
||||
|
||||
class HGameCGCom(Provider, Std):
|
||||
__img_selector = '#thumbnails > div .col-thumbnail'
|
||||
__img_count = 0
|
||||
|
||||
def get_archive_name(self) -> str:
|
||||
return 'page_{:0>3}'.format(self.chapter)
|
||||
|
||||
def get_chapter_index(self) -> str:
|
||||
return '0'
|
||||
|
||||
def get_main_content(self):
|
||||
return self._get_content('{}/index/category/{}')
|
||||
|
||||
def get_manga_name(self) -> str:
|
||||
return self._get_name('/index/category/([^/]+)')
|
||||
|
||||
def get_chapters(self):
|
||||
images = self.document_fromstring(self.content, self.__img_selector)
|
||||
self.__img_count = len(images)
|
||||
pages = self.document_fromstring(self.content, '.pagination li > a')
|
||||
pages_count = 0
|
||||
if pages:
|
||||
pages_count = self.re.search('/start-(\d+)', pages[-1].get('href')).group(1)
|
||||
pages_count = int(int(pages_count) / self.__img_count)
|
||||
return range(1, pages_count + 2)[::-1]
|
||||
|
||||
def __tmb_to_img(self, tmbs):
|
||||
url = '{}/action.php?id={}&part=e'
|
||||
imgs = []
|
||||
re = self.re.compile(r'/picture/(\d+)')
|
||||
for i in tmbs:
|
||||
idx = re.search(i.get('href')).group(1)
|
||||
imgs.append(url.format(self.domain, idx))
|
||||
return imgs
|
||||
|
||||
def get_files(self):
|
||||
pages_url = self.get_url() + '/start-{}'
|
||||
if self.chapter > 1:
|
||||
offset = self.__img_count * (self.chapter - 1)
|
||||
images = self.html_fromstring(pages_url.format(offset), self.__img_selector)
|
||||
else:
|
||||
images = self.document_fromstring(self.content, self.__img_selector)
|
||||
return self.__tmb_to_img(images)
|
||||
|
||||
def get_cover(self) -> str:
|
||||
# return self._cover_from_content('.cover img')
|
||||
pass
|
||||
|
||||
def book_meta(self) -> dict:
|
||||
pass
|
||||
|
||||
def chapter_for_json(self):
|
||||
return self.get_url()
|
||||
|
||||
|
||||
main = HGameCGCom
|
||||
63
manga-py-stable_1.x/manga_py/providers/hitmanga_eu.py
Normal file
63
manga-py-stable_1.x/manga_py/providers/hitmanga_eu.py
Normal file
@@ -0,0 +1,63 @@
|
||||
from urllib.parse import unquote_plus
|
||||
|
||||
from manga_py.provider import Provider
|
||||
from .helpers.std import Std
|
||||
|
||||
|
||||
class HitMangaEu(Provider, Std):
|
||||
_n = None
|
||||
postfix = None
|
||||
main_domain = 'http://www.mymanga.io'
|
||||
api_url = 'http://www.hitmanga.eu/listener/'
|
||||
|
||||
def get_chapter_index(self) -> str:
|
||||
chapter = self.chapter
|
||||
idx = self.re.search('[^/]+/[^/]+/[^/]+?-([^/]+)', chapter)
|
||||
return idx.group(1)
|
||||
|
||||
def get_main_content(self):
|
||||
return self._content(self._get_content('{}/mangas/{}/'))
|
||||
|
||||
def get_manga_name(self) -> str:
|
||||
url = self.get_url()
|
||||
re = '{}/([^/]+)'
|
||||
if ~url.find('/mangas/'):
|
||||
re = '{}/mangas/([^/]+)'
|
||||
re = re.format(self.postfix)
|
||||
return self.re.search(re, url).group(1)
|
||||
|
||||
def get_chapters(self):
|
||||
return self._elements('.listchapseries li a.follow:not(.ddl)')
|
||||
|
||||
def _content(self, url):
|
||||
return self.re.sub(r'<!--.+?--!>', '', self.http_get(url))
|
||||
|
||||
def get_files(self):
|
||||
chapter = self.chapter
|
||||
img = self.document_fromstring(self._content(chapter), '#chpimg', 0).get('src')
|
||||
idx = self.get_chapter_index()
|
||||
items = self.http_post(url=self.api_url, data={
|
||||
'number': unquote_plus(idx),
|
||||
'permalink': self.manga_name,
|
||||
'type': 'chap-pages',
|
||||
})
|
||||
if items == '0':
|
||||
return []
|
||||
items = items.split('|')
|
||||
return [self._n(i, img) for i in items]
|
||||
|
||||
def get_cover(self) -> str:
|
||||
return self._cover_from_content('#picture img')
|
||||
|
||||
def prepare_cookies(self):
|
||||
domain = self.domain.split('.')
|
||||
self.postfix = r'\.' + domain[-1]
|
||||
n = self.http().normalize_uri
|
||||
self._n = lambda u, r: n(u, r)
|
||||
|
||||
def book_meta(self) -> dict:
|
||||
# todo meta
|
||||
pass
|
||||
|
||||
|
||||
main = HitMangaEu
|
||||
25
manga-py-stable_1.x/manga_py/providers/hitomi_la.py
Normal file
25
manga-py-stable_1.x/manga_py/providers/hitomi_la.py
Normal file
@@ -0,0 +1,25 @@
|
||||
from urllib.parse import unquote_plus
|
||||
|
||||
from .hentaifox_com import HentaiFoxCom
|
||||
|
||||
|
||||
class HitomiLa(HentaiFoxCom):
|
||||
_idx_re = r'/(?:galleries|reader)/(\d+)'
|
||||
_url_str = '{}/galleries/{}.html'
|
||||
_name_selector = '.dj-gallery h1 a'
|
||||
_cdn = 'http://0a.hitomi.la/galleries/'
|
||||
|
||||
def get_manga_name(self):
|
||||
name = super().get_manga_name()
|
||||
return unquote_plus(name.split('|')[0].strip())
|
||||
|
||||
def get_files(self):
|
||||
idx = self._get_name(self._idx_re)
|
||||
url = 'http://ltn.hitomi.la/galleries/{}.js'.format(idx)
|
||||
images = self.re.search(r'(\[.+\])', self.http_get(url))
|
||||
images = self.json.loads(images.group(1))
|
||||
p = '{}{}/'.format(self._cdn, idx)
|
||||
return [p + i.get('name') for i in images]
|
||||
|
||||
|
||||
main = HitomiLa
|
||||
@@ -0,0 +1,40 @@
|
||||
from manga_py.provider import Provider
|
||||
from .helpers.std import Std
|
||||
|
||||
|
||||
class HocVienTruyenTranhCom(Provider, Std):
|
||||
|
||||
def get_chapter_index(self) -> str:
|
||||
idx = self.re.search(r'/chapter/(\d+)', self.chapter)
|
||||
return '{}-{}'.format(self.chapter_id, idx.group(1))
|
||||
|
||||
def _test_main_url(self, url):
|
||||
if self.re.search('/chapter/', url):
|
||||
url = self.html_fromstring(url, '#subNavi a', 0).get('href')
|
||||
return url
|
||||
|
||||
def get_main_content(self):
|
||||
url = self._test_main_url(self.get_url())
|
||||
return self.http_get(self.http().normalize_uri(url))
|
||||
|
||||
def get_manga_name(self) -> str:
|
||||
url = self._test_main_url(self.get_url())
|
||||
return self.re.search('/manga/[^/]+/([^/]+)', url).group(1)
|
||||
|
||||
def get_chapters(self):
|
||||
return self._elements('.table-scroll table.table td > a')
|
||||
|
||||
def get_files(self):
|
||||
selector = '.manga-container img.page'
|
||||
items = self.html_fromstring(self.chapter, selector)
|
||||
return [i.get('src') for i in items]
|
||||
|
||||
def get_cover(self):
|
||||
return self._cover_from_content('.__info-container .__image img')
|
||||
|
||||
def book_meta(self) -> dict:
|
||||
# todo meta
|
||||
pass
|
||||
|
||||
|
||||
main = HocVienTruyenTranhCom
|
||||
54
manga-py-stable_1.x/manga_py/providers/hoducomics_com.py
Normal file
54
manga-py-stable_1.x/manga_py/providers/hoducomics_com.py
Normal file
@@ -0,0 +1,54 @@
|
||||
from manga_py.crypt.base_lib import BaseLib
|
||||
from manga_py.provider import Provider
|
||||
from .helpers.std import Std
|
||||
|
||||
|
||||
class HoduComicsCom(Provider, Std):
|
||||
|
||||
def get_archive_name(self) -> str:
|
||||
return self.normal_arc_name({'vol': [
|
||||
self.chapter_id,
|
||||
self.get_chapter_index()
|
||||
]})
|
||||
|
||||
def get_chapter_index(self) -> str:
|
||||
return self.re.search(r'view/(\d+)', self.chapter).group(1)
|
||||
|
||||
def get_main_content(self):
|
||||
content = self._storage.get('main_content', None)
|
||||
if content is None:
|
||||
self._storage['main_content'] = self.http_get(self.get_url())
|
||||
return self._storage['main_content']
|
||||
|
||||
def get_manga_name(self) -> str:
|
||||
self.http().referer = self.get_url()
|
||||
element = self.document_fromstring(self.content, '[property="og:title"]', 0)
|
||||
return element.get('content')
|
||||
|
||||
def get_chapters(self):
|
||||
items = self._elements('.episode_list .episode_tr.not_need_pay')
|
||||
re = self.re.compile(r'(/webtoon/.+?/\d+)')
|
||||
n = self.http().normalize_uri
|
||||
if len(items) == 0:
|
||||
return []
|
||||
return [n(re.search(i.get('onclick')).group(1)) for i in items]
|
||||
|
||||
def get_files(self):
|
||||
content = self.http_get(self.chapter)
|
||||
images = self.re.search(r'toon_img\s*=\s*[\'"](.+?)[\'"]', content)
|
||||
if not images:
|
||||
return []
|
||||
parser = self.document_fromstring(BaseLib.base64decode(images.group(1)).decode())
|
||||
return self._images_helper(parser, 'img')
|
||||
|
||||
def get_cover(self) -> str:
|
||||
return self._cover_from_content('.episode_bnr > img')
|
||||
|
||||
def book_meta(self) -> dict:
|
||||
pass
|
||||
|
||||
def prepare_cookies(self):
|
||||
self.cf_protect(self.get_url())
|
||||
|
||||
|
||||
main = HoduComicsCom
|
||||
@@ -0,0 +1,9 @@
|
||||
from .gomanga_co import GoMangaCo
|
||||
|
||||
|
||||
class HotChocolateScansCom(GoMangaCo):
|
||||
_name_re = '/fs/[^/]+/([^/]+)/'
|
||||
_content_str = '{}/fs/series/{}/'
|
||||
|
||||
|
||||
main = HotChocolateScansCom
|
||||
71
manga-py-stable_1.x/manga_py/providers/inmanga_com.py
Normal file
71
manga-py-stable_1.x/manga_py/providers/inmanga_com.py
Normal file
@@ -0,0 +1,71 @@
|
||||
from manga_py.provider import Provider
|
||||
from .helpers.std import Std
|
||||
|
||||
|
||||
class InMangaCom(Provider, Std):
|
||||
__local_storage = None
|
||||
|
||||
def get_chapter_index(self) -> str:
|
||||
return str(self.chapter['Number'])
|
||||
|
||||
def get_main_content(self):
|
||||
if not self.__local_storage.get('uri_hex', False):
|
||||
self.get_manga_name()
|
||||
url = '{}/chapter/getall?mangaIdentification={}'.format(
|
||||
self.domain,
|
||||
self.__local_storage['uri_hex']
|
||||
)
|
||||
data = self.json.loads(self.http_get(url))['data']
|
||||
return self.json.loads(data)
|
||||
|
||||
def get_manga_name(self) -> str:
|
||||
url = self.get_url()
|
||||
test = self.re.search(r'/ver/manga/[^/]+/\d+/[^/]+', url)
|
||||
if test:
|
||||
content = self._elements('.chapterControlsContainer label.blue a.blue')[0]
|
||||
url = self.domain + content.get('href')
|
||||
manga_name, uri_hex = self.re.search('/ver/manga/([^/]+)/([^/]+)', url).groups()
|
||||
self.__local_storage['manga_name'] = manga_name
|
||||
self.__local_storage['uri_hex'] = uri_hex
|
||||
return self.__local_storage['manga_name']
|
||||
|
||||
@staticmethod
|
||||
def __sort_chapters(items, reverse=False):
|
||||
return sorted(items, key=lambda i: float(i['FriendlyChapterNumber']), reverse=reverse)
|
||||
|
||||
def get_chapters(self):
|
||||
items = self.content['result']
|
||||
return self.__sort_chapters(items, True)
|
||||
|
||||
def prepare_cookies(self):
|
||||
self.__local_storage = {}
|
||||
|
||||
def _make_url(self, chapter):
|
||||
return '{}/ver/manga/{}/{}/{}'.format(
|
||||
self.domain,
|
||||
self.manga_name,
|
||||
chapter['FriendlyChapterNumber'],
|
||||
chapter['Identification']
|
||||
)
|
||||
|
||||
def get_files(self):
|
||||
files_url = '{}/page/getPageImage/?identification={}'
|
||||
url = self._make_url(self.chapter)
|
||||
images = self.html_fromstring(url, '.PagesContainer img.ImageContainer')
|
||||
|
||||
domain = self.domain
|
||||
return [files_url.format(domain, i.get('id')) for i in images]
|
||||
|
||||
def get_cover(self):
|
||||
idx = self.__local_storage['uri_hex']
|
||||
return '{}/manga/getMangaImage?identification={}'.format(self.domain, idx)
|
||||
|
||||
def book_meta(self) -> dict:
|
||||
# todo meta
|
||||
pass
|
||||
|
||||
def chapter_for_json(self):
|
||||
return self._make_url(self.chapter)
|
||||
|
||||
|
||||
main = InMangaCom
|
||||
12
manga-py-stable_1.x/manga_py/providers/isekaiscan_com.py
Normal file
12
manga-py-stable_1.x/manga_py/providers/isekaiscan_com.py
Normal file
@@ -0,0 +1,12 @@
|
||||
from .rawdevart_com import RawDevArtCom
|
||||
|
||||
|
||||
class ISekaiScanCom(RawDevArtCom):
|
||||
_chapter_selector = r'/chapter-(\d+(?:-[\w\-]+)?)'
|
||||
|
||||
def get_files(self):
|
||||
parser = self.html_fromstring(self.chapter)
|
||||
return self._images_helper(parser, '.page-break img.wp-manga-chapter-img', 'data-src')
|
||||
|
||||
|
||||
main = ISekaiScanCom
|
||||
32
manga-py-stable_1.x/manga_py/providers/japscan_com.py
Normal file
32
manga-py-stable_1.x/manga_py/providers/japscan_com.py
Normal file
@@ -0,0 +1,32 @@
|
||||
from .gomanga_co import GoMangaCo
|
||||
|
||||
|
||||
class JapScanCom(GoMangaCo):
|
||||
_name_re = r'\.(?:com|cc|to)/[^/]+/([^/]+)/'
|
||||
_content_str = '{}/manga/{}/'
|
||||
_chapters_selector = '#chapters_list .chapters_list a'
|
||||
|
||||
def get_archive_name(self) -> str:
|
||||
idx = self.chapter_id, self.get_chapter_index()
|
||||
return self.normal_arc_name({'vol': idx})
|
||||
|
||||
def get_chapter_index(self) -> str:
|
||||
selector = r'\.(?:com|cc|to)/[^/]+/[^/]+/(\d+)/'
|
||||
url = self.chapter
|
||||
return self.re.search(selector, url).group(1)
|
||||
|
||||
def get_files(self):
|
||||
n = self.http().normalize_uri
|
||||
parser = self.html_fromstring(self.chapter)
|
||||
|
||||
base_url = self.base_url(parser)
|
||||
images = self._images_helper(parser, '#pages option', 'data-img')
|
||||
|
||||
return [n(base_url+i) for i in images]
|
||||
|
||||
def base_url(self, parser):
|
||||
base_url = parser.cssselect('#image')[0].get('data-src')
|
||||
return self.re.search(r'(.+/)\w+\.\w+', base_url).group(1)
|
||||
|
||||
|
||||
main = JapScanCom
|
||||
50
manga-py-stable_1.x/manga_py/providers/jurnalu_ru.py
Normal file
50
manga-py-stable_1.x/manga_py/providers/jurnalu_ru.py
Normal file
@@ -0,0 +1,50 @@
|
||||
from manga_py.provider import Provider
|
||||
from .helpers.std import Std
|
||||
|
||||
|
||||
class JurnaluRu(Provider, Std):
|
||||
|
||||
def get_chapter_index(self) -> str:
|
||||
return str(self.chapter_id)
|
||||
|
||||
def get_main_content(self):
|
||||
name = self._get_name(r'(online-reading/[^/]+/[^/]+)')
|
||||
url = self.html_fromstring(
|
||||
'{}/{}'.format(self.domain, name),
|
||||
'.MagList .MagListLine > a',
|
||||
0
|
||||
).get('href')
|
||||
return self.http_get(self.domain + url)
|
||||
|
||||
def get_manga_name(self) -> str:
|
||||
return self._get_name(r'/online-reading/[^/]+/([^/]+)')
|
||||
|
||||
def get_chapters(self):
|
||||
name = self.re.search(r'(online-reading/[^/]+/[^/]+)', self.get_url())
|
||||
if not name:
|
||||
return []
|
||||
items = self.document_fromstring(self.content, 'select.magSelection option')
|
||||
url = '{}/{}/'.format(self.domain, name.group(1))
|
||||
return [url + i.get('value') for i in items]
|
||||
|
||||
@staticmethod
|
||||
def __get_file(parser):
|
||||
image = parser.cssselect('a[rel="shadowbox"]')
|
||||
return image[0].get('href')
|
||||
|
||||
def get_files(self):
|
||||
chapter = self.chapter
|
||||
page = self.html_fromstring(chapter, '.ForRead', 0)
|
||||
pages = page.cssselect('.navigation')[0].cssselect('select.M option + option')
|
||||
images = [self.__get_file(page)]
|
||||
for i in pages:
|
||||
uri = '{}/{}'.format(chapter, i.get('value'))
|
||||
parser = self.html_fromstring(uri, '.ForRead', 0)
|
||||
images.append(self.__get_file(parser))
|
||||
return images
|
||||
|
||||
def get_cover(self):
|
||||
return self._cover_from_content('.ops > div > img')
|
||||
|
||||
|
||||
main = JurnaluRu
|
||||
87
manga-py-stable_1.x/manga_py/providers/kissmanga_com.py
Normal file
87
manga-py-stable_1.x/manga_py/providers/kissmanga_com.py
Normal file
@@ -0,0 +1,87 @@
|
||||
from sys import stderr
|
||||
|
||||
from manga_py.crypt import KissMangaComCrypt
|
||||
from manga_py.provider import Provider
|
||||
from .helpers.std import Std
|
||||
|
||||
|
||||
class KissMangaCom(Provider, Std):
|
||||
__local_data = {
|
||||
'iv': b'a5e8e2e9c2721be0a84ad660c472c1f3',
|
||||
'key': b'mshsdf832nsdbash20asdm',
|
||||
}
|
||||
|
||||
def get_archive_name(self) -> str:
|
||||
return '{:0>3}-{}'.format(
|
||||
self.chapter_id + 1,
|
||||
self.get_chapter_index()
|
||||
)
|
||||
|
||||
def get_chapter_index(self) -> str:
|
||||
name = self.re.search(r'/Manga/[^/]+/(.+)\?id=(\d+)', self.chapter)
|
||||
return '-'.join(name.groups())
|
||||
|
||||
def get_main_content(self):
|
||||
return self._get_content('{}/Manga/{}')
|
||||
|
||||
def get_manga_name(self) -> str:
|
||||
return self._get_name('/Manga/([^/]+)')
|
||||
|
||||
def get_chapters(self):
|
||||
chapters = self._elements('.listing td a')
|
||||
if not len(chapters):
|
||||
self.log('Chapters not found', file=stderr)
|
||||
return chapters
|
||||
|
||||
def prepare_cookies(self):
|
||||
self._params['rename_pages'] = True
|
||||
self.cf_protect(self.get_url())
|
||||
self._storage['cookies']['rco_quality'] = 'hq'
|
||||
if not self._params['cf-protect']:
|
||||
self.log('CloudFlare protect fail!', file=stderr)
|
||||
|
||||
def __decrypt_images(self, crypt, key, hexes):
|
||||
images = []
|
||||
for i in hexes:
|
||||
try:
|
||||
img = crypt.decrypt(self.__local_data['iv'], key, i)
|
||||
images.append(img.decode('utf-8', errors='ignore').replace('\x10', '').replace('\x0f', ''))
|
||||
|
||||
except Exception as e:
|
||||
pass
|
||||
|
||||
return images
|
||||
|
||||
def __check_key(self, crypt, content):
|
||||
# if need change key
|
||||
need = self.re.search(r'\["([^"]+)"\].\+chko.?=.?chko', content)
|
||||
key = self.__local_data['key']
|
||||
if need:
|
||||
# need last group
|
||||
key += crypt.decode_escape(need.group(1))
|
||||
else:
|
||||
# if need change key
|
||||
need = self.re.findall(r'\["([^"]+)"\].*?chko.*?=.*?chko', content)
|
||||
if need:
|
||||
key = crypt.decode_escape(need[-1])
|
||||
return key
|
||||
|
||||
def get_files(self):
|
||||
crypt = KissMangaComCrypt()
|
||||
content = self.http_get(self.chapter)
|
||||
key = self.__check_key(crypt, content)
|
||||
hexes = self.re.findall(r'lstImages.push\(wrapKA\(["\']([^"\']+?)["\']\)', content)
|
||||
if not hexes:
|
||||
self.log('Images not found!', file=stderr)
|
||||
return []
|
||||
return self.__decrypt_images(crypt, key, hexes)
|
||||
|
||||
def get_cover(self):
|
||||
return self._cover_from_content('.rightBox .barContent img')
|
||||
|
||||
def book_meta(self) -> dict:
|
||||
# todo meta
|
||||
pass
|
||||
|
||||
|
||||
main = KissMangaCom
|
||||
38
manga-py-stable_1.x/manga_py/providers/komikcast_com.py
Normal file
38
manga-py-stable_1.x/manga_py/providers/komikcast_com.py
Normal file
@@ -0,0 +1,38 @@
|
||||
from manga_py.provider import Provider
|
||||
from .helpers.std import Std
|
||||
|
||||
|
||||
class KomikCastCom(Provider, Std):
|
||||
_chapter_re = r'\.com/[^/]+-(\d+(?:-\d+)?)'
|
||||
|
||||
def get_chapter_index(self) -> str:
|
||||
re = self.re.compile('-chapter-(\d+(?:-\d+)?)')
|
||||
return re.search(self.chapter).group(1)
|
||||
|
||||
def get_main_content(self):
|
||||
return self._get_content('{}/{}')
|
||||
|
||||
def get_manga_name(self) -> str:
|
||||
url = self.get_url()
|
||||
if ~url.find('/chapter/'):
|
||||
url = self.html_fromstring(url, '.allc a', 0).get('href')
|
||||
self._params['url'] = self.http().normalize_uri(url)
|
||||
return self.get_manga_name()
|
||||
return self._get_name(r'\.com/([^/]+)')
|
||||
|
||||
def get_chapters(self) -> list:
|
||||
return self._elements('.mangainfo .leftoff a')
|
||||
|
||||
def get_files(self) -> list:
|
||||
parser = self.html_fromstring(self.chapter)
|
||||
return self._images_helper(parser, '#readerarea img')
|
||||
|
||||
def get_cover(self):
|
||||
return self._cover_from_content('.topinfo img')
|
||||
|
||||
def book_meta(self) -> dict:
|
||||
# todo meta
|
||||
pass
|
||||
|
||||
|
||||
main = KomikCastCom
|
||||
26
manga-py-stable_1.x/manga_py/providers/komikid_com.py
Normal file
26
manga-py-stable_1.x/manga_py/providers/komikid_com.py
Normal file
@@ -0,0 +1,26 @@
|
||||
from .gomanga_co import GoMangaCo
|
||||
from .helpers.std import Std
|
||||
|
||||
|
||||
class KomikIdCom(GoMangaCo, Std):
|
||||
_name_re = '/manga/([^/]+)'
|
||||
_content_str = '{}/manga/{}'
|
||||
_chapters_selector = '.chapter-title-rtl a'
|
||||
|
||||
def get_chapter_index(self) -> str:
|
||||
re = r'/manga/[^/]+/(\d+)(?:[^\d](\d+))?'
|
||||
idx = self.re.search(re, self.chapter)
|
||||
return self._join_groups(idx.groups())
|
||||
|
||||
def get_files(self):
|
||||
parser = self.html_fromstring(self.chapter)
|
||||
return self._images_helper(parser, '#all img[data-src]', 'data-src')
|
||||
|
||||
def get_cover(self) -> str:
|
||||
return self._cover_from_content('.boxed img')
|
||||
|
||||
def prepare_cookies(self):
|
||||
pass
|
||||
|
||||
|
||||
main = KomikIdCom
|
||||
66
manga-py-stable_1.x/manga_py/providers/kumanga_com.py
Normal file
66
manga-py-stable_1.x/manga_py/providers/kumanga_com.py
Normal file
@@ -0,0 +1,66 @@
|
||||
from math import ceil
|
||||
|
||||
from manga_py.provider import Provider
|
||||
from .helpers.std import Std
|
||||
|
||||
|
||||
class KuMangaCom(Provider, Std):
|
||||
def get_chapter_index(self) -> str:
|
||||
return str(self.chapter_id)
|
||||
|
||||
def get_main_content(self):
|
||||
url = self.re.search(r'(.+\.com/manga/\d+)', self.get_url())
|
||||
return self.http_get('%s/' % url.group(1))
|
||||
|
||||
def get_manga_name(self) -> str:
|
||||
selector = r'pagination\(\d+,\'(.+)\',\'pagination\''
|
||||
parser = self.re.search(selector, self.content)
|
||||
return parser.group(1).strip()
|
||||
|
||||
def _chapters(self, parser):
|
||||
items = parser.cssselect('.table h4.title > a')
|
||||
chapters = []
|
||||
for i in items:
|
||||
c = '{}/{}'.format(self.domain, i.get('href'))
|
||||
chapters.append(c.replace('/c/', '/leer/'))
|
||||
return chapters
|
||||
|
||||
def _url_helper(self):
|
||||
idx = self.re.search(r'\.com/manga/(\d+)', self.get_url())
|
||||
return '{}/manga/{}/p/%d/{}'.format(
|
||||
self.domain,
|
||||
idx.group(1),
|
||||
self.manga_name
|
||||
)
|
||||
|
||||
def get_chapters(self):
|
||||
selector = r'\'pagination\',\d+,(\d+),(\d+)'
|
||||
pages = self.re.search(selector, self.content).groups()
|
||||
pages = ceil(float(pages[0]) / float(pages[1]))
|
||||
chapters = []
|
||||
url_path = self._url_helper()
|
||||
for i in range(int(pages) - 1):
|
||||
parser = self.html_fromstring(url_path % (i + 1))
|
||||
chapters += self._chapters(parser)
|
||||
return chapters
|
||||
|
||||
def _get_real_url(self, url):
|
||||
location = self.http().requests(url=url, method='head')
|
||||
return location.headers.get('Location', url)
|
||||
|
||||
def get_files(self):
|
||||
r = self.http().get_redirect_url
|
||||
selector = r'(\[\{"npage".+\}\])'
|
||||
content = self.http_get(self.chapter)
|
||||
items = self.json.loads(self.re.search(selector, content))
|
||||
return [r(i.get('imgURL')) for i in items.group(1)]
|
||||
|
||||
def get_cover(self) -> str:
|
||||
return self._cover_from_content('.container img.img-responsive')
|
||||
|
||||
def book_meta(self) -> dict:
|
||||
# todo meta
|
||||
pass
|
||||
|
||||
|
||||
main = KuMangaCom
|
||||
@@ -0,0 +1,9 @@
|
||||
from .gomanga_co import GoMangaCo
|
||||
|
||||
|
||||
class LectorKirishimaFanSubCom(GoMangaCo):
|
||||
_name_re = '/(?:reader/)?(?:series|read)/([^/]+)/'
|
||||
_content_str = '{}/lector/series/{}/'
|
||||
|
||||
|
||||
main = LectorKirishimaFanSubCom
|
||||
@@ -0,0 +1,9 @@
|
||||
from .gomanga_co import GoMangaCo
|
||||
|
||||
|
||||
class LectorYTNoFanCom(GoMangaCo):
|
||||
_name_re = '/(?:series|read)/([^/]+)/'
|
||||
_content_str = '{}/series/{}/'
|
||||
|
||||
|
||||
main = LectorYTNoFanCom
|
||||
81
manga-py-stable_1.x/manga_py/providers/leitor_net.py
Normal file
81
manga-py-stable_1.x/manga_py/providers/leitor_net.py
Normal file
@@ -0,0 +1,81 @@
|
||||
from manga_py.provider import Provider
|
||||
from .helpers.std import Std
|
||||
|
||||
|
||||
class LeitorNet(Provider, Std):
|
||||
__idx = None
|
||||
|
||||
def get_archive_name(self) -> str:
|
||||
ch = self.chapter
|
||||
return self.normal_arc_name({
|
||||
'vol': ch['number'].split('.'),
|
||||
'ch': [ch['id_chapter'], ch['id_release']],
|
||||
})
|
||||
|
||||
def get_chapter_index(self) -> str:
|
||||
return '-'.join(self.chapter['number'].split('.'))
|
||||
|
||||
def get_main_content(self):
|
||||
idx = self.html_fromstring(self.get_url(), '[data-id-serie]', 0)
|
||||
self.__idx = idx.get('data-id-serie')
|
||||
return b'0'
|
||||
|
||||
def get_manga_name(self) -> str:
|
||||
return self._get_name(r'/manga/([^/]+)')
|
||||
|
||||
@staticmethod
|
||||
def __morph_chapters(items):
|
||||
result = []
|
||||
for item in items: # items loop
|
||||
for r in item['releases']: # items.releases loop
|
||||
release = item['releases'][r]
|
||||
result.append({
|
||||
'number': item['number'],
|
||||
'id_chapter': item['id_chapter'],
|
||||
'id_serie': item['id_serie'],
|
||||
'id_release': release['id_release'],
|
||||
'link': release['link'],
|
||||
})
|
||||
return result
|
||||
|
||||
def get_chapters(self):
|
||||
url = '{}/series/chapters_list.json?page={}&id_serie={}'
|
||||
items = []
|
||||
for i in range(1, 100):
|
||||
content = self.json.loads(self.http_get(url.format(
|
||||
self.domain, i, self.__idx
|
||||
), headers={'x-requested-with': 'XMLHttpRequest'}))
|
||||
chapters = content.get('chapters', False)
|
||||
if not chapters:
|
||||
break
|
||||
items += chapters
|
||||
return self.__morph_chapters(items)
|
||||
|
||||
def get_files(self):
|
||||
content = self.http_get(self.domain + self.chapter['link'])
|
||||
token = self.re.search(r'token=([^&]+)', content).group(1)
|
||||
url = '{}/leitor/pages.json?key={}&id_release={}'
|
||||
images = self.json.loads(self.http_get(url.format(
|
||||
self.domain,
|
||||
token, self.chapter['id_release']
|
||||
), headers={'x-requested-with': 'XMLHttpRequest'}))
|
||||
return images.get('images', {})
|
||||
|
||||
def get_cover(self) -> str:
|
||||
url = '{}/manga/{}/{}'.format(
|
||||
self.domain,
|
||||
self.manga_name,
|
||||
self.__idx
|
||||
)
|
||||
image = self.html_fromstring(url, '.cover-image')
|
||||
if image and len(image):
|
||||
return self.parse_background(image[0])
|
||||
|
||||
def book_meta(self) -> dict:
|
||||
pass
|
||||
|
||||
def chapter_for_json(self):
|
||||
return self.domain + self.chapter['link']
|
||||
|
||||
|
||||
main = LeitorNet
|
||||
50
manga-py-stable_1.x/manga_py/providers/leomanga_com.py
Normal file
50
manga-py-stable_1.x/manga_py/providers/leomanga_com.py
Normal file
@@ -0,0 +1,50 @@
|
||||
from manga_py.provider import Provider
|
||||
from .helpers.std import Std
|
||||
|
||||
|
||||
class LeoMangaCom(Provider, Std):
|
||||
|
||||
def get_chapter_index(self) -> str:
|
||||
url = self.chapter
|
||||
idx = self.re.search(r'/manga/[^/]+/capitulo-(\d+)/([^/]+)/', url).groups()
|
||||
return '{1}-{0}'.format(*idx)
|
||||
|
||||
def get_main_content(self):
|
||||
return self._get_content('{}/manga/{}')
|
||||
|
||||
def get_manga_name(self) -> str:
|
||||
return self._get_name('/manga/([^/]+)')
|
||||
|
||||
def _get_first_href(self, parser):
|
||||
n = self.http().normalize_uri
|
||||
url = n(parser[0].get('href'))
|
||||
select0 = self.html_fromstring(url, '.list-group .cap-option')
|
||||
if select0:
|
||||
return n(select0[0].get('href'))
|
||||
return None
|
||||
|
||||
def get_chapters(self):
|
||||
chapter = self.document_fromstring(self.content, '.caps-list a')
|
||||
if chapter:
|
||||
url = self._get_first_href(chapter)
|
||||
if url:
|
||||
selector = '.viewcap-info select.form-control'
|
||||
parser = self.html_fromstring(url)
|
||||
options = self._first_select_options(parser, selector)
|
||||
return [i.get('value') for i in options[::-1]]
|
||||
return []
|
||||
|
||||
def get_files(self):
|
||||
n = self.http().normalize_uri
|
||||
items = self.html_fromstring(self.chapter, '.vertical .cap-images')
|
||||
return [n(i.get('src')) for i in items]
|
||||
|
||||
def get_cover(self) -> str:
|
||||
return self._cover_from_content('.cover img', 'data-original')
|
||||
|
||||
def book_meta(self) -> dict:
|
||||
# todo meta
|
||||
pass
|
||||
|
||||
|
||||
main = LeoMangaCom
|
||||
29
manga-py-stable_1.x/manga_py/providers/leviatanscans_com.py
Normal file
29
manga-py-stable_1.x/manga_py/providers/leviatanscans_com.py
Normal file
@@ -0,0 +1,29 @@
|
||||
from manga_py.provider import Provider
|
||||
from .helpers.std import Std
|
||||
|
||||
|
||||
class LeviatanScansCom(Provider, Std):
|
||||
|
||||
def get_chapter_index(self) -> str:
|
||||
return self.re.search(r'.+/(\d+/\d+)', self.chapter).group(1).replace('/', '-')
|
||||
|
||||
def get_main_content(self):
|
||||
return self.http_get(self.get_url())
|
||||
|
||||
def get_manga_name(self) -> str:
|
||||
return self.text_content(self.content, '.text-highlight')
|
||||
|
||||
def get_chapters(self):
|
||||
return self._elements('.list a.item-author')
|
||||
|
||||
def get_files(self):
|
||||
content = self.http_get(self.chapter)
|
||||
images = self.re.search(r'chapterPages\s*=\s*(\[.+?\])', content).group(1)
|
||||
return self.json.loads(images)
|
||||
|
||||
def get_cover(self) -> str:
|
||||
image = self._elements('.media-comic-card .media-content')[0]
|
||||
return self.parse_background(image)
|
||||
|
||||
|
||||
main = LeviatanScansCom
|
||||
30
manga-py-stable_1.x/manga_py/providers/lhscans_com.py
Normal file
30
manga-py-stable_1.x/manga_py/providers/lhscans_com.py
Normal file
@@ -0,0 +1,30 @@
|
||||
from manga_py.provider import Provider
|
||||
from .helpers.std import Std
|
||||
|
||||
|
||||
class LhScansCom(Provider, Std):
|
||||
def get_chapter_index(self) -> str:
|
||||
re = self.re.compile(r'-chapter-(\d+(?:\.\d+)?)')
|
||||
return re.search(self.chapter).group(1).replace('.', '-')
|
||||
|
||||
def get_main_content(self):
|
||||
return self._get_content('{}/manga-{}.html')
|
||||
|
||||
def get_manga_name(self) -> str:
|
||||
return self._get_name(r'(?:read|manga)-(.+?)(?:-chapter-.+)?.html')
|
||||
|
||||
def get_chapters(self):
|
||||
return self._elements('a.chapter')
|
||||
|
||||
def get_files(self):
|
||||
parser = self.html_fromstring(self.chapter)
|
||||
return self._images_helper(parser, '.chapter-content .chapter-img')
|
||||
|
||||
def get_cover(self) -> str:
|
||||
return self._cover_from_content('.thumbnail img')
|
||||
|
||||
def book_meta(self) -> dict:
|
||||
pass
|
||||
|
||||
|
||||
main = LhScansCom
|
||||
24
manga-py-stable_1.x/manga_py/providers/lhtranslation_com.py
Normal file
24
manga-py-stable_1.x/manga_py/providers/lhtranslation_com.py
Normal file
@@ -0,0 +1,24 @@
|
||||
from time import sleep
|
||||
|
||||
from requests import get
|
||||
|
||||
from .gomanga_co import GoMangaCo
|
||||
from .helpers.std import Std
|
||||
|
||||
|
||||
class LHTranslationCom(GoMangaCo, Std):
|
||||
_name_re = r'/(?:truyen|manga)-([^/]+)\.html'
|
||||
_content_str = '{}/manga-{}.html'
|
||||
_chapters_selector = '#tab-chapper td > a.chapter,#list-chapters a.chapter'
|
||||
|
||||
def get_chapter_index(self) -> str:
|
||||
idx = self.re.search(r'-chapter-(.+?)\.html', self.chapter)
|
||||
return idx.group(1).replace('.', '-')
|
||||
|
||||
def get_files(self):
|
||||
content = self.http_get(self.chapter)
|
||||
parser = self.document_fromstring(content, 'article#content,.chapter-content', 0)
|
||||
return self._images_helper(parser, 'img.chapter-img', 'data-original')
|
||||
|
||||
|
||||
main = LHTranslationCom
|
||||
52
manga-py-stable_1.x/manga_py/providers/lolibooru_moe.py
Normal file
52
manga-py-stable_1.x/manga_py/providers/lolibooru_moe.py
Normal file
@@ -0,0 +1,52 @@
|
||||
from .danbooru_donmai_us import DanbooruDonmaiUs
|
||||
from .helpers.std import Std
|
||||
|
||||
|
||||
class LoliBooruMoe(DanbooruDonmaiUs, Std):
|
||||
_archive_prefix = 'lolibooru_'
|
||||
|
||||
def get_manga_name(self) -> str:
|
||||
if ~self.get_url().find(r'tags='):
|
||||
self._is_tag = True
|
||||
self._manga_name = self._get_name(r'[\?&]tags=([^&]+)')
|
||||
else:
|
||||
self._manga_name = self._get_name(r'/post/show/(\d+)')
|
||||
return self._archive_prefix + self._manga_name
|
||||
|
||||
def get_chapters(self): # pragma: no cover
|
||||
if self._is_tag:
|
||||
pages = self._elements('#paginator .pagination > a')
|
||||
if pages:
|
||||
count = self.re.search(r'\bpage=(\d+)', pages[-2].get('href')).group(1)
|
||||
max_page = int(count)
|
||||
if max_page > 1001:
|
||||
self.log('1000 pages maximum!')
|
||||
max_page = 1000
|
||||
return range(1, max_page)[::-1]
|
||||
return [1]
|
||||
|
||||
def _tag_images(self): # pragma: no cover
|
||||
url = '{}/post?tags={}&page={}'.format(
|
||||
self.domain,
|
||||
self._manga_name,
|
||||
self.chapter,
|
||||
)
|
||||
parser = self.html_fromstring(url)
|
||||
return self._images_helper(parser, '#post-list-posts a.directlink', 'href')
|
||||
|
||||
def _post_image(self, url): # pragma: no cover
|
||||
if isinstance(url, str):
|
||||
parser = self.html_fromstring(url)
|
||||
else:
|
||||
parser = url
|
||||
|
||||
full_size = parser.cssselect('.status-notice a.highres-show')
|
||||
if full_size:
|
||||
return [full_size[0].get('href')]
|
||||
return [parser.cssselect('#image')[0].get('src')]
|
||||
|
||||
def chapter_for_json(self):
|
||||
return self.get_url()
|
||||
|
||||
|
||||
main = LoliBooruMoe
|
||||
10
manga-py-stable_1.x/manga_py/providers/lolivault_net.py
Normal file
10
manga-py-stable_1.x/manga_py/providers/lolivault_net.py
Normal file
@@ -0,0 +1,10 @@
|
||||
from .gomanga_co import GoMangaCo
|
||||
|
||||
|
||||
class LoliVaultNet(GoMangaCo):
|
||||
_name_re = '/online/[^/]+/([^/]+)/'
|
||||
_content_str = '{}/online/series/{}/'
|
||||
_chapters_selector = '.list .group .element .title a'
|
||||
|
||||
|
||||
main = LoliVaultNet
|
||||
45
manga-py-stable_1.x/manga_py/providers/luscious_net.py
Normal file
45
manga-py-stable_1.x/manga_py/providers/luscious_net.py
Normal file
@@ -0,0 +1,45 @@
|
||||
from manga_py.provider import Provider
|
||||
from .helpers.std import Std
|
||||
|
||||
|
||||
class LusciousNet(Provider, Std):
|
||||
|
||||
def get_archive_name(self) -> str:
|
||||
return 'archive'
|
||||
|
||||
def get_chapter_index(self) -> str:
|
||||
return '0'
|
||||
|
||||
def get_main_content(self):
|
||||
name = self._get_name('/albums?/([^/]+)/')
|
||||
return self.http_get('{}/albums/{}/'.format(self.domain, name))
|
||||
|
||||
def get_manga_name(self) -> str:
|
||||
return self._get_name('/albums?/([^/]+)_\d+/')
|
||||
|
||||
def get_chapters(self):
|
||||
return [b'0']
|
||||
|
||||
def get_files(self):
|
||||
items = self._elements('#album_meta_ds .item > a')
|
||||
n = self.http().normalize_uri
|
||||
images = []
|
||||
for i in items:
|
||||
content = self.http_get(n(i.get('href')), headers={'x-requested-with': 'XMLHttpRequest'})
|
||||
image = self.document_fromstring(content, '#single_picture')
|
||||
if image:
|
||||
images.append(n(image[0].get('src')))
|
||||
return images
|
||||
|
||||
def get_cover(self) -> str:
|
||||
return self._cover_from_content('.album_cover_item img')
|
||||
|
||||
def book_meta(self) -> dict:
|
||||
# todo meta
|
||||
pass
|
||||
|
||||
def chapter_for_json(self):
|
||||
return self.get_url()
|
||||
|
||||
|
||||
main = LusciousNet
|
||||
43
manga-py-stable_1.x/manga_py/providers/mang_as.py
Normal file
43
manga-py-stable_1.x/manga_py/providers/mang_as.py
Normal file
@@ -0,0 +1,43 @@
|
||||
from sys import stderr
|
||||
|
||||
from manga_py.provider import Provider
|
||||
from .helpers.std import Std
|
||||
|
||||
|
||||
class MangAs(Provider, Std):
|
||||
|
||||
def get_chapter_index(self) -> str:
|
||||
idx = self.re.search('/manga/[^/]+/([^/]+)', self.chapter).group(1)
|
||||
return idx.replace('.', '-')
|
||||
|
||||
def get_main_content(self):
|
||||
return self._get_content('{}/manga/{}')
|
||||
|
||||
def get_manga_name(self) -> str:
|
||||
return self._get_name('/manga/([^/]+)')
|
||||
|
||||
def get_chapters(self):
|
||||
return self._elements('.chapter-title-rtl > a')
|
||||
|
||||
def get_files(self):
|
||||
content = self.http_get(self.chapter)
|
||||
self.http().referer = self.chapter
|
||||
items = self.re.search(r'var\s+pages\s*=\s*(\[.+\])', content)
|
||||
if not items:
|
||||
self.log('Images not found!', file=stderr)
|
||||
return []
|
||||
n = self.http().normalize_uri
|
||||
items = self.json.loads(items.group(1))
|
||||
return [n(i.get('page_image')) for i in items]
|
||||
|
||||
def prepare_cookies(self):
|
||||
self._base_cookies(self.get_url())
|
||||
|
||||
def get_cover(self) -> str:
|
||||
return self._cover_from_content('.boxed > img.img-responsive')
|
||||
|
||||
def book_meta(self) -> dict:
|
||||
pass
|
||||
|
||||
|
||||
main = MangAs
|
||||
38
manga-py-stable_1.x/manga_py/providers/manga_ae.py
Normal file
38
manga-py-stable_1.x/manga_py/providers/manga_ae.py
Normal file
@@ -0,0 +1,38 @@
|
||||
from manga_py.provider import Provider
|
||||
from .helpers.std import Std
|
||||
|
||||
|
||||
class MangaAe(Provider, Std):
|
||||
|
||||
def get_chapter_index(self) -> str:
|
||||
return self.re.search(r'\.ae/[^/]+/(\d+)', self.chapter).group(1)
|
||||
|
||||
def get_main_content(self):
|
||||
return self._get_content('{}/{}/')
|
||||
|
||||
def get_manga_name(self) -> str:
|
||||
return self._get_name(r'\.ae/([^/]+)')
|
||||
|
||||
def get_chapters(self):
|
||||
return self._elements('li > a.chapter')
|
||||
|
||||
def get_files(self):
|
||||
img_selector = '#showchaptercontainer img'
|
||||
parser = self.html_fromstring(self.chapter)
|
||||
pages = parser.cssselect('#morepages a + a')
|
||||
images = self._images_helper(parser, img_selector)
|
||||
if pages:
|
||||
for i in pages:
|
||||
parser = self.html_fromstring(i.get('href'))
|
||||
images += self._images_helper(parser, img_selector)
|
||||
return images
|
||||
|
||||
def get_cover(self) -> str:
|
||||
return self._cover_from_content('img.manga-cover')
|
||||
|
||||
def book_meta(self) -> dict:
|
||||
# todo meta
|
||||
pass
|
||||
|
||||
|
||||
main = MangaAe
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user