# -*- coding: utf-8 -*- # Copyright 2015-2019 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. """Extract images from https://hitomi.la/""" from .common import GalleryExtractor from .. import text, util import string class HitomiGalleryExtractor(GalleryExtractor): """Extractor for image galleries from hitomi.la""" category = "hitomi" root = "https://hitomi.la" pattern = r"(?:https?://)?hitomi\.la/(?:galleries|reader)/(\d+)" test = ( ("https://hitomi.la/galleries/867789.html", { "pattern": r"https://aa.hitomi.la/galleries/867789/\d+.jpg", "keyword": "d097a8db8e810045131b4510c41714004f9eff3a", "count": 16, }), ("https://hitomi.la/galleries/1401410.html", { # download test "range": "1", "content": "b3ca8c6c8cc5826cf8b4ceb7252943abad7b8b4c", }), ("https://hitomi.la/galleries/733697.html", { # Game CG with scenes (#321) "url": "c2a84185f467450b8b9b72fbe40c0649029ce007", "count": 210, }), ("https://hitomi.la/reader/867789.html"), ) def __init__(self, match): self.gallery_id = match.group(1) url = "{}/galleries/{}.html".format(self.root, self.gallery_id) GalleryExtractor.__init__(self, match, url) def metadata(self, page): extr = text.extract_from(page, page.index('

', '<').strip()), "artist" : self._prep(extr('

', '

')), "group" : self._prep(extr('Group', '')), "type" : self._prep_1(extr('Type', '')), "language" : self._prep_1(extr('Language', '')), "parody" : self._prep(extr('Series', '')), "characters": self._prep(extr('Characters', '')), "tags" : self._prep(extr('Tags', '')), "date" : self._date(extr('', '')), } if data["language"] == "N/a": data["language"] = None data["lang"] = util.language_to_code(data["language"]) return data def images(self, page): # see https://ltn.hitomi.la/common.js offset = text.parse_int(self.gallery_id[-1]) % 3 subdomain = chr(97 + offset) + "a" base = "https://" + subdomain + ".hitomi.la/galleries/" # set Referer header before image downloads (#239) self.session.headers["Referer"] = self.chapter_url # handle Game CG galleries with scenes (#321) scenes = text.extract(page, "var scene_indexes = [", "]")[0] if scenes and scenes.strip(): url = "{}/reader/{}.html".format(self.root, self.gallery_id) page = self.request(url).text begin, end = ">//g.hitomi.la/galleries/", "" else: begin, end = "'//tn.hitomi.la/smalltn/", ".jpg'," return [ (base + urlpart, None) for urlpart in text.extract_iter(page, begin, end) ] @staticmethod def _prep(value): return [ text.unescape(string.capwords(v)) for v in text.extract_iter(value or "", '.html">', '<') ] @staticmethod def _prep_1(value): return text.remove_html(value).capitalize() @staticmethod def _date(value): return text.parse_datetime(value + ":00", "%Y-%m-%d %H:%M:%S%z")