Path: blob/master/gallery_dl/extractor/allporncomic.py
14119 views
# -*- coding: utf-8 -*-12# Copyright 2026 Mike Fährmann3#4# This program is free software; you can redistribute it and/or modify5# it under the terms of the GNU General Public License version 2 as6# published by the Free Software Foundation.78"""Extractors for https://allporncomic.com/"""910from .common import Extractor, ChapterExtractor, MangaExtractor, Message11from .. import text1213BASE_PATTERN = r"(?:https?://)?(?:www\.)?allporncomic\.com"141516class AllporncomicBase():17"""Base class for allporncomic extractors"""18category = "allporncomic"19root = "https://allporncomic.com"2021def _manga_info(self, slug, page=None):22if page is None:23url = f"{self.root}/porncomic/{slug}/"24page = self.request(url).text25extr = text.extract_from(page)2627lang = extr('property="og:locale" content="', '"')28title = text.unescape(extr('property="og:title" content="', '"'))29manga = text.re(r"(.+?)( \([^)]+\))?( \[[^\]]+\])?\s*$").match(title)3031return {32"description" : text.unescape(extr(33'property="og:description" content="', '"')),34"manga" : "" if manga is None else manga[1],35"manga_slug" : slug,36"manga_cover" : extr('property="og:image" content="', '"'),37"manga_date" : self.parse_datetime_iso(extr(38'"datePublished":"', '"')),39"manga_date_updated": self.parse_datetime_iso(extr(40'"dateModified":"', '"')),41"manga_id" : text.parse_int(extr(" postid-", " ")),42"rating" : text.parse_float(extr('total_votes">', "<")),43"votes" : text.parse_int(extr('id="countrate">', "<")),44"characters" : text.split_html(extr(45'class="author-content">', "</div>"))[::2],46"parody" : text.split_html(extr(47'class="author-content">', "</div>"))[::2],48"group" : text.split_html(extr(49'class="author-content">', "</div>"))[::2],50"artist" : text.split_html(extr(51'class="artist-content">', "</div>"))[::2],52"tags" : text.split_html(extr(53'class="genres-content">', "</div>"))[::2],54"type" : extr('class="summary-content">', "<").strip(),55"status" : extr('class="summary-content">', "<").strip(),56"comments" : text.parse_int(extr('<span>', " ")),57"bookmarks" : text.parse_int(extr(58'class="action_detail"><span>', " ")),59"lang" : lang.partition("_")[0],60}616263class AllporncomicChapterExtractor(AllporncomicBase, ChapterExtractor):64"""Extractor for allporncomic manga chapters"""65directory_fmt = ("{category}", "{path[:-1]:I}", "{title}")66filename_fmt = "{page:>03}.{extension}"67archive_fmt = "{manga_id}_{chapter_id}_{page}"68pattern = (BASE_PATTERN +69r"(/porncomic/([^/?#]+)/(\d+(?:-\d+)?)?([^/?#]+))")70example = "https://allporncomic.com/porncomic/MANGA/123-TITLE/"7172def __init__(self, match):73url = f"{self.root}{match[1]}/"74ChapterExtractor.__init__(self, match, url)7576def metadata(self, page):77_, manga_slug, chapter, title_slug = self.groups78if chapter is None:79chapter = sep = minor = ""80else:81chapter, sep, minor = chapter.partition("-")8283if '<source src="' in page:84media = "video"85self.needle = '<source src="'86else:87media = "image"88self.needle = ' data-src="'8990path = text.split_html(text.extr(91page, '<ol class="breadcrumb', '</ol>'))92title = text.re(93r"^(?:\s*\d+(?:\.\d+)?\s*\.|\[[^\]]+\])\s").sub("", path[-1])94title = text.re(95r"(?:\s+-)?"96r"(?:\s+[Cc]hapter \d+(?:\s+[Ee]xtras)?)?"97r"(?:\s+\([^)]+\))?"98r"(?:\s+(?:-\s+)?\[[^\]]+\])?\s*$").sub("", title)99100return {101**self.cache(self._manga_info, manga_slug),102"path" : path[3:],103"media" : media,104"title" : title,105"title_slug" : title_slug.lstrip("-"),106"chapter" : text.parse_int(chapter),107"chapter_id" : text.parse_int(text.extr(108page, 'manga_chapter_id" value="', '"')),109"chapter_minor": "." + minor if minor else "",110}111112def images(self, page):113return [114(url.strip(), None)115for url in text.extract_iter(page, self.needle, '"')116]117118119class AllporncomicMangaExtractor(AllporncomicBase, MangaExtractor):120"""Extractor for allporncomic manga"""121chapterclass = AllporncomicChapterExtractor122pattern = BASE_PATTERN + r"/porncomic/([^/?#]+)"123example = "https://allporncomic.com/porncomic/MANGA/"124125def __init__(self, match):126url = f"{self.root}/porncomic/{match[1]}/"127MangaExtractor.__init__(self, match, url)128129def chapters(self, page):130slug = text.extr(page, "/porncomic/", "/")131info = self._manga_info(slug, page)132133results = []134for ch in text.extract_iter(135page, '<li class="wp-manga-chapter', '</li>'):136url = text.extr(ch, ' href="', '"')137data = {138**info,139"date": self.parse_datetime(text.extr(140page, "<i>", "<"), "%B %d, %Y"),141}142results.append((url, data))143return results144145146class AllporncomicTagExtractor(AllporncomicBase, Extractor):147"""Extractor for allporncomic tag search results"""148subcategory = "tag"149pattern = (BASE_PATTERN + r"(/(?:porncomic-)?"150r"(?:genre|series|group|artist|characters)"151r"/[^/?#]+(?:/page/\d+)?)(/?\?[^#]+)?")152example = "https://allporncomic.com/porncomic-genre/GENRE/"153154def items(self):155data = {"_extractor": AllporncomicMangaExtractor}156157url = f"{self.root}{self.groups[0]}{self.groups[1] or '/'}"158while url:159page = self.request(url).text160161for manga in text.extract_iter(page, 'id="manga-item-', "</div>"):162yield Message.Queue, text.extr(manga, ' href="', '"'), data163164url = text.extr(page, '<link rel="next" href="', '"')165166167