consistent extractor naming scheme + docstrings

pull/13/head
Mike Fährmann 8 years ago
parent 888a988725
commit d7e168799d
No known key found for this signature in database
GPG Key ID: 5680CA389D365A88

@ -6,11 +6,11 @@
# it under the terms of the GNU General Public License version 2 as # it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation. # published by the Free Software Foundation.
"""Extract image-urls from http://behoimi.org/""" """Extract images from http://behoimi.org/"""
from . import booru from . import booru
class ThreeDeeBooruExtractor(booru.JSONBooruExtractor): class ThreedeebooruExtractor(booru.JSONBooruExtractor):
"""Base class for 3dbooru extractors""" """Base class for 3dbooru extractors"""
category = "3dbooru" category = "3dbooru"
api_url = "http://behoimi.org/post/index.json" api_url = "http://behoimi.org/post/index.json"
@ -19,8 +19,8 @@ class ThreeDeeBooruExtractor(booru.JSONBooruExtractor):
"User-Agent": "Mozilla/5.0", "User-Agent": "Mozilla/5.0",
} }
class ThreeDeeBooruTagExtractor(ThreeDeeBooruExtractor, booru.BooruTagExtractor): class ThreedeebooruTagExtractor(ThreedeebooruExtractor, booru.BooruTagExtractor):
"""Extract images from 3dbooru based on search-tags""" """Extractor for images from behoimi.org based on search-tags"""
subcategory = "tag" subcategory = "tag"
pattern = [r"(?:https?://)?(?:www\.)?behoimi\.org/post(?:/(?:index)?)?\?tags=([^&]+)"] pattern = [r"(?:https?://)?(?:www\.)?behoimi\.org/post(?:/(?:index)?)?\?tags=([^&]+)"]
test = [("http://behoimi.org/post?tags=himekawa_azuru dress", { test = [("http://behoimi.org/post?tags=himekawa_azuru dress", {
@ -28,8 +28,8 @@ class ThreeDeeBooruTagExtractor(ThreeDeeBooruExtractor, booru.BooruTagExtractor)
"content": "11cbda40c287e026c1ce4ca430810f761f2d0b2a", "content": "11cbda40c287e026c1ce4ca430810f761f2d0b2a",
})] })]
class ThreeDeeBooruPoolExtractor(ThreeDeeBooruExtractor, booru.BooruPoolExtractor): class ThreedeebooruPoolExtractor(ThreedeebooruExtractor, booru.BooruPoolExtractor):
"""Extract image-pools from 3dbooru""" """Extractor for image-pools from behoimi.org"""
subcategory = "pool" subcategory = "pool"
pattern = [r"(?:https?://)?(?:www\.)?behoimi\.org/pool/show/(\d+)"] pattern = [r"(?:https?://)?(?:www\.)?behoimi\.org/pool/show/(\d+)"]
test = [("http://behoimi.org/pool/show/27", { test = [("http://behoimi.org/pool/show/27", {
@ -37,8 +37,8 @@ class ThreeDeeBooruPoolExtractor(ThreeDeeBooruExtractor, booru.BooruPoolExtracto
"content": "fd5b37c5c6c2de4b4d6f1facffdefa1e28176554", "content": "fd5b37c5c6c2de4b4d6f1facffdefa1e28176554",
})] })]
class ThreeDeeBooruPostExtractor(ThreeDeeBooruExtractor, booru.BooruPostExtractor): class ThreedeebooruPostExtractor(ThreedeebooruExtractor, booru.BooruPostExtractor):
"""Extract single images from 3dbooru""" """Extractor for single images from behoimi.org"""
subcategory = "post" subcategory = "post"
pattern = [r"(?:https?://)?(?:www\.)?behoimi\.org/post/show/(\d+)"] pattern = [r"(?:https?://)?(?:www\.)?behoimi\.org/post/show/(\d+)"]
test = [("http://behoimi.org/post/show/140852", { test = [("http://behoimi.org/post/show/140852", {

@ -6,13 +6,14 @@
# it under the terms of the GNU General Public License version 2 as # it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation. # published by the Free Software Foundation.
"""Extract image- and video-urls from threads on https://www.4chan.org/""" """Extract images and videos from https://www.4chan.org/"""
from .chan import ChanExtractor from .chan import ChanExtractor
class FourChanExtractor(ChanExtractor): class FourchanThreadExtractor(ChanExtractor):
"""Extractor for images from threads from 4chan.org"""
category = "4chan" category = "4chan"
subcategory = "thread"
pattern = [r"(?:https?://)?boards\.4chan\.org/([^/]+)/thread/(\d+)"] pattern = [r"(?:https?://)?boards\.4chan\.org/([^/]+)/thread/(\d+)"]
api_url = "https://a.4cdn.org/{board}/thread/{thread}.json" api_url = "https://a.4cdn.org/{board}/thread/{thread}.json"
file_url = "https://i.4cdn.org/{board}/{tim}{ext}" file_url = "https://i.4cdn.org/{board}/{tim}{ext}"

@ -6,13 +6,14 @@
# it under the terms of the GNU General Public License version 2 as # it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation. # published by the Free Software Foundation.
"""Extract image- and video-urls from threads on https://8ch.net/""" """Extract images and videos from https://8ch.net/"""
from .chan import ChanExtractor from .chan import ChanExtractor
class InfinityChanExtractor(ChanExtractor): class InfinitychanThreadExtractor(ChanExtractor):
"""Extractor for images from threads from 8ch.net"""
category = "8chan" category = "8chan"
subcategory = "thread"
pattern = [r"(?:https?://)?(?:www\.)?8ch\.net/([^/]+)/res/(\d+)"] pattern = [r"(?:https?://)?(?:www\.)?8ch\.net/([^/]+)/res/(\d+)"]
api_url = "https://8ch.net/{board}/res/{thread}.json" api_url = "https://8ch.net/{board}/res/{thread}.json"
file_url = "https://8ch.net/{board}/src/{tim}{ext}" file_url = "https://8ch.net/{board}/src/{tim}{ext}"

@ -6,15 +6,16 @@
# it under the terms of the GNU General Public License version 2 as # it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation. # published by the Free Software Foundation.
"""Extract manga pages from http://bato.to/""" """Extract manga chapters from http://bato.to/"""
from .common import AsynchronousExtractor, Message from .common import AsynchronousExtractor, Message
from .. import text, iso639_1 from .. import text, iso639_1
import re import re
class BatotoExtractor(AsynchronousExtractor): class BatotoChapterExtractor(AsynchronousExtractor):
"""Extractor for manga-chapters from bato.to"""
category = "batoto" category = "batoto"
subcategory = "chapter"
directory_fmt = ["{category}", "{manga}", "c{chapter:>03} - {title}"] directory_fmt = ["{category}", "{manga}", "c{chapter:>03} - {title}"]
filename_fmt = "{manga}_c{chapter:>03}_{page:>03}.{extension}" filename_fmt = "{manga}_c{chapter:>03}_{page:>03}.{extension}"
pattern = [r"(?:https?://)?(?:www\.)?bato\.to/reader#([0-9a-f]+)"] pattern = [r"(?:https?://)?(?:www\.)?bato\.to/reader#([0-9a-f]+)"]

@ -15,7 +15,7 @@ import json
import urllib.parse import urllib.parse
class BooruExtractor(Extractor): class BooruExtractor(Extractor):
"""Base class for all booru extractors"""
info = {} info = {}
headers = {} headers = {}
page = "page" page = "page"
@ -73,7 +73,7 @@ class BooruExtractor(Extractor):
class JSONBooruExtractor(BooruExtractor): class JSONBooruExtractor(BooruExtractor):
"""Base class for JSON based API responses"""
def items_impl(self): def items_impl(self):
self.update_page(reset=True) self.update_page(reset=True)
while True: while True:
@ -89,7 +89,7 @@ class JSONBooruExtractor(BooruExtractor):
class XMLBooruExtractor(BooruExtractor): class XMLBooruExtractor(BooruExtractor):
"""Base class for XML based API responses"""
def items_impl(self): def items_impl(self):
self.update_page(reset=True) self.update_page(reset=True)
while True: while True:
@ -104,8 +104,7 @@ class XMLBooruExtractor(BooruExtractor):
class BooruTagExtractor(BooruExtractor): class BooruTagExtractor(BooruExtractor):
"""Extract images based on search-tags""" """Extractor for images based on search-tags"""
directory_fmt = ["{category}", "{tags}"] directory_fmt = ["{category}", "{tags}"]
filename_fmt = "{category}_{id}_{md5}.{extension}" filename_fmt = "{category}_{id}_{md5}.{extension}"
@ -122,8 +121,7 @@ class BooruTagExtractor(BooruExtractor):
class BooruPoolExtractor(BooruExtractor): class BooruPoolExtractor(BooruExtractor):
"""Extract image-pools""" """Extractor for image-pools"""
directory_fmt = ["{category}", "pool", "{pool}"] directory_fmt = ["{category}", "pool", "{pool}"]
filename_fmt = "{category}_{id}_{md5}.{extension}" filename_fmt = "{category}_{id}_{md5}.{extension}"
@ -140,8 +138,7 @@ class BooruPoolExtractor(BooruExtractor):
class BooruPostExtractor(BooruExtractor): class BooruPostExtractor(BooruExtractor):
"""Extract single images""" """Extractor for single images"""
directory_fmt = ["{category}"] directory_fmt = ["{category}"]
filename_fmt = "{category}_{id}_{md5}.{extension}" filename_fmt = "{category}_{id}_{md5}.{extension}"

@ -12,7 +12,7 @@ from .common import Extractor, Message
from .. import text from .. import text
class ChanExtractor(Extractor): class ChanExtractor(Extractor):
"""Base class for extractors for Futaba Channel boards"""
directory_fmt = ["{category}", "{board}-{thread}"] directory_fmt = ["{category}", "{board}-{thread}"]
filename_fmt = "{tim}-{filename}{ext}" filename_fmt = "{tim}-{filename}{ext}"
api_url = "" api_url = ""

@ -14,6 +14,7 @@ from .. import text
class ChronosImageExtractor(Extractor): class ChronosImageExtractor(Extractor):
"""Extractor for single images from chronos.to""" """Extractor for single images from chronos.to"""
category = "chronos" category = "chronos"
subcategory = "image"
directory_fmt = ["{category}"] directory_fmt = ["{category}"]
filename_fmt = "{filename}" filename_fmt = "{filename}"
pattern = [r"(?:https?://)?(?:www\.)?chronos\.to/([a-z0-9]{12})"] pattern = [r"(?:https?://)?(?:www\.)?chronos\.to/([a-z0-9]{12})"]

@ -6,7 +6,7 @@
# it under the terms of the GNU General Public License version 2 as # it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation. # published by the Free Software Foundation.
"""Extract image-urls from https://danbooru.donmai.us/""" """Extract images from https://danbooru.donmai.us/"""
from . import booru from . import booru
@ -16,7 +16,7 @@ class DanbooruExtractor(booru.JSONBooruExtractor):
api_url = "https://danbooru.donmai.us/posts.json" api_url = "https://danbooru.donmai.us/posts.json"
class DanbooruTagExtractor(DanbooruExtractor, booru.BooruTagExtractor): class DanbooruTagExtractor(DanbooruExtractor, booru.BooruTagExtractor):
"""Extract images from danbooru based on search-tags""" """Extractor for images from danbooru based on search-tags"""
subcategory = "tag" subcategory = "tag"
pattern = [(r"(?:https?://)?(?:www\.)?danbooru.donmai.us/posts" pattern = [(r"(?:https?://)?(?:www\.)?danbooru.donmai.us/posts"
r"\?(?:utf8=%E2%9C%93&)?tags=([^&]+)")] r"\?(?:utf8=%E2%9C%93&)?tags=([^&]+)")]
@ -26,7 +26,7 @@ class DanbooruTagExtractor(DanbooruExtractor, booru.BooruTagExtractor):
})] })]
class DanbooruPoolExtractor(DanbooruExtractor, booru.BooruPoolExtractor): class DanbooruPoolExtractor(DanbooruExtractor, booru.BooruPoolExtractor):
"""Extract image-pools from danbooru""" """Extractor for image-pools from danbooru"""
subcategory = "pool" subcategory = "pool"
pattern = [r"(?:https?://)?(?:www\.)?danbooru.donmai.us/pools/(\d+)"] pattern = [r"(?:https?://)?(?:www\.)?danbooru.donmai.us/pools/(\d+)"]
test = [("https://danbooru.donmai.us/pools/7659", { test = [("https://danbooru.donmai.us/pools/7659", {
@ -35,7 +35,7 @@ class DanbooruPoolExtractor(DanbooruExtractor, booru.BooruPoolExtractor):
})] })]
class DanbooruPostExtractor(DanbooruExtractor, booru.BooruPostExtractor): class DanbooruPostExtractor(DanbooruExtractor, booru.BooruPostExtractor):
"""Extract single images from danbooru""" """Extractor for single images from danbooru"""
subcategory = "post" subcategory = "post"
pattern = [r"(?:https?://)?(?:www\.)?danbooru.donmai.us/posts/(\d+)"] pattern = [r"(?:https?://)?(?:www\.)?danbooru.donmai.us/posts/(\d+)"]
test = [("https://danbooru.donmai.us/posts/294929", { test = [("https://danbooru.donmai.us/posts/294929", {

@ -12,8 +12,8 @@ from .common import Extractor, AsynchronousExtractor, Message
from .. import text from .. import text
import re import re
class DeviantArtUserExtractor(AsynchronousExtractor): class DeviantartUserExtractor(AsynchronousExtractor):
"""Extract all works of an artist on deviantart""" """Extractor for all works from an artist on deviantart.com"""
category = "deviantart" category = "deviantart"
subcategory = "user" subcategory = "user"
directory_fmt = ["{category}", "{artist}"] directory_fmt = ["{category}", "{artist}"]
@ -99,8 +99,8 @@ class DeviantArtUserExtractor(AsynchronousExtractor):
return re.match(pattern, txt) return re.match(pattern, txt)
class DeviantArtImageExtractor(Extractor): class DeviantartImageExtractor(Extractor):
"""Extract a single image from deviantart""" """Extractor for single images from deviantart.com"""
category = "deviantart" category = "deviantart"
subcategory = "image" subcategory = "image"
directory_fmt = ["{category}", "{artist}"] directory_fmt = ["{category}", "{artist}"]

@ -13,8 +13,9 @@ from .. import text
import re import re
class DoujinmodeChapterExtractor(Extractor): class DoujinmodeChapterExtractor(Extractor):
"""Extractor for manga-/doujinshi-chapters from doujinmode.net"""
category = "doujinmode" category = "doujinmode"
subcategory = "chapter"
directory_fmt = ["{category}", "{title}"] directory_fmt = ["{category}", "{title}"]
filename_fmt = "{num:>03}.{extension}" filename_fmt = "{num:>03}.{extension}"
pattern = [(r"(?:https?://)?(?:www\.)?doujinmode\.net/" pattern = [(r"(?:https?://)?(?:www\.)?doujinmode\.net/"

@ -6,7 +6,7 @@
# it under the terms of the GNU General Public License version 2 as # it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation. # published by the Free Software Foundation.
"""Extract image-urls from https://e621.net/""" """Extract images from https://e621.net/"""
from . import booru from . import booru
@ -16,7 +16,7 @@ class E621Extractor(booru.JSONBooruExtractor):
api_url = "https://e621.net/post/index.json" api_url = "https://e621.net/post/index.json"
class E621TagExtractor(E621Extractor, booru.BooruTagExtractor): class E621TagExtractor(E621Extractor, booru.BooruTagExtractor):
"""Extract images from e621 based on search-tags""" """Extractor for images from e621.net based on search-tags"""
subcategory = "tag" subcategory = "tag"
pattern = [ pattern = [
r"(?:https?://)?(?:www\.)?e621\.net/post/index/\d+/([^?]+)", r"(?:https?://)?(?:www\.)?e621\.net/post/index/\d+/([^?]+)",
@ -28,7 +28,7 @@ class E621TagExtractor(E621Extractor, booru.BooruTagExtractor):
})] })]
class E621PoolExtractor(E621Extractor, booru.BooruPoolExtractor): class E621PoolExtractor(E621Extractor, booru.BooruPoolExtractor):
"""Extract image-pools from e621""" """Extractor for image-pools from e621.net"""
subcategory = "pool" subcategory = "pool"
pattern = [r"(?:https?://)?(?:www\.)?e621\.net/pool/show/(\d+)"] pattern = [r"(?:https?://)?(?:www\.)?e621\.net/pool/show/(\d+)"]
test = [("https://e621.net/pool/show/73", { test = [("https://e621.net/pool/show/73", {
@ -37,7 +37,7 @@ class E621PoolExtractor(E621Extractor, booru.BooruPoolExtractor):
})] })]
class E621PostExtractor(E621Extractor, booru.BooruPostExtractor): class E621PostExtractor(E621Extractor, booru.BooruPostExtractor):
"""Extract single images from e621""" """Extractor for single images from e621.net"""
subcategory = "post" subcategory = "post"
pattern = [r"(?:https?://)?(?:www\.)?e621\.net/post/show/(\d+)"] pattern = [r"(?:https?://)?(?:www\.)?e621\.net/post/show/(\d+)"]
test = [("https://e621.net/post/show/535", { test = [("https://e621.net/post/show/535", {

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright 2014, 2015 Mike Fährmann # Copyright 2014-2016 Mike Fährmann
# #
# This program is free software; you can redistribute it and/or modify # 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 # it under the terms of the GNU General Public License version 2 as
@ -14,9 +14,10 @@ from ..cache import cache
import time import time
import random import random
class ExhentaiExtractor(Extractor): class ExhentaiGalleryExtractor(Extractor):
"""Extractor for image-galleries from exhentai.org"""
category = "exhentai" category = "exhentai"
subcategory = "gallery"
directory_fmt = ["{category}", "{gallery-id}"] directory_fmt = ["{category}", "{gallery-id}"]
filename_fmt = "{gallery-id}_{num:>04}_{imgkey}_{name}.{extension}" filename_fmt = "{gallery-id}_{num:>04}_{imgkey}_{name}.{extension}"
pattern = [r"(?:https?://)?(g\.e-|ex)hentai\.org/g/(\d+)/([\da-f]{10})"] pattern = [r"(?:https?://)?(g\.e-|ex)hentai\.org/g/(\d+)/([\da-f]{10})"]

@ -6,7 +6,7 @@
# it under the terms of the GNU General Public License version 2 as # it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation. # published by the Free Software Foundation.
"""Extract image-urls from http://gelbooru.com/""" """Extract images from http://gelbooru.com/"""
from . import booru from . import booru
from .. import config from .. import config
@ -33,7 +33,7 @@ class GelbooruExtractor(booru.XMLBooruExtractor):
self.params["pid"] = 0 self.params["pid"] = 0
class GelbooruTagExtractor(GelbooruExtractor, booru.BooruTagExtractor): class GelbooruTagExtractor(GelbooruExtractor, booru.BooruTagExtractor):
"""Extract images from gelbooru based on search-tags""" """Extractor for images from gelbooru.com based on search-tags"""
subcategory = "tag" subcategory = "tag"
pattern = [(r"(?:https?://)?(?:www\.)?gelbooru\.com/(?:index\.php)?" pattern = [(r"(?:https?://)?(?:www\.)?gelbooru\.com/(?:index\.php)?"
r"\?page=post&s=list&tags=([^&]+)")] r"\?page=post&s=list&tags=([^&]+)")]
@ -43,12 +43,12 @@ class GelbooruTagExtractor(GelbooruExtractor, booru.BooruTagExtractor):
# TODO: find out how to access pools via gelbooru-api # TODO: find out how to access pools via gelbooru-api
# class GelbooruPoolExtractor(GelbooruExtractor, booru.BooruPoolExtractor): # class GelbooruPoolExtractor(GelbooruExtractor, booru.BooruPoolExtractor):
# """Extract image-pools from gelbooru""" # """Extractor for image-pools from gelbooru.com"""
# subcategory = "pool" # subcategory = "pool"
# pattern = [r"(?:https?://)?(?:www\.)?gelbooru\.com/(?:index\.php)?\?page=pool&s=show&id=(\d+)"] # pattern = [r"(?:https?://)?(?:www\.)?gelbooru\.com/(?:index\.php)?\?page=pool&s=show&id=(\d+)"]
class GelbooruPostExtractor(GelbooruExtractor, booru.BooruPostExtractor): class GelbooruPostExtractor(GelbooruExtractor, booru.BooruPostExtractor):
"""Extract single images from gelbooru""" """Extractor for single images from gelbooru.com"""
subcategory = "post" subcategory = "post"
pattern = [(r"(?:https?://)?(?:www\.)?gelbooru\.com/(?:index\.php)?" pattern = [(r"(?:https?://)?(?:www\.)?gelbooru\.com/(?:index\.php)?"
r"\?page=post&s=view&id=(\d+)")] r"\?page=post&s=view&id=(\d+)")]

@ -13,8 +13,8 @@ from .. import text
import json import json
import re import re
class Hentai2ReadMangaExtractor(Extractor): class Hentai2readMangaExtractor(Extractor):
"""Extractor for mangas from hentai2read.com"""
category = "hentai2read" category = "hentai2read"
subcategory = "manga" subcategory = "manga"
pattern = [r"(?:https?://)?(?:www\.)?hentai2read\.com/([^/]+)/?$"] pattern = [r"(?:https?://)?(?:www\.)?hentai2read\.com/([^/]+)/?$"]
@ -45,8 +45,8 @@ class Hentai2ReadMangaExtractor(Extractor):
text.extract_iter(page, needle, '"') text.extract_iter(page, needle, '"')
)) ))
class Hentai2ReadChapterExtractor(Extractor): class Hentai2readChapterExtractor(Extractor):
"""Extractor for a single manga chapter from hentai2read.com"""
category = "hentai2read" category = "hentai2read"
subcategory = "chapter" subcategory = "chapter"
directory_fmt = ["{category}", "{gallery-id} {title}"] directory_fmt = ["{category}", "{gallery-id} {title}"]

@ -12,7 +12,7 @@ from .common import Extractor, Message
from .. import text, iso639_1 from .. import text, iso639_1
class HentaiboxChapterExtractor(Extractor): class HentaiboxChapterExtractor(Extractor):
"""Extractor for a single manga chapter from hentaibox.net"""
category = "hentaibox" category = "hentaibox"
subcategory = "chapter" subcategory = "chapter"
directory_fmt = ["{category}", "{series}", "{title}"] directory_fmt = ["{category}", "{series}", "{title}"]

@ -11,8 +11,8 @@
from .common import Extractor, Message from .common import Extractor, Message
from .. import text from .. import text
class HentaiFoundryUserExtractor(Extractor): class HentaifoundryUserExtractor(Extractor):
"""Extract all pictures of a hentaifoundry-user""" """Extractor for all images of a hentai-foundry-user"""
category = "hentaifoundry" category = "hentaifoundry"
subcategory = "user" subcategory = "user"
directory_fmt = ["{category}", "{artist}"] directory_fmt = ["{category}", "{artist}"]
@ -105,8 +105,8 @@ class HentaiFoundryUserExtractor(Extractor):
method="post", data=formdata) method="post", data=formdata)
class HentaiFoundryImageExtractor(Extractor): class HentaifoundryImageExtractor(Extractor):
"""Extract a single hentaifoundry picture""" """Extractor for a single image from hentaifoundry.com"""
category = "hentaifoundry" category = "hentaifoundry"
subcategory = "image" subcategory = "image"
directory_fmt = ["{category}", "{artist}"] directory_fmt = ["{category}", "{artist}"]

@ -12,9 +12,10 @@ from .common import Extractor, Message
from .. import text, iso639_1 from .. import text, iso639_1
import string import string
class HitomiExtractor(Extractor): class HitomiGalleryExtractor(Extractor):
"""Extractor for image galleries from hitomi.la"""
category = "hitomi" category = "hitomi"
subcategory = "gallery"
directory_fmt = ["{category}", "{gallery-id} {title}"] directory_fmt = ["{category}", "{gallery-id} {title}"]
filename_fmt = "{category}_{gallery-id}_{num:>03}_{name}.{extension}" filename_fmt = "{category}_{gallery-id}_{num:>03}_{name}.{extension}"
pattern = [r"(?:https?://)?hitomi\.la/(?:galleries|reader)/(\d+)\.html"] pattern = [r"(?:https?://)?hitomi\.la/(?:galleries|reader)/(\d+)\.html"]

@ -12,7 +12,7 @@ from .common import Extractor, AsynchronousExtractor, Message
from .. import text from .. import text
class ImagebamGalleryExtractor(AsynchronousExtractor): class ImagebamGalleryExtractor(AsynchronousExtractor):
"""Extractor for image galleries from imagebam.com"""
category = "imagebam" category = "imagebam"
subcategory = "gallery" subcategory = "gallery"
directory_fmt = ["{category}", "{title} - {gallery-key}"] directory_fmt = ["{category}", "{title} - {gallery-key}"]
@ -57,6 +57,7 @@ class ImagebamGalleryExtractor(AsynchronousExtractor):
return data return data
def get_images(self, url): def get_images(self, url):
"""Yield all image-urls and -ids for a gallery"""
done = False done = False
while not done: while not done:
page = self.request(self.url_base + url).text page = self.request(self.url_base + url).text
@ -72,7 +73,7 @@ class ImagebamGalleryExtractor(AsynchronousExtractor):
class ImagebamImageExtractor(Extractor): class ImagebamImageExtractor(Extractor):
"""Extractor for single images from imagebam.com"""
category = "imagebam" category = "imagebam"
subcategory = "image" subcategory = "image"
directory_fmt = ["{category}"] directory_fmt = ["{category}"]

@ -13,7 +13,7 @@ from .. import text
import json import json
class ImagefapGalleryExtractor(Extractor): class ImagefapGalleryExtractor(Extractor):
"""Extract all images from a gallery at imagefap.com""" """Extractor for image galleries from imagefap.com"""
category = "imagefap" category = "imagefap"
subcategory = "gallery" subcategory = "gallery"
directory_fmt = ["{category}", "{gallery-id} {title}"] directory_fmt = ["{category}", "{gallery-id} {title}"]
@ -29,6 +29,7 @@ class ImagefapGalleryExtractor(Extractor):
def __init__(self, match): def __init__(self, match):
Extractor.__init__(self) Extractor.__init__(self)
self.gid = match.group(1) self.gid = match.group(1)
self.image_id = ""
def items(self): def items(self):
url = "http://www.imagefap.com/pictures/" + self.gid + "/" url = "http://www.imagefap.com/pictures/" + self.gid + "/"
@ -60,7 +61,7 @@ class ImagefapGalleryExtractor(Extractor):
while True: while True:
pos = 0 pos = 0
page = self.request(url, params=params).text page = self.request(url, params=params).text
for i in range(24): for _ in range(24):
imgurl, pos = text.extract(page, '<a href="', '"', pos) imgurl, pos = text.extract(page, '<a href="', '"', pos)
num += 1 num += 1
_, imgid, name = imgurl.rsplit("/", 2) _, imgid, name = imgurl.rsplit("/", 2)
@ -73,7 +74,7 @@ class ImagefapGalleryExtractor(Extractor):
class ImagefapImageExtractor(Extractor): class ImagefapImageExtractor(Extractor):
"""Extract a single image from imagefap.com""" """Extractor for single images from imagefap.com"""
category = "imagefap" category = "imagefap"
subcategory = "image" subcategory = "image"
directory_fmt = ["{category}", "{gallery-id} {title}"] directory_fmt = ["{category}", "{gallery-id} {title}"]
@ -125,7 +126,7 @@ class ImagefapImageExtractor(Extractor):
class ImagefapUserExtractor(Extractor): class ImagefapUserExtractor(Extractor):
"""Extract all images from all galleries from a user at imagefap.com""" """Extractor for all galleries from a user at imagefap.com"""
category = "imagefap" category = "imagefap"
subcategory = "user" subcategory = "user"
directory_fmt = ["{category}", "{gallery-id} {title}"] directory_fmt = ["{category}", "{gallery-id} {title}"]

@ -11,9 +11,10 @@
from .common import Extractor, Message from .common import Extractor, Message
from .. import text from .. import text
class ImagetwistExtractor(Extractor): class ImagetwistImageExtractor(Extractor):
"""Extractor for single images from imagetwist.com"""
category = "imagetwist" category = "imagetwist"
subcategory = "image"
directory_fmt = ["{category}"] directory_fmt = ["{category}"]
filename_fmt = "{category}_{user}_{filename}" filename_fmt = "{category}_{user}_{filename}"
pattern = [r"(?:https?://)?(?:www\.)?imagetwist\.com/([a-z0-9]{12})"] pattern = [r"(?:https?://)?(?:www\.)?imagetwist\.com/([a-z0-9]{12})"]

@ -13,8 +13,9 @@ from .. import text
import re import re
class ImgboxGalleryExtractor(AsynchronousExtractor): class ImgboxGalleryExtractor(AsynchronousExtractor):
"""Extract image galleries from imgbox""" """Extractor for image galleries from imgbox.com"""
category = "imgbox" category = "imgbox"
subcategory = "gallery"
directory_fmt = ["{category}", "{title} - {gallery-key}"] directory_fmt = ["{category}", "{title} - {gallery-key}"]
filename_fmt = "{num:>03}-{name}" filename_fmt = "{num:>03}-{name}"
pattern = [r"(?:https?://)?(?:www\.)?imgbox\.com/g/([A-Za-z0-9]{10})"] pattern = [r"(?:https?://)?(?:www\.)?imgbox\.com/g/([A-Za-z0-9]{10})"]
@ -63,8 +64,9 @@ class ImgboxGalleryExtractor(AsynchronousExtractor):
class ImgboxImageExtractor(Extractor): class ImgboxImageExtractor(Extractor):
"""Extract a single image from imgbox""" """Extractor for single images from imgbox.com"""
category = "imgbox" category = "imgbox"
subcategory = "image"
directory_fmt = ["{category}"] directory_fmt = ["{category}"]
filename_fmt = "{filename}" filename_fmt = "{filename}"
pattern = [r"(?:https?://)?(?:www\.)?imgbox\.com/([A-Za-z0-9]{8})"] pattern = [r"(?:https?://)?(?:www\.)?imgbox\.com/([A-Za-z0-9]{8})"]

@ -14,6 +14,7 @@ from .. import text
class ImgcandyImageExtractor(Extractor): class ImgcandyImageExtractor(Extractor):
"""Extractor for single images from imgcandy.net""" """Extractor for single images from imgcandy.net"""
category = "imgcandy" category = "imgcandy"
subcategory = "image"
directory_fmt = ["{category}"] directory_fmt = ["{category}"]
filename_fmt = "{filename}" filename_fmt = "{filename}"
pattern = [(r"(?:https?://)?(?:www\.)?imgcandy\.net/img-([a-z0-9]+)" pattern = [(r"(?:https?://)?(?:www\.)?imgcandy\.net/img-([a-z0-9]+)"

@ -12,8 +12,9 @@ from .common import Extractor, Message
from .. import text from .. import text
class ImgthGalleryExtractor(Extractor): class ImgthGalleryExtractor(Extractor):
"""Extract all images of a gallery""" """Extractor for image galleries from imgth.com"""
category = "imgth" category = "imgth"
subcategory = "gallery"
directory_fmt = ["{category}", "{gallery-id} {title}"] directory_fmt = ["{category}", "{gallery-id} {title}"]
filename_fmt = "{category}_{gallery-id}_{num:>03}.{extension}" filename_fmt = "{category}_{gallery-id}_{num:>03}.{extension}"
pattern = [r"(?:https?://)?imgth\.com/gallery/(\d+)"] pattern = [r"(?:https?://)?imgth\.com/gallery/(\d+)"]

@ -14,6 +14,7 @@ from .. import text
class ImgtrexImageExtractor(Extractor): class ImgtrexImageExtractor(Extractor):
"""Extractor for single images from imgtrex.com""" """Extractor for single images from imgtrex.com"""
category = "imgtrex" category = "imgtrex"
subcategory = "image"
directory_fmt = ["{category}"] directory_fmt = ["{category}"]
filename_fmt = "{filename}" filename_fmt = "{filename}"
pattern = [r"(?:https?://)?(?:www\.)?imgtrex\.com/([^/]+)"] pattern = [r"(?:https?://)?(?:www\.)?imgtrex\.com/([^/]+)"]

@ -14,7 +14,7 @@ from urllib.parse import urljoin
import os.path import os.path
class ImgurAlbumExtractor(Extractor): class ImgurAlbumExtractor(Extractor):
"""Extract albums from imgur""" """Extractor for image albums from imgur.com"""
category = "imgur" category = "imgur"
subcategory = "album" subcategory = "album"
directory_fmt = ["{category}", "{album-key} - {title}"] directory_fmt = ["{category}", "{album-key} - {title}"]

@ -15,6 +15,7 @@ from os.path import splitext
class ImgytImageExtractor(Extractor): class ImgytImageExtractor(Extractor):
"""Extractor for single images from img.yt""" """Extractor for single images from img.yt"""
category = "imgyt" category = "imgyt"
subcategory = "image"
directory_fmt = ["{category}"] directory_fmt = ["{category}"]
filename_fmt = "{filename}" filename_fmt = "{filename}"
pattern = [r"(?:https?://)?(?:www\.)?img\.yt/img-([a-z0-9]+)\.html"] pattern = [r"(?:https?://)?(?:www\.)?img\.yt/img-([a-z0-9]+)\.html"]

@ -6,14 +6,15 @@
# it under the terms of the GNU General Public License version 2 as # it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation. # published by the Free Software Foundation.
"""Extract images from https://nijie.info/""" """Extract soundtracks from https://khinsider.com/"""
from .common import AsynchronousExtractor, Message from .common import AsynchronousExtractor, Message
from .. import text from .. import text
class KhinsiderExtractor(AsynchronousExtractor): class KhinsiderSoundtrackExtractor(AsynchronousExtractor):
"""Extractor for soundtracks from khinsider.com"""
category = "khinsider" category = "khinsider"
subcategory = "soundtrack"
directory_fmt = ["{category}", "{album}"] directory_fmt = ["{category}", "{album}"]
filename_fmt = "{filename}" filename_fmt = "{filename}"
pattern = [r"(?:https?://)?downloads\.khinsider\.com/game-soundtracks/album/(.+)"] pattern = [r"(?:https?://)?downloads\.khinsider\.com/game-soundtracks/album/(.+)"]

@ -25,7 +25,7 @@ class KissmangaExtractor(Extractor):
class KissmangaMangaExtractor(KissmangaExtractor): class KissmangaMangaExtractor(KissmangaExtractor):
"""Extract all manga-chapters from kissmanga""" """Extractor for mangas from kissmanga.com"""
subcategory = "manga" subcategory = "manga"
pattern = [r"(?:https?://)?(?:www\.)?kissmanga\.com/Manga/[^/]+/?$"] pattern = [r"(?:https?://)?(?:www\.)?kissmanga\.com/Manga/[^/]+/?$"]
test = [("http://kissmanga.com/Manga/Dropout", { test = [("http://kissmanga.com/Manga/Dropout", {
@ -47,7 +47,7 @@ class KissmangaMangaExtractor(KissmangaExtractor):
class KissmangaChapterExtractor(KissmangaExtractor): class KissmangaChapterExtractor(KissmangaExtractor):
"""Extract a single manga-chapter from kissmanga""" """Extractor for manga-chapters from kissmanga.com"""
subcategory = "chapter" subcategory = "chapter"
pattern = [r"(?:https?://)?(?:www\.)?kissmanga\.com/Manga/.+/.+\?id=\d+"] pattern = [r"(?:https?://)?(?:www\.)?kissmanga\.com/Manga/.+/.+\?id=\d+"]
test = [ test = [

@ -6,7 +6,7 @@
# it under the terms of the GNU General Public License version 2 as # it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation. # published by the Free Software Foundation.
"""Extract image-urls from https://konachan.com/""" """Extract images from https://konachan.com/"""
from . import booru from . import booru
@ -16,7 +16,7 @@ class KonachanExtractor(booru.JSONBooruExtractor):
api_url = "https://konachan.com/post.json" api_url = "https://konachan.com/post.json"
class KonachanTagExtractor(KonachanExtractor, booru.BooruTagExtractor): class KonachanTagExtractor(KonachanExtractor, booru.BooruTagExtractor):
"""Extract images from konachan based on search-tags""" """Extractor for images from konachan.com based on search-tags"""
subcategory = "tag" subcategory = "tag"
pattern = [r"(?:https?://)?(?:www\.)?konachan\.com/post\?tags=([^&]+)"] pattern = [r"(?:https?://)?(?:www\.)?konachan\.com/post\?tags=([^&]+)"]
test = [("http://konachan.com/post?tags=patata", { test = [("http://konachan.com/post?tags=patata", {
@ -24,7 +24,7 @@ class KonachanTagExtractor(KonachanExtractor, booru.BooruTagExtractor):
})] })]
class KonachanPoolExtractor(KonachanExtractor, booru.BooruPoolExtractor): class KonachanPoolExtractor(KonachanExtractor, booru.BooruPoolExtractor):
"""Extract image-pools from konachan""" """Extractor for image-pools from konachan.com"""
subcategory = "pool" subcategory = "pool"
pattern = [r"(?:https?://)?(?:www\.)?konachan\.com/pool/show/(\d+)"] pattern = [r"(?:https?://)?(?:www\.)?konachan\.com/pool/show/(\d+)"]
test = [("http://konachan.com/pool/show/95", { test = [("http://konachan.com/pool/show/95", {
@ -32,7 +32,7 @@ class KonachanPoolExtractor(KonachanExtractor, booru.BooruPoolExtractor):
})] })]
class KonachanPostExtractor(KonachanExtractor, booru.BooruPostExtractor): class KonachanPostExtractor(KonachanExtractor, booru.BooruPostExtractor):
"""Extract single images from konachan""" """Extractor for single images from konachan.com"""
subcategory = "post" subcategory = "post"
pattern = [r"(?:https?://)?(?:www\.)?konachan\.com/post/show/(\d+)"] pattern = [r"(?:https?://)?(?:www\.)?konachan\.com/post/show/(\d+)"]
test = [("http://konachan.com/post/show/205189", { test = [("http://konachan.com/post/show/205189", {

@ -12,9 +12,10 @@ from .common import Extractor, Message
from .. import text, iso639_1 from .. import text, iso639_1
from urllib.parse import urljoin from urllib.parse import urljoin
class LusciousExtractor(Extractor): class LusciousAlbumExtractor(Extractor):
"""Extractor for image albums from luscious.net"""
category = "luscious" category = "luscious"
subcategory = "album"
directory_fmt = ["{category}", "{gallery-id} {title}"] directory_fmt = ["{category}", "{gallery-id} {title}"]
filename_fmt = "{category}_{gallery-id}_{num:>03}.{extension}" filename_fmt = "{category}_{gallery-id}_{num:>03}.{extension}"
pattern = [(r"(?:https?://)?(?:www\.)?luscious\.net/c/([^/]+)/" pattern = [(r"(?:https?://)?(?:www\.)?luscious\.net/c/([^/]+)/"

@ -6,14 +6,14 @@
# it under the terms of the GNU General Public License version 2 as # it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation. # published by the Free Software Foundation.
"""Extract manga-chapters and entire manga from from http://www.mangahere.co/""" """Extract manga-chapters and entire manga from http://www.mangahere.co/"""
from .common import Extractor, AsynchronousExtractor, Message from .common import Extractor, AsynchronousExtractor, Message
from .. import text from .. import text
import re import re
class MangaHereMangaExtractor(Extractor): class MangahereMangaExtractor(Extractor):
"""Extract all manga-chapters from mangahere""" """Extractor for mangas from mangahere.co"""
category = "mangahere" category = "mangahere"
subcategory = "manga" subcategory = "manga"
pattern = [r"(?:https?://)?(?:www\.)?mangahere\.co/manga/([^/]+)/?$"] pattern = [r"(?:https?://)?(?:www\.)?mangahere\.co/manga/([^/]+)/?$"]
@ -39,8 +39,8 @@ class MangaHereMangaExtractor(Extractor):
)) ))
class MangaHereChapterExtractor(AsynchronousExtractor): class MangahereChapterExtractor(AsynchronousExtractor):
"""Extract a single manga-chapter from mangahere""" """Extractor for manga-chapters from mangahere.co"""
category = "mangahere" category = "mangahere"
subcategory = "chapter" subcategory = "chapter"
directory_fmt = ["{category}", "{manga}", "c{chapter:>03}{chapter-minor}"] directory_fmt = ["{category}", "{manga}", "c{chapter:>03}{chapter-minor}"]

@ -12,8 +12,8 @@ from .common import Extractor, Message
from .. import text from .. import text
import re import re
class MangaMintMangaExtractor(Extractor): class MangamintMangaExtractor(Extractor):
"""Extract all manga-chapters from mangamint""" """Extractor for mangas from mangamint.com"""
category = "mangamint" category = "mangamint"
subcategory = "manga" subcategory = "manga"
pattern = [r"(?:https?://)?(?:www\.)?mangamint\.com(/manga/[^\?]+-manga)"] pattern = [r"(?:https?://)?(?:www\.)?mangamint\.com(/manga/[^\?]+-manga)"]
@ -46,8 +46,8 @@ class MangaMintMangaExtractor(Extractor):
return reversed(chapters) return reversed(chapters)
class MangaMintChapterExtractor(Extractor): class MangamintChapterExtractor(Extractor):
"""Extract a single manga-chapter from mangamint""" """Extractor for manga-chapters from mangamint.com"""
category = "mangamint" category = "mangamint"
subcategory = "chapter" subcategory = "chapter"
directory_fmt = ["{category}", "{manga}", "c{chapter:>03}{chapter-minor}"] directory_fmt = ["{category}", "{manga}", "c{chapter:>03}{chapter-minor}"]

@ -8,24 +8,24 @@
"""Extract manga-chapters and entire manga from http://www.mangapanda.com/""" """Extract manga-chapters and entire manga from http://www.mangapanda.com/"""
from .mangareader import MangaReaderMangaExtractor, MangaReaderChapterExtractor from .mangareader import MangareaderMangaExtractor, MangareaderChapterExtractor
class MangaPandaBase(): class MangapandaBase():
"""Base class for mangapanda extractors""" """Base class for mangapanda extractors"""
category = "mangapanda" category = "mangapanda"
url_base = "http://www.mangapanda.com" url_base = "http://www.mangapanda.com"
class MangaPandaMangaExtractor(MangaPandaBase, MangaReaderMangaExtractor): class MangapandaMangaExtractor(MangapandaBase, MangareaderMangaExtractor):
"""Extract all manga-chapters from mangapanda""" """Extractor for mangas from mangapanda.com"""
subcategory = "manga" subcategory = "manga"
pattern = [r"(?:https?://)?(?:www\.)?mangapanda\.com(/[^/]+)$"] pattern = [r"(?:https?://)?(?:www\.)?mangapanda\.com(/[^/]+)$"]
test = [("http://www.mangapanda.com/mushishi", { test = [("http://www.mangapanda.com/mushishi", {
"url": "50a1ba730b85426b904da256c80f68ba6a8a2566", "url": "50a1ba730b85426b904da256c80f68ba6a8a2566",
})] })]
class MangaPandaChapterExtractor(MangaPandaBase, MangaReaderChapterExtractor): class MangapandaChapterExtractor(MangapandaBase, MangareaderChapterExtractor):
"""Extract a single manga-chapter from mangapanda""" """Extractor for manga-chapters from mangapanda.com"""
subcategory = "chapter" subcategory = "chapter"
pattern = [ pattern = [
r"(?:https?://)?(?:www\.)?mangapanda\.com((/[^/]+)/(\d+))", r"(?:https?://)?(?:www\.)?mangapanda\.com((/[^/]+)/(\d+))",

@ -12,7 +12,7 @@ from .common import Extractor, Message
from .. import text from .. import text
class MangaparkMangaExtractor(Extractor): class MangaparkMangaExtractor(Extractor):
"""Extract all chapters of a manga from mangapark""" """Extractor for mangas from mangapark.me"""
category = "mangapark" category = "mangapark"
subcategory = "manga" subcategory = "manga"
pattern = [r"(?:https?://)?(?:www\.)?mangapark\.me/manga/([^/]+)$"] pattern = [r"(?:https?://)?(?:www\.)?mangapark\.me/manga/([^/]+)$"]
@ -41,7 +41,7 @@ class MangaparkMangaExtractor(Extractor):
class MangaparkChapterExtractor(Extractor): class MangaparkChapterExtractor(Extractor):
"""Extract a single manga-chapter from mangapark""" """Extractor for manga-chapters from mangapark.me"""
category = "mangapark" category = "mangapark"
subcategory = "chapter" subcategory = "chapter"
directory_fmt = ["{category}", "{manga}", "c{chapter:>03}{chapter-minor}"] directory_fmt = ["{category}", "{manga}", "c{chapter:>03}{chapter-minor}"]

@ -11,7 +11,7 @@
from .common import AsynchronousExtractor, Extractor, Message from .common import AsynchronousExtractor, Extractor, Message
from .. import text from .. import text
class MangaReaderBase(): class MangareaderBase():
"""Base class for mangareader extractors""" """Base class for mangareader extractors"""
category = "mangareader" category = "mangareader"
directory_fmt = ["{category}", "{manga}", "c{chapter:>03} - {title}"] directory_fmt = ["{category}", "{manga}", "c{chapter:>03} - {title}"]
@ -19,8 +19,8 @@ class MangaReaderBase():
url_base = "http://www.mangareader.net" url_base = "http://www.mangareader.net"
class MangaReaderMangaExtractor(MangaReaderBase, Extractor): class MangareaderMangaExtractor(MangareaderBase, Extractor):
"""Extract all manga-chapters from mangareader""" """Extractor for mangas from mangareader.net"""
subcategory = "manga" subcategory = "manga"
pattern = [r"(?:https?://)?(?:www\.)?mangareader\.net(/[^/]+)$"] pattern = [r"(?:https?://)?(?:www\.)?mangareader\.net(/[^/]+)$"]
test = [("http://www.mangareader.net/mushishi", { test = [("http://www.mangareader.net/mushishi", {
@ -41,8 +41,8 @@ class MangaReaderMangaExtractor(MangaReaderBase, Extractor):
yield Message.Queue, url + chapter yield Message.Queue, url + chapter
class MangaReaderChapterExtractor(MangaReaderBase, AsynchronousExtractor): class MangareaderChapterExtractor(MangareaderBase, AsynchronousExtractor):
"""Extract a single manga-chapter from mangareader""" """Extractor for manga-chapters from mangareader.net"""
subcategory = "chapter" subcategory = "chapter"
pattern = [ pattern = [
r"(?:https?://)?(?:www\.)?mangareader\.net((/[^/]+)/(\d+))", r"(?:https?://)?(?:www\.)?mangareader\.net((/[^/]+)/(\d+))",

@ -11,8 +11,8 @@
from .common import Extractor, AsynchronousExtractor, Message from .common import Extractor, AsynchronousExtractor, Message
from .. import text from .. import text
class MangaShareMangaExtractor(Extractor): class MangashareMangaExtractor(Extractor):
"""Extract all manga-chapters from mangashare""" """Extractor for mangas from mangashare.com"""
category = "mangashare" category = "mangashare"
subcategory = "manga" subcategory = "manga"
pattern = [r"(?:https?://)?read\.mangashare\.com/[^/]+$"] pattern = [r"(?:https?://)?read\.mangashare\.com/[^/]+$"]
@ -37,8 +37,8 @@ class MangaShareMangaExtractor(Extractor):
)) ))
class MangaShareChapterExtractor(AsynchronousExtractor): class MangashareChapterExtractor(AsynchronousExtractor):
"""Extract a single manga-chapter from mangashare""" """Extractor for manga-chapters from mangashare.com"""
category = "mangashare" category = "mangashare"
subcategory = "chapter" subcategory = "chapter"
directory_fmt = ["{category}", "{manga}", "c{chapter:>03} - {title}"] directory_fmt = ["{category}", "{manga}", "c{chapter:>03} - {title}"]

@ -6,14 +6,15 @@
# it under the terms of the GNU General Public License version 2 as # it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation. # published by the Free Software Foundation.
"""Extract manga pages from https://www.mangastream.com/""" """Extract manga-chapters from https://www.mangastream.com/"""
from .common import AsynchronousExtractor, Message from .common import AsynchronousExtractor, Message
from .. import text from .. import text
class MangaStreamExtractor(AsynchronousExtractor): class MangastreamChapterExtractor(AsynchronousExtractor):
"""Extractor for manga-chapters from mangastream.com"""
category = "mangastream" category = "mangastream"
subcategory = "chapter"
directory_fmt = ["{category}", "{manga}", "c{chapter} - {title}"] directory_fmt = ["{category}", "{manga}", "c{chapter} - {title}"]
filename_fmt = "{manga}_c{chapter}_{page:>03}.{extension}" filename_fmt = "{manga}_c{chapter}_{page:>03}.{extension}"
pattern = [(r"(?:https?://)?(?:www\.)?(?:readms|mangastream)\.com/" pattern = [(r"(?:https?://)?(?:www\.)?(?:readms|mangastream)\.com/"

@ -12,9 +12,10 @@ from .common import Extractor, Message
from .. import text from .. import text
import json import json
class NhentaiExtractor(Extractor): class NhentaiGalleryExtractor(Extractor):
"""Extractor for image-galleries from nhentai.net"""
category = "nhentai" category = "nhentai"
subcategory = "nijie"
directory_fmt = ["{category}", "{gallery-id} {title}"] directory_fmt = ["{category}", "{gallery-id} {title}"]
filename_fmt = "{category}_{gallery-id}_{num:>03}.{extension}" filename_fmt = "{category}_{gallery-id}_{num:>03}.{extension}"
pattern = [r"(?:https?://)?(?:www\.)?nhentai\.net/g/(\d+)"] pattern = [r"(?:https?://)?(?:www\.)?nhentai\.net/g/(\d+)"]

@ -13,8 +13,9 @@ from .. import config, text, exception
from ..cache import cache from ..cache import cache
class NijieUserExtractor(AsynchronousExtractor): class NijieUserExtractor(AsynchronousExtractor):
"""Extract all works of a single nijie-user""" """Extractor for works of a nijie-user"""
category = "nijie" category = "nijie"
subcategory = "user"
directory_fmt = ["{category}", "{artist-id}"] directory_fmt = ["{category}", "{artist-id}"]
filename_fmt = "{category}_{artist-id}_{image-id}_p{index:>02}.{extension}" filename_fmt = "{category}_{artist-id}_{image-id}_p{index:>02}.{extension}"
pattern = [r"(?:https?://)?(?:www\.)?nijie\.info/members(?:_illust)?\.php\?id=(\d+)"] pattern = [r"(?:https?://)?(?:www\.)?nijie\.info/members(?:_illust)?\.php\?id=(\d+)"]

@ -37,7 +37,7 @@ class PinterestExtractor(Extractor):
class PinterestPinExtractor(PinterestExtractor): class PinterestPinExtractor(PinterestExtractor):
"""Extract an image from a single pin from https://www.pinterest.com""" """Extractor for images from a single pin from pinterest.com"""
subcategory = "pin" subcategory = "pin"
pattern = [r"(?:https?://)?(?:www\.)?pinterest\.com/pin/([^/]+)"] pattern = [r"(?:https?://)?(?:www\.)?pinterest\.com/pin/([^/]+)"]
test = [("https://www.pinterest.com/pin/858146903966145189/", { test = [("https://www.pinterest.com/pin/858146903966145189/", {
@ -59,7 +59,7 @@ class PinterestPinExtractor(PinterestExtractor):
class PinterestBoardExtractor(PinterestExtractor): class PinterestBoardExtractor(PinterestExtractor):
"""Extract an image from a single pin from https://www.pinterest.com""" """Extractor for images from a board from pinterest.com"""
category = "pinterest" category = "pinterest"
subcategory = "board" subcategory = "board"
directory_fmt = ["{category}", "{user}", "{board}"] directory_fmt = ["{category}", "{user}", "{board}"]

@ -15,7 +15,7 @@ import re
import json import json
class PixivUserExtractor(Extractor): class PixivUserExtractor(Extractor):
"""Extract all works of a single pixiv-user""" """Extractor for works of a pixiv-user"""
category = "pixiv" category = "pixiv"
subcategory = "user" subcategory = "user"
directory_fmt = ["{category}", "{artist-id}-{artist-nick}"] directory_fmt = ["{category}", "{artist-id}-{artist-nick}"]
@ -138,7 +138,7 @@ class PixivUserExtractor(Extractor):
class PixivWorkExtractor(PixivUserExtractor): class PixivWorkExtractor(PixivUserExtractor):
"""Extract a single pixiv work/illustration""" """Extractor for a single pixiv work/illustration"""
subcategory = "work" subcategory = "work"
pattern = [(r"(?:https?://)?(?:www\.)?pixiv\.net/member(?:_illust)?\.php" pattern = [(r"(?:https?://)?(?:www\.)?pixiv\.net/member(?:_illust)?\.php"
r"\?(?:[^&]+&)*illust_id=(\d+)"), r"\?(?:[^&]+&)*illust_id=(\d+)"),
@ -171,7 +171,7 @@ class PixivWorkExtractor(PixivUserExtractor):
class PixivFavoriteExtractor(PixivUserExtractor): class PixivFavoriteExtractor(PixivUserExtractor):
"""Extract all favorites/bookmarks of a single pixiv-user""" """Extractor for all favorites/bookmarks of a pixiv-user"""
subcategory = "favorite" subcategory = "favorite"
directory_fmt = ["{category}", "bookmarks", "{artist-id}-{artist-nick}"] directory_fmt = ["{category}", "bookmarks", "{artist-id}-{artist-nick}"]
pattern = [r"(?:https?://)?(?:www\.)?pixiv\.net/bookmark\.php\?id=(\d+)"] pattern = [r"(?:https?://)?(?:www\.)?pixiv\.net/bookmark\.php\?id=(\d+)"]
@ -188,7 +188,7 @@ class PixivFavoriteExtractor(PixivUserExtractor):
class PixivBookmarkExtractor(PixivFavoriteExtractor): class PixivBookmarkExtractor(PixivFavoriteExtractor):
"""Extract all favorites/bookmarks of your own account""" """Extractor for all favorites/bookmarks of your own account"""
subcategory = "bookmark" subcategory = "bookmark"
pattern = [r"(?:https?://)?(?:www\.)?pixiv\.net/bookmark\.php()$"] pattern = [r"(?:https?://)?(?:www\.)?pixiv\.net/bookmark\.php()$"]
test = [] test = []

@ -6,7 +6,7 @@
# it under the terms of the GNU General Public License version 2 as # it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation. # published by the Free Software Foundation.
"""Extract manga pages from http://powermanga.org/""" """Extract manga-chapters from http://powermanga.org/"""
from .common import Extractor, Message from .common import Extractor, Message
from .. import text, iso639_1 from .. import text, iso639_1
@ -14,9 +14,10 @@ import os.path
import json import json
import re import re
class PowerMangaExtractor(Extractor): class PowermangaChapterExtractor(Extractor):
"""Extractor for manga-chapters from powermanga.org"""
category = "powermanga" category = "powermanga"
subcategory = "chapter"
directory_fmt = ["{category}", "{manga}", "c{chapter:>03}{chapter-minor} - {title}"] directory_fmt = ["{category}", "{manga}", "c{chapter:>03}{chapter-minor} - {title}"]
filename_fmt = "{manga}_c{chapter:>03}{chapter-minor}_{page:>03}.{extension}" filename_fmt = "{manga}_c{chapter:>03}{chapter-minor}_{page:>03}.{extension}"
pattern = [ pattern = [

@ -6,7 +6,7 @@
# it under the terms of the GNU General Public License version 2 as # it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation. # published by the Free Software Foundation.
"""Extract image-urls from http://safebooru.org/""" """Extract images from http://safebooru.org/"""
from . import booru from . import booru
@ -26,18 +26,20 @@ class SafebooruExtractor(booru.XMLBooruExtractor):
self.params["pid"] = 0 self.params["pid"] = 0
class SafebooruTagExtractor(SafebooruExtractor, booru.BooruTagExtractor): class SafebooruTagExtractor(SafebooruExtractor, booru.BooruTagExtractor):
"""Extract images from safebooru based on search-tags""" """Extractor for images from safebooru.org based on search-tags"""
subcategory = "tag" subcategory = "tag"
pattern = [r"(?:https?://)?(?:www\.)?safebooru\.org/(?:index\.php)?\?page=post&s=list&tags=([^&]+)"] pattern = [(r"(?:https?://)?(?:www\.)?safebooru\.org/(?:index\.php)?"
r"\?page=post&s=list&tags=([^&]+)")]
test = [("http://safebooru.org/index.php?page=post&s=list&tags=bonocho", { test = [("http://safebooru.org/index.php?page=post&s=list&tags=bonocho", {
"url": "c91e04ffbdf317fae95b2e160c8345503d9fb730", "url": "c91e04ffbdf317fae95b2e160c8345503d9fb730",
"content": "e5ad4c5bf241b1def154958535bef6c2f6b733eb", "content": "e5ad4c5bf241b1def154958535bef6c2f6b733eb",
})] })]
class SafebooruPostExtractor(SafebooruExtractor, booru.BooruPostExtractor): class SafebooruPostExtractor(SafebooruExtractor, booru.BooruPostExtractor):
"""Extract single images from safebooru""" """Extractor for single images from safebooru.org"""
subcategory = "post" subcategory = "post"
pattern = [r"(?:https?://)?(?:www\.)?safebooru\.org/(?:index\.php)?\?page=post&s=view&id=(\d+)"] pattern = [(r"(?:https?://)?(?:www\.)?safebooru\.org/(?:index\.php)?"
r"\?page=post&s=view&id=(\d+)")]
test = [("http://safebooru.org/index.php?page=post&s=view&id=1169132", { test = [("http://safebooru.org/index.php?page=post&s=view&id=1169132", {
"url": "bcb6047665729c7c9db243a27f41cbef9af1ecef", "url": "bcb6047665729c7c9db243a27f41cbef9af1ecef",
"content": "93b293b27dabd198afafabbaf87c49863ac82f27", "content": "93b293b27dabd198afafabbaf87c49863ac82f27",

@ -11,9 +11,10 @@
from .common import AsynchronousExtractor, Message from .common import AsynchronousExtractor, Message
from .. import text from .. import text
class SankakuExtractor(AsynchronousExtractor): class SankakuTagExtractor(AsynchronousExtractor):
"""Extractor for images from chan.sankakucomplex.com based on search-tags"""
category = "sankaku" category = "sankaku"
subcategory = "tag"
directory_fmt = ["{category}", "{tags}"] directory_fmt = ["{category}", "{tags}"]
filename_fmt = "{category}_{id}_{md5}.{extension}" filename_fmt = "{category}_{id}_{md5}.{extension}"
pattern = [r"(?:https?://)?chan\.sankakucomplex\.com/\?tags=([^&]+)"] pattern = [r"(?:https?://)?chan\.sankakucomplex\.com/\?tags=([^&]+)"]

@ -13,14 +13,15 @@ from .. import config, exception
from ..cache import cache from ..cache import cache
class SeigaImageExtractor(Extractor): class SeigaImageExtractor(Extractor):
"""Extract a single image from seiga.nicovideo.jp""" """Extractor for single images from seiga.nicovideo.jp"""
category = "seiga" category = "seiga"
subcategory = "image" subcategory = "image"
directory_fmt = ["{category}"] directory_fmt = ["{category}"]
filename_fmt = "{category}_{image-id}.jpg" filename_fmt = "{category}_{image-id}.jpg"
pattern = [(r"(?:https?://)?(?:www\.|seiga\.)?nicovideo\.jp/" pattern = [(r"(?:https?://)?(?:www\.|seiga\.)?nicovideo\.jp/"
r"(?:seiga/im|image/source/)(\d+)"), r"(?:seiga/im|image/source/)(\d+)"),
r"(?:https?://)?lohas\.nicoseiga\.jp/(?:priv|o)/[^/]+/\d+/(\d+)"] (r"(?:https?://)?lohas\.nicoseiga\.jp/"
r"(?:priv|o)/[^/]+/\d+/(\d+)")]
test = [("http://seiga.nicovideo.jp/seiga/im5977527", { test = [("http://seiga.nicovideo.jp/seiga/im5977527", {
"keyword": "e2ea59186c47beb71484ba35d550cf6511ac185a", "keyword": "e2ea59186c47beb71484ba35d550cf6511ac185a",
"content": "d9202292012178374d57fb0126f6124387265297", "content": "d9202292012178374d57fb0126f6124387265297",

@ -10,10 +10,9 @@
from .common import Extractor, Message from .common import Extractor, Message
from .. import text from .. import text
import re
class SenmangaRawChapterExtractor(Extractor): class SenmangaChapterExtractor(Extractor):
"""Extract a single manga-chapter from raw.senmanga.com""" """Extractor for manga-chapters from raw.senmanga.com"""
category = "senmanga" category = "senmanga"
subcategory = "chapter" subcategory = "chapter"
directory_fmt = ["{category}", "{manga}", "c{chapter:>03}"] directory_fmt = ["{category}", "{manga}", "c{chapter:>03}"]

@ -11,8 +11,8 @@
from .common import Extractor, AsynchronousExtractor, Message from .common import Extractor, AsynchronousExtractor, Message
from .. import text from .. import text
class SpectrumNexusMangaExtractor(Extractor): class SpectrumnexusMangaExtractor(Extractor):
"""Extract all manga-chapters and -volumes from spectrumnexus""" """Extractor for mangas from thespectrum.net"""
category = "spectrumnexus" category = "spectrumnexus"
subcategory = "manga" subcategory = "manga"
pattern = [r"(?:https?://)?view\.thespectrum\.net/series/([^\.]+)\.html$"] pattern = [r"(?:https?://)?view\.thespectrum\.net/series/([^\.]+)\.html$"]
@ -37,8 +37,8 @@ class SpectrumNexusMangaExtractor(Extractor):
return text.extract_iter(page, '<option value="', '"') return text.extract_iter(page, '<option value="', '"')
class SpectrumNexusChapterExtractor(AsynchronousExtractor): class SpectrumnexusChapterExtractor(AsynchronousExtractor):
"""Extract a single manga-chapter or -volume from spectrumnexus""" """Extractor for manga-chapters or -volumes from thespectrum.net"""
category = "spectrumnexus" category = "spectrumnexus"
subcategory = "chapter" subcategory = "chapter"
directory_fmt = ["{category}", "{manga}", "{identifier}"] directory_fmt = ["{category}", "{manga}", "{identifier}"]

@ -13,7 +13,7 @@ from .. import text
import json import json
class TumblrUserExtractor(Extractor): class TumblrUserExtractor(Extractor):
"""Extract all images from a tumblr-user""" """Extractor for all images from a tumblr-user"""
category = "tumblr" category = "tumblr"
subcategory = "user" subcategory = "user"
directory_fmt = ["{category}", "{user}"] directory_fmt = ["{category}", "{user}"]
@ -85,7 +85,7 @@ class TumblrUserExtractor(Extractor):
class TumblrPostExtractor(TumblrUserExtractor): class TumblrPostExtractor(TumblrUserExtractor):
"""Extract images from a single post on tumblr""" """Extractor for images from a single post on tumblr"""
subcategory = "post" subcategory = "post"
pattern = [r"(?:https?://)?([^.]+)\.tumblr\.com/post/(\d+)"] pattern = [r"(?:https?://)?([^.]+)\.tumblr\.com/post/(\d+)"]
test = [("http://demo.tumblr.com/post/459265350", { test = [("http://demo.tumblr.com/post/459265350", {
@ -99,7 +99,7 @@ class TumblrPostExtractor(TumblrUserExtractor):
class TumblrTagExtractor(TumblrUserExtractor): class TumblrTagExtractor(TumblrUserExtractor):
"""Extract images from a tumblr-user by tag""" """Extractor for images from a tumblr-user by tag"""
subcategory = "tag" subcategory = "tag"
pattern = [r"(?:https?://)?([^.]+)\.tumblr\.com/tagged/(.+)"] pattern = [r"(?:https?://)?([^.]+)\.tumblr\.com/tagged/(.+)"]
test = [("http://demo.tumblr.com/tagged/Times Square", { test = [("http://demo.tumblr.com/tagged/Times Square", {

@ -11,9 +11,10 @@
from .common import Extractor, Message from .common import Extractor, Message
from .. import text from .. import text
class TurboimagehostExtractor(Extractor): class TurboimagehostImageExtractor(Extractor):
"""Extractor for single images from turboimagehost.com"""
category = "turboimagehost" category = "turboimagehost"
subcategory = "image"
directory_fmt = ["{category}"] directory_fmt = ["{category}"]
filename_fmt = "{category}_{index}_{filename}" filename_fmt = "{category}_{index}_{filename}"
pattern = [r"(?:https?://)?(?:www\.)?turboimagehost\.com/p/((\d+)/[^/]+\.html)"] pattern = [r"(?:https?://)?(?:www\.)?turboimagehost\.com/p/((\d+)/[^/]+\.html)"]

@ -6,7 +6,7 @@
# it under the terms of the GNU General Public License version 2 as # it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation. # published by the Free Software Foundation.
"""Extract image-urls from https://yande.re/""" """Extract images from https://yande.re/"""
from . import booru from . import booru
@ -16,7 +16,7 @@ class YandereExtractor(booru.JSONBooruExtractor):
api_url = "https://yande.re/post.json" api_url = "https://yande.re/post.json"
class YandereTagExtractor(YandereExtractor, booru.BooruTagExtractor): class YandereTagExtractor(YandereExtractor, booru.BooruTagExtractor):
"""Extract images from yandere based on search-tags""" """Extractor for images from yande.re based on search-tags"""
subcategory = "tag" subcategory = "tag"
pattern = [r"(?:https?://)?(?:www\.)?yande\.re/post\?tags=([^&]+)"] pattern = [r"(?:https?://)?(?:www\.)?yande\.re/post\?tags=([^&]+)"]
test = [("https://yande.re/post?tags=ouzoku armor", { test = [("https://yande.re/post?tags=ouzoku armor", {
@ -24,7 +24,7 @@ class YandereTagExtractor(YandereExtractor, booru.BooruTagExtractor):
})] })]
class YanderePoolExtractor(YandereExtractor, booru.BooruPoolExtractor): class YanderePoolExtractor(YandereExtractor, booru.BooruPoolExtractor):
"""Extract image-pools from yandere""" """Extractor for image-pools from yande.re"""
subcategory = "pool" subcategory = "pool"
pattern = [r"(?:https?://)?(?:www\.)?yande.re/pool/show/(\d+)"] pattern = [r"(?:https?://)?(?:www\.)?yande.re/pool/show/(\d+)"]
test = [("https://yande.re/pool/show/318", { test = [("https://yande.re/pool/show/318", {
@ -32,7 +32,7 @@ class YanderePoolExtractor(YandereExtractor, booru.BooruPoolExtractor):
})] })]
class YanderePostExtractor(YandereExtractor, booru.BooruPostExtractor): class YanderePostExtractor(YandereExtractor, booru.BooruPostExtractor):
"""Extract single images from yandere""" """Extractor for single images from yande.re"""
subcategory = "post" subcategory = "post"
pattern = [r"(?:https?://)?(?:www\.)?yande.re/post/show/(\d+)"] pattern = [r"(?:https?://)?(?:www\.)?yande.re/post/show/(\d+)"]
test = [("https://yande.re/post/show/51824", { test = [("https://yande.re/post/show/51824", {

Loading…
Cancel
Save