diff --git a/gallery_dl/extractor/mangafreak.py b/gallery_dl/extractor/mangafreak.py index 1ea2cd50..4e015563 100644 --- a/gallery_dl/extractor/mangafreak.py +++ b/gallery_dl/extractor/mangafreak.py @@ -1,7 +1,5 @@ # -*- 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. @@ -11,7 +9,7 @@ from .common import ChapterExtractor, MangaExtractor from .. import text -BASE_PATTERN = r"(?:https?://)?(?:ww\d\.)?mangafreak\.me" +BASE_PATTERN = r"(?:https?://)?(?:ww[\dw]\.)?mangafreak\.me" class MangafreakBase(): @@ -22,33 +20,30 @@ class MangafreakBase(): class MangafreakChapterExtractor(MangafreakBase, ChapterExtractor): """Extractor for mangafreak manga chapters""" - pattern = BASE_PATTERN + r"(/Read1_(.+)_(\d+[a-z]?))" + pattern = BASE_PATTERN + r"(/Read1_([^/?#]+)_((\d+)([a-z])?))" example = "https://ww2.mangafreak.me/Read1_Onepunch_Man_1" def metadata(self, page): - extr = text.extract_from(page) - manga = text.unescape(extr("", " Chapter ")) - title = text.unescape(extr("", " - MangaFreak")) - - chapter_str = self.groups[2] - chapter, sep, minor = chapter_str.partition("e") + manga = text.extr(page, "<title>Read ", " Chapter ") + title = text.extr(page, 'selected="selected">', "<").partition(": ")[2] + _, manga_slug, chapter_string, chapter, minor = self.groups return { - "manga" : manga, - "title" : title, + "manga" : text.unescape(manga), + "manga_slug" : manga_slug, + "title" : text.unescape(title) if title else "", "chapter" : text.parse_int(chapter), - "chapter_minor": sep + minor, - "chapter_string": chapter_str, - "manga_slug" : self.groups[1], + "chapter_minor": "" if minor is None else minor, + "chapter_string": chapter_string, "lang" : "en", "language" : "English", } def images(self, page): + base = "https://images.mangafreak.me/mangas/" return [ - ("https://images.mangafreak.me/mangas/" + path, None) - for path in text.extract_iter( - page, 'src="https://images.mangafreak.me/mangas/', '"') + (base + path, None) + for path in text.extract_iter(page, 'src="' + base, '"') ] @@ -59,34 +54,32 @@ class MangafreakMangaExtractor(MangafreakBase, MangaExtractor): example = "https://ww2.mangafreak.me/Manga/Onepunch_Man" def chapters(self, page): - extr = text.extract_from(page) - manga = text.unescape(extr("<title>", " Manga")) - - chapter_table = text.extr(page, "<table>", "</table>") - if not chapter_table: - return [] + table = text.extr(page, "<table>", "</table>") + if not table: + return () data = { - "manga" : manga, + "manga" : text.unescape(text.extr(page, "<title>", " Manga")), "manga_slug": self.groups[1], "lang" : "en", "language" : "English", } results = [] - for row in text.extract_iter(chapter_table, "<tr>", "</tr>"): + chapter_match = text.re(r"(\d+)(\w*)").match + for row in text.extract_iter(table, "<tr>", "</tr>"): href = text.extr(row, '<a href="', '"') if not href: continue url = self.root + href - chapter_str = url.rpartition("_")[2] - chapter, sep, minor = chapter_str.partition("e") - + chapter_string = href.rpartition("_")[2] + chapter, minor = chapter_match(chapter_string).groups() + title = text.extr(row, '">', '<').partition(" - ")[2] results.append((url, { - "chapter" : text.parse_int(chapter), - "chapter_minor": sep + minor, - "chapter_string": chapter_str, + "chapter" : text.parse_int(chapter), + "chapter_minor" : minor, + "chapter_string": chapter_string, + "title" : text.unescape(title) if title else "", **data, })) - return results diff --git a/test/results/mangafreak.py b/test/results/mangafreak.py index 3466bb0f..0478f8aa 100644 --- a/test/results/mangafreak.py +++ b/test/results/mangafreak.py @@ -32,6 +32,37 @@ __tests__ = ( "chapter_string": "167e", }, +{ + "#url" : "https://ww2.mangafreak.me/Read1_Sss_Rank_Dungeon_De_Knife_Ippon_Tewatasare_Tsuihou_Sareta_Shiro_Madoushi_Yggdrasil_No_Noroi_Ni_Yori_Jakuten_De_Aru_Maryoku_Fusoku_Wo_Kokufuku_Shi_Sekai_Saikyou_E_To_Itaru_23c", + "#class" : mangafreak.MangafreakChapterExtractor, + "#pattern" : r"https://images\.mangafreak\.me/mangas/sss_rank_dungeon_de_knife_ippon_tewatasare_tsuihou_sareta_shiro_madoushi_yggdrasil_no_noroi_ni_yori_jakuten_de_aru_maryoku_fusoku_wo_kokufuku_shi_sekai_saikyou_e_to_itaru/sss_rank_dungeon_de_knife_ippon_tewatasare_tsuihou_sareta_shiro_madoushi_yggdrasil_no_noroi_ni_yori_jakuten_de_aru_maryoku_fusoku_wo_kokufuku_shi_sekai_saikyou_e_to_itaru_23c/sss_rank_dungeon_de_knife_ippon_tewatasare_tsuihou_sareta_shiro_madoushi_yggdrasil_no_noroi_ni_yori_jakuten_de_aru_maryoku_fusoku_wo_kokufuku_shi_sekai_saikyou_e_to_itaru_23c_\d+\.jpg", + "#count" : 11, + + "chapter" : 23, + "chapter_minor" : "c", + "chapter_string": "23c", + "count" : 11, + "page" : range(1, 11), + "filename" : str, + "extension" : "jpg", + "lang" : "en", + "language" : "English", + "manga" : "Sss Rank Dungeon De Knife Ippon Tewatasare Tsuihou Sareta Shiro Madoushi Yggdrasil No Noroi Ni Yori Jakuten De Aru Maryoku Fusoku Wo Kokufuku Shi Sekai Saikyou E To Itaru", + "manga_slug" : "Sss_Rank_Dungeon_De_Knife_Ippon_Tewatasare_Tsuihou_Sareta_Shiro_Madoushi_Yggdrasil_No_Noroi_Ni_Yori_Jakuten_De_Aru_Maryoku_Fusoku_Wo_Kokufuku_Shi_Sekai_Saikyou_E_To_Itaru", + "title" : "", +}, + +{ + "#url" : "https://ww2.mangafreak.me/Read1_Tensei_Shitara_Slime_Datta_Ken_62", + "#class" : mangafreak.MangafreakChapterExtractor, + "#count" : 19, + + "chapter" : 62, + "count" : 19, + "manga" : "Tensei Shitara Slime Datta Ken", + "title" : "To be a Monster or Human", +}, + { "#url" : "https://ww2.mangafreak.me/Manga/Onepunch_Man", "#class" : mangafreak.MangafreakMangaExtractor, @@ -45,4 +76,20 @@ __tests__ = ( "chapter" : int, }, +{ + "#url" : "https://ww2.mangafreak.me/Manga/Sss_Rank_Dungeon_De_Knife_Ippon_Tewatasare_Tsuihou_Sareta_Shiro_Madoushi_Yggdrasil_No_Noroi_Ni_Yori_Jakuten_De_Aru_Maryoku_Fusoku_Wo_Kokufuku_Shi_Sekai_Saikyou_E_To_Itaru", + "#class" : mangafreak.MangafreakMangaExtractor, + "#pattern" : mangafreak.MangafreakChapterExtractor.pattern, + "#count" : range(40, 80), + + "chapter" : int, + "chapter_minor" : {"", "a", "b", "c"}, + "chapter_string": str, + "lang" : "en", + "language" : "English", + "manga" : "SSS Rank Dungeon de Knife Ippon Tewatasare Tsuihou Sareta Shiro Madoushi: Yggdrasil no Noroi ni yori Jakuten de aru Maryoku Fusoku wo Kokufuku-shi Sekai Saikyou e to Itaru", + "manga_slug" : "Sss_Rank_Dungeon_De_Knife_Ippon_Tewatasare_Tsuihou_Sareta_Shiro_Madoushi_Yggdrasil_No_Noroi_Ni_Yori_Jakuten_De_Aru_Maryoku_Fusoku_Wo_Kokufuku_Shi_Sekai_Saikyou_E_To_Itaru", + "title" : str, +}, + )