Added manga-py source

This commit is contained in:
2019-12-14 22:33:14 -05:00
parent 9a4dd4b09b
commit 45067caea6
420 changed files with 18054 additions and 0 deletions

View 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

View 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

View 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

View 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

View 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
```

View 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

View 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

View 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

View 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

View 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

View File

@@ -0,0 +1,9 @@
from .read_powermanga_org import ReadPowerMangaOrg
class AdultoSeinagiOrg(ReadPowerMangaOrg):
_name_re = '[^/]/[^/]+/([^/]+)/'
_content_str = '{}/series/{}/'
main = AdultoSeinagiOrg

View 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

View 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

View File

@@ -0,0 +1,9 @@
from .read_powermanga_org import ReadPowerMangaOrg
class AntiSenseScansCom(ReadPowerMangaOrg):
_name_re = '/online/[^/]+/([^/]+)/'
_content_str = '{}/online/series/{}/'
main = AntiSenseScansCom

View 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

View File

@@ -0,0 +1,8 @@
from .danbooru_donmai_us import DanbooruDonmaiUs
class AtfBooruNinja(DanbooruDonmaiUs):
_archive_prefix = 'atfbooru'
main = AtfBooruNinja

View 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

View 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

View 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

View File

@@ -0,0 +1,9 @@
from .read_powermanga_org import ReadPowerMangaOrg
class BnsShounenAiNet(ReadPowerMangaOrg):
_name_re = '/read/[^/]+/([^/]+)/'
_content_str = '{}/read/series/{}/'
main = BnsShounenAiNet

View 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

View 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

View 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

View File

@@ -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

View File

@@ -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

View 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

View File

@@ -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

View File

@@ -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

View 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

View 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

View File

@@ -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

View 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

View 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

View 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

View 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

View File

@@ -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

View File

@@ -0,0 +1,9 @@
from .helveticascans_com import HelveticaScansCom
class DejameProbarEs(HelveticaScansCom):
_name_re = '/slide/[^/]+/([^/]+)/'
_content_str = '{}/slide/series/{}/'
main = DejameProbarEs

View 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

View File

@@ -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

View 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&gtk=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

View 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('&amp;', '&') 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View File

@@ -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)

View File

@@ -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

View File

@@ -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

View File

@@ -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

View 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')

View 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

View 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

View File

@@ -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

View File

@@ -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

View File

@@ -0,0 +1,9 @@
from .gomanga_co import GoMangaCo
class HelveticaScansCom(GoMangaCo):
_name_re = '/r/[^/]+/([^/]+)/'
_content_str = '{}/r/series/{}/'
main = HelveticaScansCom

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View File

@@ -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

View 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

View File

@@ -0,0 +1,9 @@
from .gomanga_co import GoMangaCo
class HotChocolateScansCom(GoMangaCo):
_name_re = '/fs/[^/]+/([^/]+)/'
_content_str = '{}/fs/series/{}/'
main = HotChocolateScansCom

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View File

@@ -0,0 +1,9 @@
from .gomanga_co import GoMangaCo
class LectorKirishimaFanSubCom(GoMangaCo):
_name_re = '/(?:reader/)?(?:series|read)/([^/]+)/'
_content_str = '{}/lector/series/{}/'
main = LectorKirishimaFanSubCom

View File

@@ -0,0 +1,9 @@
from .gomanga_co import GoMangaCo
class LectorYTNoFanCom(GoMangaCo):
_name_re = '/(?:series|read)/([^/]+)/'
_content_str = '{}/series/{}/'
main = LectorYTNoFanCom

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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