[comick] add initial support (#1825 #6782)

This commit is contained in:
Mike Fährmann
2025-06-24 18:52:24 +02:00
parent 790e097edd
commit 578aea51ed
4 changed files with 325 additions and 1 deletions

View File

@@ -187,6 +187,12 @@ Consider all listed sites to potentially be NSFW.
<td>Tag Searches</td>
<td></td>
</tr>
<tr>
<td>Comick</td>
<td>https://comick.io/</td>
<td>Chapters, Manga</td>
<td></td>
</tr>
<tr>
<td>Coomer</td>
<td>https://coomer.su/</td>

View File

@@ -7,7 +7,7 @@
# published by the Free Software Foundation.
import sys
from ..util import re_compile
from ..text import re_compile
modules = [
"2ch",
@@ -40,6 +40,7 @@ modules = [
"chevereto",
"cien",
"civitai",
"comick",
"comicvine",
"cyberdrop",
"danbooru",

View File

@@ -0,0 +1,167 @@
# -*- coding: utf-8 -*-
# Copyright 2025 Mike Fährmann
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation.
"""Extractors for https://comick.io/"""
from .common import ChapterExtractor, MangaExtractor
from .. import text
from ..cache import memcache
BASE_PATTERN = r"(?:https?://)?(?:www\.)?comick\.io"
class ComickBase():
"""Base class for comick.io extractors"""
category = "comick"
root = "https://comick.io"
@memcache(keyarg=1)
def _manga_info(self, slug):
url = f"{self.root}/comic/{slug}"
page = self.request(url).text
data = self._extract_nextdata(page)
props = data["props"]["pageProps"]
comic = props["comic"]
map_status = {
0: "Unknown",
1: "Ongoing",
2: "Complete",
}
genre = []
theme = []
format = ""
for item in comic["md_comic_md_genres"]:
item = item["md_genres"]
group = item["group"]
if group == "Genre":
genre.append(item["name"])
elif group == "Theme":
theme.append(item["name"])
else:
format = item["name"]
if mu := comic["mu_comics"]:
tags = [c["mu_categories"]["title"]
for c in mu["mu_comic_categories"]]
publisher = [p["mu_publishers"]["title"]
for p in mu["mu_comic_publishers"]]
else:
tags = publisher = ()
return {
"manga": comic["title"],
"manga_id": comic["id"],
"manga_hid": comic["hid"],
"manga_slug": slug,
"manga_titles": [t["title"] for t in comic["md_titles"]],
"artist": [a["name"] for a in props["artists"]],
"author": [a["name"] for a in props["authors"]],
"genre" : genre,
"theme" : theme,
"format": format,
"tags" : tags,
"publisher": publisher,
"published": text.parse_int(comic["year"]),
"description": comic["desc"],
"demographic": props["demographic"],
"origin": comic["iso639_1"],
"mature": props["matureContent"],
"rating": comic["content_rating"],
"rank" : comic["follow_rank"],
"score" : text.parse_float(comic["bayesian_rating"]),
"status": map_status[comic["status"]],
"links" : comic["links"],
"_build_id": data["buildId"],
}
def _chapter_info(self, manga, chstr):
slug = manga['manga_slug']
url = (f"{self.root}/_next/data/{manga['_build_id']}"
f"/comic/{slug}/{chstr}.json")
params = {"slug": slug, "chapter": chstr}
return self.request_json(url, params=params)["pageProps"]
class ComickChapterExtractor(ComickBase, ChapterExtractor):
"""Extractor for comick.io manga chapters"""
pattern = BASE_PATTERN + r"/comic/([\w-]+)/(\w+-chapter-[^/?#]+)"
example = "https://comick.io/comic/MANGA/ID-chapter-123-en"
def __init__(self, match):
ChapterExtractor.__init__(self, match, False)
def metadata(self, page):
slug, chstr = self.groups
manga = self._manga_info(slug)
props = self._chapter_info(manga, chstr)
ch = props["chapter"]
self._images = ch["md_images"]
chapter, sep, minor = ch["chap"].partition(".")
return {
**manga,
"title" : props["chapTitle"],
"volume" : text.parse_int(ch["vol"]),
"chapter" : text.parse_int(chapter),
"chapter_minor" : sep + minor,
"chapter_id" : ch["id"],
"chapter_hid" : ch["hid"],
"chapter_string": chstr,
"group" : ch["group_name"],
"date" : text.parse_datetime(
ch["created_at"][:19], "%Y-%m-%dT%H:%M:%S"),
"date_updated" : text.parse_datetime(
ch["updated_at"][:19], "%Y-%m-%dT%H:%M:%S"),
"lang" : ch["lang"],
}
def images(self, page):
return [
("https://meo.comick.pictures/" + img["b2key"], img)
for img in self._images
]
class ComickMangaExtractor(ComickBase, MangaExtractor):
"""Extractor for comick.io manga"""
chapterclass = ComickChapterExtractor
pattern = BASE_PATTERN + r"/comic/([\w-]+)/?(?:\?lang=(\w{2}))?"
example = "https://comick.io/comic/MANGA"
def __init__(self, match):
MangaExtractor.__init__(self, match, False)
def chapters(self, page):
slug, lang = self.groups
manga = self._manga_info(slug)
url = f"https://api.comick.io/comic/{manga['manga_hid']}/chapters"
params = {"lang": lang}
data = self.request_json(url, params=params)
if data["total"] > data["limit"]:
# workaround for manga with more than 60 chapters
ch = data["chapters"][0]
chstr = f"{ch['hid']}-chapter-{ch['chap']}-{ch['lang']}"
data = self._chapter_info(manga, chstr)
results = []
for ch in data["chapters"]:
url = (f"{self.root}/comic/{slug}"
f"/{ch['hid']}-chapter-{ch['chap']}-{ch['lang']}")
ch.update(manga)
chapter, sep, minor = ch["chap"].partition(".")
ch["chapter"] = text.parse_int(chapter)
ch["chapter_minor"] = sep + minor
results.append((url, ch))
return results

150
test/results/comick.py Normal file
View File

@@ -0,0 +1,150 @@
# -*- coding: utf-8 -*-
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation.
from gallery_dl.extractor import comick
__tests__ = (
{
"#url" : "https://comick.io/comic/neko-no-oshigoto/L7TaJB4n-chapter-10.5-en",
"#class" : comick.ComickChapterExtractor,
"#results" : (
"https://meo.comick.pictures/0-ThqKs6imRo5oK.webp",
"https://meo.comick.pictures/1-NHbu8c09NjBCv.webp",
"https://meo.comick.pictures/2-i88d48rBYweD0.webp",
"https://meo.comick.pictures/3-AKTIcb3vjy3Lf.webp",
"https://meo.comick.pictures/4-N8Vj2XVdYY4Pv.webp",
),
"volume": 1,
"chapter": 10,
"chapter_minor": ".5",
"chapter_hid": "L7TaJB4n",
"chapter_id": 4105343,
"chapter_string": "L7TaJB4n-chapter-10.5-en",
"count": 5,
"page" : range(1, 5),
"date": "dt:2025-06-21 13:07:32",
"date_updated": "dt:2025-06-21 16:52:40",
"demographic": "Seinen",
"description": "Ever wondered what it would be like if your cat had to get a job? The cats in this book do every kind of occupation you can imagine, and they do it just the way they like. Feline chefs, dentists, wrestlers, detectives, opera singers and much more await in this hilarious full-color collection!",
"format": "Full Color",
"lang": "en",
"manga": "Neko no Oshigoto",
"manga_hid": "aHgHjCfY",
"manga_id": 119004,
"manga_slug": "neko-no-oshigoto",
"mature": False,
"origin": "ja",
"published": 2023,
"publisher": (),
"rank": 29915,
"rating": "safe",
"score": float,
"status": "Ongoing",
"title": "",
"tags" : (),
"artist": ["Pandania"],
"author": ["Pandania"],
"group" : ["Official"],
"theme" : ["Animals"],
"genre" : [
"Comedy",
"Slice of Life",
],
"manga_titles": [
"ねこのおしごと",
"Cats With Jobs",
],
"links": {
"al" : "194211",
"amz" : "https://www.amazon.co.jp/%E3%81%AD%E3%81%93%E3%81%AE%E3%81%8A%E3%81%97%E3%81%94%E3%81%A8-1-%E3%83%92%E3%83%BC%E3%83%AD%E3%83%BC%E3%82%BA%E3%82%B3%E3%83%9F%E3%83%83%E3%82%AF%E3%82%B9-%E3%82%8F%E3%81%84%E3%82%8B%E3%81%A9-%E3%81%B1%E3%82%93%E3%81%A0%E3%81%AB%E3%81%82/dp/4864681643",
"bw" : "series/409260/list",
"ebj" : "https://ebookjapan.yahoo.co.jp/books/754652/",
"engtl": "https://sevenseasentertainment.com/series/cats-with-jobs/",
},
},
{
"#url" : "https://comick.io/comic/koko-jidai-ni-gomandatta-jou-sama-to-no-dousei-seikatsu-wa-igaito-igokochi-ga-warukunai/aPu5CgJA-chapter-3-vi",
"#class" : comick.ComickChapterExtractor,
"#pattern" : r"https://meo.comick.pictures/\d+-[\w-]+\.(jpg|png)",
"#count" : 20,
"artist": ["Togawa Ritsu"],
"author": ["Dozaemon Misoneta"],
"volume": 1,
"chapter": 3,
"chapter_minor": "",
"chapter_hid": "aPu5CgJA",
"chapter_id": 4043238,
"chapter_string": "aPu5CgJA-chapter-3-vi",
"count": 20,
"date": "dt:2025-05-09 17:25:38",
"date_updated": "dt:2025-06-21 18:25:55",
"demographic": "Seinen",
"description": "\"Hey, wanna do it?\"\n\nA romantic comedy about living together with a scarred \"Queen\" in a relationship thats more than friends but less than lovers!!\n\nOne late night, Yamamoto, a college student working part-time at a convenience store, reunites with Hayashi Megumi, his high school classmate and the most beautiful girl in their class.\nKnown as the \"Queen\" for her strong-willed and arrogant personality, Yamamoto had always found her difficult to get along with. However, during a routine conversation, he notices painful bruises on her wrist.\nAfter learning that her boyfriend had been abusing her, Yamamoto decides to let Hayashi stay at his place...!?",
"format": "Adaptation",
"genre": [
"Comedy",
"Drama",
"Mystery",
"Psychological",
"Romance",
],
"group": [
"Dịch cho vui",
],
"lang": "vi",
"links": {
"al" : "187656",
"amz": "https://www.amazon.co.jp/-/en/dp/4088937163",
"bw" : "series/520105/list",
"mal": "178605",
"raw": "https://manga.nicovideo.jp/comic/71123",
},
"manga": "Koko Jidai ni Gomandatta Jou sama to no Dousei Seikatsu wa Igaito Igokochi ga Warukunai",
"manga_hid": "oeb0Dydj",
"manga_id": 114526,
"manga_slug": "koko-jidai-ni-gomandatta-jou-sama-to-no-dousei-seikatsu-wa-igaito-igokochi-ga-warukunai",
"manga_titles": [
"Cuộc sống chung với nữ hoàng từng kiêu ngạo hồi cấp ba, không ngờ lại khá dễ chịu.",
"高校時代に傲慢だった女王様との同棲生活は意外と居心地が悪くない",
"Koko Jidai Ni Gomandatta Jou Sama To No Dosei Seikatsu Ha Igaito Igokochi Ga Warukunai",
"Living together with the queen from my high school days who was arrogant, surprisingly isn't that uncomfortable",
],
"mature": False,
"origin": "ja",
"published": 2025,
"publisher": (),
"rank": range(800, 1000),
"rating": "safe",
"score": float,
"status": "Ongoing",
"tags" : (),
"theme": ["School Life"],
"title": "Yamamoto \"Đuổi\" Hayashi Đi Ư!?",
},
{
"#url" : "https://comick.io/comic/koko-jidai-ni-gomandatta-jou-sama-to-no-dousei-seikatsu-wa-igaito-igokochi-ga-warukunai?lang=vi",
"#comment" : "language filter",
"#class" : comick.ComickMangaExtractor,
"#pattern" : comick.ComickChapterExtractor.pattern,
"#results" : (
"https://comick.io/comic/koko-jidai-ni-gomandatta-jou-sama-to-no-dousei-seikatsu-wa-igaito-igokochi-ga-warukunai/1ngqqSQg-chapter-1-vi",
"https://comick.io/comic/koko-jidai-ni-gomandatta-jou-sama-to-no-dousei-seikatsu-wa-igaito-igokochi-ga-warukunai/rSROPoui-chapter-2-vi",
"https://comick.io/comic/koko-jidai-ni-gomandatta-jou-sama-to-no-dousei-seikatsu-wa-igaito-igokochi-ga-warukunai/aPu5CgJA-chapter-3-vi",
"https://comick.io/comic/koko-jidai-ni-gomandatta-jou-sama-to-no-dousei-seikatsu-wa-igaito-igokochi-ga-warukunai/eQ26SPqi-chapter-4-vi",
),
"lang": "vi",
},
)