Merge pull request #271 from Techwolfy/upstream-new-comics-4

Upstream new comics 4
This commit is contained in:
Tobias Gruetzmacher 2023-06-09 15:49:03 +02:00 committed by GitHub
commit 02718209ce
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
24 changed files with 236 additions and 214 deletions

View file

@ -6,7 +6,7 @@
from re import compile, escape, MULTILINE from re import compile, escape, MULTILINE
from ..util import tagre from ..util import tagre
from ..scraper import BasicScraper, _BasicScraper, _ParserScraper from ..scraper import BasicScraper, ParserScraper, _BasicScraper, _ParserScraper
from ..helpers import regexNamer, bounceStarter, indirectStarter from ..helpers import regexNamer, bounceStarter, indirectStarter
from .common import WordPressScraper, WordPressNavi, WordPressWebcomic from .common import WordPressScraper, WordPressNavi, WordPressWebcomic
@ -166,18 +166,18 @@ class AllTheGrowingThings(WordPressScraper):
endOfLife = True endOfLife = True
class AlphaLuna(_ParserScraper): class AlphaLuna(ParserScraper):
url = 'https://alphaluna.net/' url = 'https://alphalunacomic.net/'
stripUrl = url + 'comic/%s/' stripUrl = url + 'comic/%s/'
firstStripUrl = stripUrl % 'issue-1-cover' firstStripUrl = stripUrl % 'issue-1-cover'
imageSearch = '//main[@id="comic"]//img' imageSearch = '//main[@id="comic"]//img'
prevSearch = '//a[@rel="prev"]' prevSearch = '//a[@rel="prev"]'
class AlphaLunaSpanish(_ParserScraper): class AlphaLunaSpanish(ParserScraper):
name = 'AlphaLuna/Spanish' name = 'AlphaLuna/Spanish'
lang = 'es' lang = 'es'
url = 'https://alphaluna.net/spanish/' url = 'https://alphalunacomic.net/spanish/'
stripUrl = url + 'comic/%s/' stripUrl = url + 'comic/%s/'
firstStripUrl = stripUrl % 'issue-1-cover' firstStripUrl = stripUrl % 'issue-1-cover'
imageSearch = '//main[@id="comic"]//img' imageSearch = '//main[@id="comic"]//img'

View file

@ -117,13 +117,6 @@ class CatAndGirl(_ParserScraper):
prevSearch = '//a[d:class("pager--prev")]' prevSearch = '//a[d:class("pager--prev")]'
class CatenaCafe(WordPressScraper):
name = 'CatenaManor/CatenaCafe'
url = 'https://catenamanor.com/'
stripUrl = url + 'comic/%s/'
firstStripUrl = stripUrl % 'reboot-book1cover-small'
class CatenaManor(_ParserScraper): class CatenaManor(_ParserScraper):
baseUrl = ('https://web.archive.org/web/20141027141116/' baseUrl = ('https://web.archive.org/web/20141027141116/'
'http://catenamanor.com/') 'http://catenamanor.com/')

View file

@ -73,10 +73,16 @@ class ComicFury(ParserScraper):
'//img[d:class("comicsegmentimage")]', '//img[d:class("comicsegmentimage")]',
) )
def namer(self, image_url, page_url): def namer(self, imageUrl, pageUrl):
parts = page_url.split('/') parts = pageUrl.split('/')
path, ext = os.path.splitext(image_url) path, ext = os.path.splitext(imageUrl)
num = parts[-1] num = parts[-1]
if self.multipleImagesPerStrip:
page = self.getPage(pageUrl)
images = page.xpath('//img[@class="comicsegmentimage"]/@src')
if len(images) > 1:
imageIndex = images.index(imageUrl) + 1
return "%s_%s-%d%s" % (self.prefix, num, imageIndex, ext)
return "%s_%s%s" % (self.prefix, num, ext) return "%s_%s%s" % (self.prefix, num, ext)
def shouldSkipUrl(self, url, data): def shouldSkipUrl(self, url, data):
@ -136,7 +142,7 @@ class ComicFury(ParserScraper):
cls('AgentBishop', 'agentbishop'), cls('AgentBishop', 'agentbishop'),
cls('AHappierKindOfSad', 'ahappierkindofsad'), cls('AHappierKindOfSad', 'ahappierkindofsad'),
cls('AlbinoBrothers', 'albinobros'), cls('AlbinoBrothers', 'albinobros'),
cls('Alderwood', 'alderwood'), cls('Alderwood', 'alderwood', segmented=True),
cls('AlexanderAndLucasRebooted', 'alexanderandlucas'), cls('AlexanderAndLucasRebooted', 'alexanderandlucas'),
cls('AliaTerra', 'alia-terra'), cls('AliaTerra', 'alia-terra'),
cls('AlienIrony', 'alien-irony'), cls('AlienIrony', 'alien-irony'),
@ -785,6 +791,7 @@ class ComicFury(ParserScraper):
cls('Pulse', 'pulse'), cls('Pulse', 'pulse'),
cls('PureHavoc', 'pure-havoc'), cls('PureHavoc', 'pure-havoc'),
cls('Queenie', 'queenie'), cls('Queenie', 'queenie'),
cls('QueenieAdventure', 'queenieadventure', adult=True, segmented=True),
cls('QuestCorporeal', 'questcorporeal'), cls('QuestCorporeal', 'questcorporeal'),
cls('Rain', 'rain'), cls('Rain', 'rain'),
cls('RandomlyAssembled', 'randomlyassembled'), cls('RandomlyAssembled', 'randomlyassembled'),

View file

@ -6,7 +6,7 @@
from re import compile, escape from re import compile, escape
from ..util import tagre from ..util import tagre
from ..scraper import _BasicScraper, _ParserScraper from ..scraper import ParserScraper, _BasicScraper, _ParserScraper
from ..helpers import indirectStarter, joinPathPartsNamer from ..helpers import indirectStarter, joinPathPartsNamer
from .common import ComicControlScraper, WordPressNaviIn, WordPressScraper from .common import ComicControlScraper, WordPressNaviIn, WordPressScraper
@ -20,24 +20,6 @@ class FalconTwin(_BasicScraper):
help = 'Index format: nnn' help = 'Index format: nnn'
class FalseStart(_ParserScraper):
baseUrl = 'https://boneitisindustries.com/'
url = baseUrl + 'comics/false-start/'
stripUrl = baseUrl + 'comic/%s/'
firstStripUrl = stripUrl % 'false-start-chapter-zero-page-1'
imageSearch = '//div[@id="content"]//img[d:class("size-full")]'
prevSearch = '//a[./span[d:class("ticon-chevron-left")]]'
adult = True
def starter(self):
archivePage = self.getPage(self.url)
self.archive = archivePage.xpath('//div[contains(@class, "vcex-portfolio-grid")]//a/@href')
return self.archive[-1]
def getPrevUrl(self, url, data):
return self.archive[self.archive.index(url) - 1]
class Faneurysm(WordPressNaviIn): class Faneurysm(WordPressNaviIn):
url = 'http://hijinksensue.com/comic/think-only-tree/' url = 'http://hijinksensue.com/comic/think-only-tree/'
firstStripUrl = 'http://hijinksensue.com/comic/captains-prerogative/' firstStripUrl = 'http://hijinksensue.com/comic/captains-prerogative/'
@ -149,18 +131,19 @@ class ForLackOfABetterComic(_ParserScraper):
endOfLife = True endOfLife = True
class FoxDad(_ParserScraper): class FoxDad(ParserScraper):
url = 'https://foxdad.com/' url = 'https://foxdad.com/'
stripUrl = url + 'post/%s' stripUrl = url + 'post/%s'
firstStripUrl = stripUrl % '149683014997/some-people-are-just-different-support-the-comic' firstStripUrl = stripUrl % '149683014997/some-people-are-just-different-support-the-comic'
imageSearch = ('//figure[@class="photo-hires-item"]//img', '//figure[@class="tmblr-full"]//img') imageSearch = '//figure[@class="photo-hires-item"]//img'
prevSearch = '//a[@class="previous-button"]' prevSearch = '//a[@class="previous-button"]'
def namer(self, imageUrl, pageUrl): def namer(self, imageUrl, pageUrl):
page = self.getPage(pageUrl) page = self.getPage(pageUrl)
post = page.xpath('//link[@type="application/json+oembed"]')[0].get('href') post = page.xpath('//li[@class="timestamp"]/a/@href')[0]
post = post.replace('https://www.tumblr.com/oembed/1.0?url=https://foxdad.com/post', '') post = post.replace('https://foxdad.com/post/', '')
post = post.replace('-support-me-on-patreon', '') if '-consider-support' in post:
post = post.split('-consider-support')[0]
return post.replace('/', '-') return post.replace('/', '-')

View file

@ -59,16 +59,6 @@ class GeeksNextDoor(_ParserScraper):
help = 'Index format: yyyy-mm-dd' help = 'Index format: yyyy-mm-dd'
class Ginpu(WordPressNavi):
url = 'https://www.ginpu.us/'
stripUrl = url + 'comic/%s/'
firstStripUrl = stripUrl % 'filler-2'
def namer(self, imageUrl, pageUrl):
filename = imageUrl.rsplit('/', 3)
return '%s-%s_%s' % (filename[1], filename[2], filename[3])
class GirlGenius(_BasicScraper): class GirlGenius(_BasicScraper):
baseUrl = 'http://www.girlgeniusonline.com/' baseUrl = 'http://www.girlgeniusonline.com/'
rurl = escape(baseUrl) rurl = escape(baseUrl)

View file

@ -68,6 +68,20 @@ class HeadlessBliss(ComicControlScraper):
url = 'http://headlessbliss.com/' url = 'http://headlessbliss.com/'
class Hellkats(ParserScraper):
url = 'https://poecatcomix.com/hellkatscomic/'
stripUrl = url + '%s/'
firstStripUrl = stripUrl % 'hellkats-issue-1-cover'
imageSearch = '//img[@class="scale-with-grid wp-post-image"]'
prevSearch = '//a[d:class("fixed-nav-prev")]'
latestSearch = '//div[@class="post-title"]//a'
starter = indirectStarter
adult = True
def namer(self, imageUrl, pageUrl):
return pageUrl.rsplit('/', 2)[1] + '.' + imageUrl.rsplit('.', 1)[-1]
class HeyFox(WordPressScraper): class HeyFox(WordPressScraper):
url = 'http://www.steamclaw.com/heyfox/' url = 'http://www.steamclaw.com/heyfox/'
stripUrl = url + 'archives/comic/%s' stripUrl = url + 'archives/comic/%s'

View file

@ -41,6 +41,16 @@ class InternetWebcomic(WordPressNavi):
help = 'Index format: n' help = 'Index format: n'
class Inverloch(ParserScraper):
stripUrl = 'https://www.seraph-inn.com/view.php?story=inverloch&page=%s'
url = stripUrl % '763'
firstStripUrl = stripUrl % '2'
imageSearch = '//img[@class="page"]'
prevSearch = '//p[@class="comic-nav"]/a[text()=" Previous"]'
multipleImagesPerStrip = True
endOfLife = True
class IrregularWebcomic(BasicScraper): class IrregularWebcomic(BasicScraper):
url = 'http://www.irregularwebcomic.net/' url = 'http://www.irregularwebcomic.net/'
stripUrl = url + '%s.html' stripUrl = url + '%s.html'

View file

@ -37,11 +37,17 @@ class KemonoCafe(ParserScraper):
filename = filename.replace('89', '90') filename = filename.replace('89', '90')
elif 'rascals' in pageUrl and '133-2' in pageUrl: elif 'rascals' in pageUrl and '133-2' in pageUrl:
filename = filename.replace('133', '134') filename = filename.replace('133', '134')
elif 'caughtinorbit' in pageUrl and '26gs' in filename:
filename = filename.replace('026gs', '021')
elif 'caughtinorbit' in pageUrl and '27gs' in filename:
filename = filename.replace('027gs', '022')
# Fix unordered filenames # Fix unordered filenames
if 'addictivescience' in pageUrl: if 'addictivescience' in pageUrl:
page = self.getPage(pageUrl) page = self.getPage(pageUrl)
num = int(page.xpath('//div[@id="comic-wrap"]/@class')[0].replace('comic-id-', '')) num = int(page.xpath('//div[@id="comic-wrap"]/@class')[0].replace('comic-id-', ''))
filename = '%04d_%s' % (num, filename) filename = '%04d_%s' % (num, filename)
elif 'CaughtInOrbit' in filename:
filename = filename.replace('CaughtInOrbit', 'CIO')
return filename return filename
@classmethod @classmethod
@ -50,13 +56,13 @@ class KemonoCafe(ParserScraper):
cls('AddictiveScience', 'addictivescience', 'page0001'), cls('AddictiveScience', 'addictivescience', 'page0001'),
cls('Bethellium', 'bethellium', 'c01p00'), cls('Bethellium', 'bethellium', 'c01p00'),
cls('CaribbeanBlue', 'cb', 'page000', last='page325'), cls('CaribbeanBlue', 'cb', 'page000', last='page325'),
cls('CaughtInOrbit', 'caughtinorbit', 'comic-cover'),
cls('IMew', 'imew', 'imew00', last='imew50'), cls('IMew', 'imew', 'imew00', last='imew50'),
cls('Knighthood', 'knighthood', 'kh0001'), cls('Knighthood', 'knighthood', 'kh0001'),
cls('KnuckleUp', 'knuckle-up', 'page001', adult=True), cls('KnuckleUp', 'knuckle-up', 'page001', adult=True),
cls('LasLindas', 'laslindas', 'll0001', adult=True), cls('LasLindas', 'laslindas', 'll0001', adult=True),
cls('Paprika', 'paprika', 'page000'), cls('Paprika', 'paprika', 'page000'),
cls('PracticeMakesPerfect', 'pmp', 'title-001'), cls('PracticeMakesPerfect', 'pmp', 'title-001'),
cls('PrincessBunny', 'princessbunny', 'pg001'),
cls('Rascals', 'rascals', 'rascals-pg-0', adult=True), cls('Rascals', 'rascals', 'rascals-pg-0', adult=True),
cls('TheEyeOfRamalach', 'theeye', 'theeye-page01'), cls('TheEyeOfRamalach', 'theeye', 'theeye-page01'),
cls('TinaOfTheSouth', 'tots', 'tos-01-01'), cls('TinaOfTheSouth', 'tots', 'tos-01-01'),

View file

@ -11,11 +11,11 @@ from ..util import tagre
from .common import ComicControlScraper, WordPressScraper, WordPressNaviIn from .common import ComicControlScraper, WordPressScraper, WordPressNaviIn
class Lackadaisy(_ParserScraper): class Lackadaisy(ParserScraper):
url = 'https://www.lackadaisy.com/comic.php' url = 'https://www.lackadaisy.com/comic.php'
stripUrl = url + '?comicid=%s' stripUrl = url + '?comicid=%s'
firstStripUrl = stripUrl % '1' firstStripUrl = stripUrl % '1'
imageSearch = '//div[@id="content"]/img' imageSearch = '//div[@id="exhibit"]/img[contains(@src, "comic/")]'
prevSearch = '//div[@class="prev"]/a' prevSearch = '//div[@class="prev"]/a'
nextSearch = '//div[@class="next"]/a' nextSearch = '//div[@class="next"]/a'
help = 'Index format: n' help = 'Index format: n'
@ -28,6 +28,12 @@ class Lackadaisy(_ParserScraper):
return 'lackadaisy_%s.%s' % (num, ext) return 'lackadaisy_%s.%s' % (num, ext)
class Lancer(WordPressScraper):
url = 'https://lancercomic.com/'
stripUrl = url + 'comic/%s/'
firstStripUrl = stripUrl % 'chapter-1-cover'
class LastResort(WordPressScraper): class LastResort(WordPressScraper):
url = 'http://www.lastres0rt.com/' url = 'http://www.lastres0rt.com/'
stripUrl = url + 'comic/%s/' stripUrl = url + 'comic/%s/'

View file

@ -95,6 +95,8 @@ class MangaDex(ParserScraper):
@classmethod @classmethod
def getmodules(cls): def getmodules(cls):
return ( return (
cls('AniTomo', '920c22e7-49c9-4bb4-b394-0c964b6037fc'),
cls('ArcaneSniper', 'cbf53f02-9594-42e7-9dbf-8ae1c783466f'),
cls('AttackOnTitan', '304ceac3-8cdb-4fe7-acf7-2b6ff7a60613'), cls('AttackOnTitan', '304ceac3-8cdb-4fe7-acf7-2b6ff7a60613'),
cls('Beastars', 'f5e3baad-3cd4-427c-a2ec-ad7d776b370d'), cls('Beastars', 'f5e3baad-3cd4-427c-a2ec-ad7d776b370d'),
cls('BokuNoKokoroNoYabaiYatsu', '3df1a9a3-a1be-47a3-9e90-9b3e55b1d0ac'), cls('BokuNoKokoroNoYabaiYatsu', '3df1a9a3-a1be-47a3-9e90-9b3e55b1d0ac'),
@ -104,6 +106,7 @@ class MangaDex(ParserScraper):
cls('DragonDrive', '5c06ae70-b5cf-431a-bcd5-262a411de527'), cls('DragonDrive', '5c06ae70-b5cf-431a-bcd5-262a411de527'),
cls('FuguushokuKajishiDakedoSaikyouDesu', '17b3b648-fd89-4a69-9a42-6068ffbfa7a7'), cls('FuguushokuKajishiDakedoSaikyouDesu', '17b3b648-fd89-4a69-9a42-6068ffbfa7a7'),
cls('GanbareDoukiChan', '190616bc-7da6-45fd-abd4-dd2ca656c183'), cls('GanbareDoukiChan', '190616bc-7da6-45fd-abd4-dd2ca656c183'),
cls('GijiHarem', 'd8f9afe2-aa44-4bc6-9145-eebb1f282372'),
cls('HangingOutWithAGamerGirl', 'de9e3b62-eac5-4c0a-917d-ffccad694381'), cls('HangingOutWithAGamerGirl', 'de9e3b62-eac5-4c0a-917d-ffccad694381'),
cls('HoriMiya', 'a25e46ec-30f7-4db6-89df-cacbc1d9a900'), cls('HoriMiya', 'a25e46ec-30f7-4db6-89df-cacbc1d9a900'),
cls('HowToOpenATriangularRiceball', '6ebd90ce-d5e8-49c0-a4bc-e02e0f8ecb93'), cls('HowToOpenATriangularRiceball', '6ebd90ce-d5e8-49c0-a4bc-e02e0f8ecb93'),
@ -113,17 +116,23 @@ class MangaDex(ParserScraper):
cls('JahySamaWaKujikenai', '2f4e5f5b-d930-4266-8c8a-c4cf9a81e51f'), cls('JahySamaWaKujikenai', '2f4e5f5b-d930-4266-8c8a-c4cf9a81e51f'),
cls('JingaiNoYomeToIchaIchaSuru', '809d2493-df3c-4e72-a57e-3e0026cae9fb'), cls('JingaiNoYomeToIchaIchaSuru', '809d2493-df3c-4e72-a57e-3e0026cae9fb'),
cls('KaetteKudasaiAkutsuSan', '737a846b-2e67-4d63-9f7e-f54b3beebac4'), cls('KaetteKudasaiAkutsuSan', '737a846b-2e67-4d63-9f7e-f54b3beebac4'),
cls('KaikoSaretaAnkokuHeishi30DaiNoSlowNaSecondLife', 'cbcf5051-74a0-4b93-b99c-1a6975f1bef9'),
cls('KawaiiJoushiWoKomarasetai', '23b7cc7a-df89-4049-af28-1fa78f88713e'), cls('KawaiiJoushiWoKomarasetai', '23b7cc7a-df89-4049-af28-1fa78f88713e'),
cls('KanojoOkarishimasu', '32fdfe9b-6e11-4a13-9e36-dcd8ea77b4e4'), cls('KanojoOkarishimasu', '32fdfe9b-6e11-4a13-9e36-dcd8ea77b4e4'),
cls('KoiToUtatane', 'f7d40a27-e289-45b3-9c68-d1cb251897e6'), cls('KoiToUtatane', 'f7d40a27-e289-45b3-9c68-d1cb251897e6'),
cls('KonoKaishaNiSukiNaHitoGaImasu', '3e8cf40f-ba17-480a-b60b-a675db032ee2'),
cls('LonelyGirlNiSakaraenai', 'd7576e72-0301-4ed3-9137-722ed768bfda'),
cls('Lv2KaraCheatDattaMotoYuushaKouhoNoMattariIsekaiLife', '58bc83a0-1808-484e-88b9-17e167469e23'), cls('Lv2KaraCheatDattaMotoYuushaKouhoNoMattariIsekaiLife', '58bc83a0-1808-484e-88b9-17e167469e23'),
cls('MaouNoOreGaDoreiElfWoYomeNiShitandaGaDouMederebaIi', '55ace2fb-e157-4d76-9e72-67c6bd762a39'), cls('MaouNoOreGaDoreiElfWoYomeNiShitandaGaDouMederebaIi', '55ace2fb-e157-4d76-9e72-67c6bd762a39'),
cls('ModernMoGal', 'b1953f80-36f7-492c-b0f8-e9dd0ad01752'), cls('ModernMoGal', 'b1953f80-36f7-492c-b0f8-e9dd0ad01752'),
cls('MousouTelepathy', '3d25d7da-893f-400e-9aeb-6163773c671a'),
cls('MyTinySenpaiFromWork', '28ed63af-61f8-43af-bac3-762030c72963'), cls('MyTinySenpaiFromWork', '28ed63af-61f8-43af-bac3-762030c72963'),
cls('MyWifeIsFromAThousandYearsAgo', '17a56d33-9443-433a-9e0d-70459893ed8f'),
cls('OMaidensinYourSavageSeason', 'c4613b7d-7a6e-48f9-82f0-bce3dd33383a'), cls('OMaidensinYourSavageSeason', 'c4613b7d-7a6e-48f9-82f0-bce3dd33383a'),
cls('OokamiShounenWaKyouMoUsoOKasaneru', '5e77d9e2-2e44-431a-a995-5fefd411e55e'), cls('OokamiShounenWaKyouMoUsoOKasaneru', '5e77d9e2-2e44-431a-a995-5fefd411e55e'),
cls('OokamiToKoshinryou', 'de900fd3-c94c-4148-bbcb-ca56eaeb57a4'), cls('OokamiToKoshinryou', 'de900fd3-c94c-4148-bbcb-ca56eaeb57a4'),
cls('OtomeYoukaiZakuro', 'c1fa97be-0f1f-4686-84bc-806881c97d53'), cls('OtomeYoukaiZakuro', 'c1fa97be-0f1f-4686-84bc-806881c97d53'),
cls('Overgeared', '3fc308c9-4b00-4dc3-943e-1f39242bc708'),
cls('OversimplifiedSCP', 'e911fe33-a9b3-43dc-9eb7-f5ee081a6dc8'), cls('OversimplifiedSCP', 'e911fe33-a9b3-43dc-9eb7-f5ee081a6dc8'),
cls('PashiriNaBokuToKoisuruBanchouSan', '838e5b3a-51c8-44cf-b6e2-68193416f6fe'), cls('PashiriNaBokuToKoisuruBanchouSan', '838e5b3a-51c8-44cf-b6e2-68193416f6fe'),
cls('PleaseDontBullyMeNagatoro', 'd86cf65b-5f6c-437d-a0af-19a31f94ec55'), cls('PleaseDontBullyMeNagatoro', 'd86cf65b-5f6c-437d-a0af-19a31f94ec55'),
@ -141,12 +150,14 @@ class MangaDex(ParserScraper):
cls('SwordArtOnlineProgressive', '22ea3f54-11e4-4932-a527-89d63d3a62d9'), cls('SwordArtOnlineProgressive', '22ea3f54-11e4-4932-a527-89d63d3a62d9'),
cls('TadokoroSan', '8ffbfa2f-23fa-4490-848e-942581a4d873'), cls('TadokoroSan', '8ffbfa2f-23fa-4490-848e-942581a4d873'),
cls('TamenDeGushi', '3f1453fb-9dac-4aca-a2ea-69613856c952'), cls('TamenDeGushi', '3f1453fb-9dac-4aca-a2ea-69613856c952'),
cls('TamingMaster', '534c1b5b-aff6-44fd-bf68-7294e6526fb3'),
cls('TenseiShitaraSlimeDattaKen', 'e78a489b-6632-4d61-b00b-5206f5b8b22b'), cls('TenseiShitaraSlimeDattaKen', 'e78a489b-6632-4d61-b00b-5206f5b8b22b'),
cls('TheNewGate', 'b41bef1e-7df9-4255-bd82-ecf570fec566'), cls('TheNewGate', 'b41bef1e-7df9-4255-bd82-ecf570fec566'),
cls('TheWolfAndRedRidingHood', 'a7d1283b-ed38-4659-b8bc-47bfca5ccb8a'), cls('TheWolfAndRedRidingHood', 'a7d1283b-ed38-4659-b8bc-47bfca5ccb8a'),
cls('TomoChanWaOnnanoko', '76ee7069-23b4-493c-bc44-34ccbf3051a8'), cls('TomoChanWaOnnanoko', '76ee7069-23b4-493c-bc44-34ccbf3051a8'),
cls('TonikakuKawaii', '30f3ac69-21b6-45ad-a110-d011b7aaadaa'), cls('TonikakuKawaii', '30f3ac69-21b6-45ad-a110-d011b7aaadaa'),
cls('UramikoiKoiUramikoi', '009b6788-48f3-4e78-975c-097f54def7ab'), cls('UramikoiKoiUramikoi', '009b6788-48f3-4e78-975c-097f54def7ab'),
cls('UzakiChanWaAsobitai', '5a90308a-8b12-4a4d-9c6d-2487028fe319'),
cls('YotsubaAnd', '58be6aa6-06cb-4ca5-bd20-f1392ce451fb'), cls('YotsubaAnd', '58be6aa6-06cb-4ca5-bd20-f1392ce451fb'),
cls('YuYuHakusho', '44a5cbe1-0204-4cc7-a1ff-0fda2ac004b6'), cls('YuYuHakusho', '44a5cbe1-0204-4cc7-a1ff-0fda2ac004b6'),
) )

View file

@ -5,7 +5,7 @@
# Copyright (C) 2019-2020 Daniel Ring # Copyright (C) 2019-2020 Daniel Ring
from re import compile, escape from re import compile, escape
from ..scraper import _BasicScraper, _ParserScraper from ..scraper import ParserScraper, _BasicScraper, _ParserScraper
from ..helpers import indirectStarter, bounceStarter from ..helpers import indirectStarter, bounceStarter
from ..util import tagre from ..util import tagre
from .common import ComicControlScraper, WordPressScraper, WordPressNavi, WordPressWebcomic from .common import ComicControlScraper, WordPressScraper, WordPressNavi, WordPressWebcomic
@ -113,29 +113,18 @@ class Nicky510(WordPressNavi):
endOfLife = True endOfLife = True
class Nightshift(WordPressWebcomic): class Nightshift(ParserScraper):
url = 'https://poecatcomix.com/nightshift-static/' url = 'https://poecatcomix.com/nightshiftcomic/'
stripUrl = 'https://poecatcomix.com/nightshift/%s/' stripUrl = url + '%s/'
firstStripUrl = stripUrl % 'ns-cover' firstStripUrl = stripUrl % 'ns-issue-1-cover'
imageSearch = '//div[contains(@class, "webcomic-media")]//img' imageSearch = '//img[@class="scale-with-grid wp-post-image"]'
prevSearch = '//a[d:class("fixed-nav-prev")]'
latestSearch = '//div[@class="post-title"]//a'
starter = indirectStarter
adult = True adult = True
def starter(self):
# Build list of chapters for naming
indexPage = self.getPage(self.url)
self.chapters = indexPage.xpath('//a[./img[contains(@class, "attachment-large")]]/@href')
latestPage = self.chapters[0]
self.chapters = self.chapters[1:]
self.currentChapter = len(self.chapters)
return latestPage
def namer(self, imageUrl, pageUrl): def namer(self, imageUrl, pageUrl):
page = pageUrl.rstrip('/').rsplit('/', 1)[-1] return pageUrl.rsplit('/', 2)[1] + '.' + imageUrl.rsplit('.', 1)[-1]
page = page.replace('blood-brothers', 'bloodbrothers').replace('bb-2', 'bb2').replace('ns7-', 'page-')
filename = 'ns%d-%s.%s' % (self.currentChapter, page, imageUrl.rsplit('.', 1)[-1])
if pageUrl in self.chapters:
self.currentChapter = self.currentChapter - 1
return filename
class Nimona(_ParserScraper): class Nimona(_ParserScraper):
@ -176,13 +165,13 @@ class NoNeedForBushido(_ParserScraper):
help = 'Index format: nnn' help = 'Index format: nnn'
class NonPlayerCharacter(_ParserScraper): class NonPlayerCharacter(ParserScraper):
url = 'https://www.lfg.co/' url = 'https://www.lfg.co/'
stripUrl = url + 'npc/tale/%s/' stripUrl = url + 'npc/comic/%s/'
firstStripUrl = stripUrl % '1-1' firstStripUrl = stripUrl % '1-1'
imageSearch = '//div[@id="comic-img"]//img' imageSearch = '//div[@id="comic-img"]//img'
prevSearch = '//a[@class="comic-nav-prev"]' prevSearch = '//a[@class="comic-nav-prev"]'
latestSearch = '//div[@id="feature-npc-footer"]/a[contains(@href, "npc/tale/")]' latestSearch = '//div[@id="feature-npc-footer"]/a[contains(@href, "npc/comic/")]'
starter = indirectStarter starter = indirectStarter
def namer(self, imageUrl, pageUrl): def namer(self, imageUrl, pageUrl):

View file

@ -75,6 +75,7 @@ class OhJoySexToy(WordPressNavi):
url = 'http://www.ohjoysextoy.com/' url = 'http://www.ohjoysextoy.com/'
firstStripUrl = url + 'introduction/' firstStripUrl = url + 'introduction/'
textSearch = '//div[@id="comic"]//img/@alt' textSearch = '//div[@id="comic"]//img/@alt'
multipleImagesPerStrip = True
adult = True adult = True

View file

@ -604,6 +604,7 @@ class Removed(Scraper):
cls('WotNow'), cls('WotNow'),
# Removed in 3.0 # Removed in 3.0
cls('CatenaManor/CatenaCafe'),
cls('ComicFury/AdventuresOftheGreatCaptainMaggieandCrew'), cls('ComicFury/AdventuresOftheGreatCaptainMaggieandCrew'),
cls('ComicFury/AWAKENING'), cls('ComicFury/AWAKENING'),
cls('ComicFury/Beebleville'), cls('ComicFury/Beebleville'),
@ -832,6 +833,8 @@ class Removed(Scraper):
cls('ComicsKingdom/Redeye'), cls('ComicsKingdom/Redeye'),
cls('ComicsKingdom/RedeyeSundays'), cls('ComicsKingdom/RedeyeSundays'),
cls('CrapIDrewOnMyLunchBreak'), cls('CrapIDrewOnMyLunchBreak'),
cls('FalseStart'),
cls('Ginpu'),
cls('GoComics/060'), cls('GoComics/060'),
cls('GoComics/2CowsAndAChicken'), cls('GoComics/2CowsAndAChicken'),
cls('GoComics/ABitSketch'), cls('GoComics/ABitSketch'),
@ -992,9 +995,11 @@ class Removed(Scraper):
cls('GoComics/Wrobbertcartoons'), cls('GoComics/Wrobbertcartoons'),
cls('GoComics/Zootopia'), cls('GoComics/Zootopia'),
cls('JustAnotherEscape'), cls('JustAnotherEscape'),
cls('KemonoCafe/PrincessBunny'),
cls('Laiyu', 'brk'), cls('Laiyu', 'brk'),
cls('MangaDex/DrStone', 'legal'), cls('MangaDex/DrStone', 'legal'),
cls('MangaDex/HeavensDesignTeam', 'legal'), cls('MangaDex/HeavensDesignTeam', 'legal'),
cls('MangaDex/ImTheMaxLevelNewbie', 'legal'),
cls('MangaDex/SPYxFAMILY', 'legal'), cls('MangaDex/SPYxFAMILY', 'legal'),
cls('Ryugou'), cls('Ryugou'),
cls('SeelPeel'), cls('SeelPeel'),
@ -1568,16 +1573,21 @@ class Removed(Scraper):
cls('SnafuComics/Tin'), cls('SnafuComics/Tin'),
cls('SnafuComics/Titan'), cls('SnafuComics/Titan'),
cls('StudioKhimera/Eorah', 'mov'), cls('StudioKhimera/Eorah', 'mov'),
cls('StudioKhimera/Mousechevious'),
cls('StuffNoOneToldMe'), cls('StuffNoOneToldMe'),
cls('TaleOfTenThousand'), cls('TaleOfTenThousand'),
cls('TalesAndTactics'),
cls('TheCyantianChronicles/CookieCaper'), cls('TheCyantianChronicles/CookieCaper'),
cls('TheCyantianChronicles/Pawprints'), cls('TheCyantianChronicles/Pawprints'),
cls('VampireHunterBoyfriends'),
cls('VGCats/Adventure'), cls('VGCats/Adventure'),
cls('VGCats/Super'), cls('VGCats/Super'),
cls('VictimsOfTheSystem'), cls('VictimsOfTheSystem'),
cls('WebDesignerCOTW'), cls('WebDesignerCOTW'),
cls('WebToons/Adamsville'), cls('WebToons/Adamsville'),
cls('WebToons/CrapIDrewOnMyLunchBreak'), cls('WebToons/CrapIDrewOnMyLunchBreak'),
cls('WebToons/CrystalVirus'),
cls('WebToons/OVERPOWERED'),
cls('WintersLight'), cls('WintersLight'),
) )
@ -1679,6 +1689,7 @@ class Renamed(Scraper):
cls('SmackJeeves/TheRealmOfKaerwyn', 'ComicFury/TheRealmOfKaerwyn'), cls('SmackJeeves/TheRealmOfKaerwyn', 'ComicFury/TheRealmOfKaerwyn'),
cls('SoloLeveling', 'MangaDex/SoloLeveling'), cls('SoloLeveling', 'MangaDex/SoloLeveling'),
cls('StudioKhimera/Draconia', 'Draconia'), cls('StudioKhimera/Draconia', 'Draconia'),
cls('StudioKhimera/UberQuest', 'UberQuest'),
cls('TracesOfThePast', 'RickGriffinStudios/TracesOfThePast'), cls('TracesOfThePast', 'RickGriffinStudios/TracesOfThePast'),
cls('TracesOfThePast/NSFW', 'RickGriffinStudios/TracesOfThePastNSFW'), cls('TracesOfThePast/NSFW', 'RickGriffinStudios/TracesOfThePastNSFW'),

View file

@ -210,12 +210,12 @@ class PlanescapeSurvival(_BasicScraper):
help = 'Index format: nnn' help = 'Index format: nnn'
class PlushAndBlood(_ParserScraper): class PlushAndBlood(ParserScraper):
url = 'http://www.plushandblood.com/Comic.php' url = 'http://www.plushandblood.com/Comic.php'
stripUrl = url + '?strip_id=%s' stripUrl = url + '?strip_id=%s'
firstStripUrl = stripUrl % '1' firstStripUrl = stripUrl % '1'
imageSearch = '//img[contains(@src, "comics/")]' imageSearch = '//img[contains(@src, "comics/")]'
prevSearch = '//a[./img[contains(@src, "Nav/Prev")]]' prevSearch = '//a[contains(text(), "PREV")]'
class PokeyThePenguin(_ParserScraper): class PokeyThePenguin(_ParserScraper):
@ -334,8 +334,10 @@ class PS238(_ParserScraper):
class PvPOnline(ParserScraper): class PvPOnline(ParserScraper):
baseUrl = 'https://www.toonhoundstudios.com/' baseUrl = 'https://www.toonhoundstudios.com/'
url = baseUrl + 'pvp/' url = baseUrl + 'pvp/'
stripUrl = baseUrl + 'comic/%s/?sid=372' stripUrl = baseUrl + 'comic/%s/'
firstStripUrl = stripUrl % '19980504' firstStripUrl = stripUrl % '19980504'
imageSearch = '//div[@id="spliced-comic"]//img/@data-src-img' imageSearch = '//div[@id="spliced-comic"]//img/@data-src-img'
prevSearch = '//div[d:class("comic-nav")]//a[d:class("prev")]' prevSearch = '//a[d:class("prev")]'
help = 'Older pages need a Patreon subscription'
def namer(self, imageUrl, pageUrl):
return 'pvp' + imageUrl.rsplit('/', 1)[-1]

View file

@ -30,10 +30,11 @@ class ProjectFuture(ParserScraper):
cls('BookOfTenets', 'tenets', '01', last='45'), cls('BookOfTenets', 'tenets', '01', last='45'),
cls('CriticalMass', 'criticalmass', 'cover', last='26'), cls('CriticalMass', 'criticalmass', 'cover', last='26'),
cls('DarkLordRising', 'darklord', '01-00', last='10-10'), cls('DarkLordRising', 'darklord', '01-00', last='10-10'),
cls('Emily', 'emily', '01-00'), cls('Emily', 'emily', '01-00', last='07-10'),
cls('FishingTrip', 'fishing', '01-00'), cls('FishingTrip', 'fishing', '01-00', last='03-12'),
cls('HeadsYouLose', 'heads', '00-01', last='07-12'), cls('HeadsYouLose', 'heads', '00-01', last='07-12'),
cls('IPanther', 'panther', '00'), cls('InnocenceGuiltAndChange', 'ernst', '01-00'),
cls('IPanther', 'panther', '00', last='20'),
cls('NiallsStory', 'niall', '00'), cls('NiallsStory', 'niall', '00'),
cls('ProjectFuture', 'strip', '0', last='664'), cls('ProjectFuture', 'strip', '0', last='664'),
cls('RedValentine', 'redvalentine', '1', last='6'), cls('RedValentine', 'redvalentine', '1', last='6'),
@ -42,10 +43,12 @@ class ProjectFuture(ParserScraper):
cls('TheAxemanCometh', 'axeman', '01-01', last='02-18'), cls('TheAxemanCometh', 'axeman', '01-01', last='02-18'),
cls('ToCatchADemon', 'daxxon', '01-00', last='03-14'), cls('ToCatchADemon', 'daxxon', '01-00', last='03-14'),
cls('TheDarkAngel', 'darkangel', 'cover', last='54'), cls('TheDarkAngel', 'darkangel', 'cover', last='54'),
cls('TheBountyProject', 'bounty', '00-00'),
cls('TheEpsilonProject', 'epsilon', '00-01'), cls('TheEpsilonProject', 'epsilon', '00-01'),
cls('TheHarvest', 'harvest', '01-00'), cls('TheHarvest', 'harvest', '01-00', last='08-26'),
cls('TheSierraChronicles', 'sierra', '0', last='29'), cls('TheSierraChronicles', 'sierra', '0', last='29'),
cls('TheTuppenyMan', 'tuppenny', '00', last='16'), cls('TheTuppenyMan', 'tuppenny', '00', last='16'),
cls('TurningANewPage', 'azrael', '1', last='54'), cls('TurningANewPage', 'azrael', '1', last='54'),
cls('Xerian', 'xerian', '01-00'), cls('Xerian', 'xerian', '01-00'),
cls('ZetaTakesATrip', 'zeta', '0-00'),
) )

View file

@ -7,11 +7,19 @@ from re import compile
from urllib.parse import urljoin from urllib.parse import urljoin
from ..helpers import bounceStarter from ..helpers import bounceStarter
from ..scraper import _BasicScraper, _ParserScraper from ..scraper import ParserScraper, _BasicScraper, _ParserScraper
from ..util import tagre from ..util import tagre
from .common import WordPressScraper, WordPressNavi, WordPressWebcomic from .common import WordPressScraper, WordPressNavi, WordPressWebcomic
class Rainburn(ParserScraper):
url = 'https://rainburn.virmir.com/'
stripUrl = url + 'comic.php?page=%s'
firstStripUrl = stripUrl % '1'
imageSearch = '//div[@class="comic"]//img'
prevSearch = '//a[contains(@class, "prev")]'
class RalfTheDestroyer(WordPressScraper): class RalfTheDestroyer(WordPressScraper):
url = 'http://ralfthedestroyer.com/' url = 'http://ralfthedestroyer.com/'

View file

@ -209,10 +209,65 @@ class Sheldon(_BasicScraper):
help = 'Index format: yymmdd' help = 'Index format: yymmdd'
class Shifters(WordPressNavi): class Shifters(ParserScraper):
url = 'http://shiftersonline.com/' baseUrl = 'https://shiftersonline.com/'
stripUrl = url + '%s/' url = baseUrl + 'series/shifters-redux/'
firstStripUrl = stripUrl % 'shifters-redux-promo' stripUrl = baseUrl + 'comic/%s/'
firstStripUrl = stripUrl % 'chapter-1-pg-1'
imageSearch = '//div[@id="spliced-comic"]//span[@class="default-lang"]//img'
prevSearch = '//a[@class="previous-comic"]'
latestSearch = '//div[@id="comic-archive-list"]//a'
starter = indirectStarter
def namer(self, imageUrl, pageUrl):
return pageUrl.rsplit('/', 2)[1] + '.' + imageUrl.rsplit('.', 1)[-1]
class ShiftersOnGossamerWings(Shifters):
name = 'Shifters/OnGossamerWings'
baseUrl = 'https://shiftersonline.com/'
url = baseUrl + 'series/shifters-on-gossamer-wings/'
stripUrl = baseUrl + 'comic/%s/'
firstStripUrl = stripUrl % 'on-gossamer-wings-cover'
class ShiftersTheBeastWithin(Shifters):
name = 'Shifters/TheBeastWithin'
baseUrl = 'https://shiftersonline.com/'
url = baseUrl + 'series/shifters-the-beast-within/'
stripUrl = baseUrl + 'comic/%s/'
firstStripUrl = stripUrl % 'awakenings-pg-1'
endOfLife = True
def namer(self, imageUrl, pageUrl):
filename = pageUrl.rsplit('/', 2)[1] + '.' + imageUrl.rsplit('.', 1)[-1]
if filename.startswith('the-company-of-dragons'):
filename = 'in-' + filename
# Prepend chapter number to filename
chapters = [
'awakenings',
'lifting-the-veil',
'tears-of-blood',
'on-the-lam',
'shades-of-intrigue',
'catfight',
'out-of-control',
'damage-control',
'wolfs-clothing',
'strange-dreams',
'blood-bonds',
'the-other-team',
'get-ferrah',
'the-price-of-power',
'dogfight',
'surfacing',
'in-the-company-of-dragons',
'filler',
]
for chapter in chapters:
if filename.startswith(chapter):
filename = 'chapter-' + str(chapters.index(chapter) + 1) + '-' + filename
return filename
class ShipInABottle(WordPressScraper): class ShipInABottle(WordPressScraper):
@ -527,30 +582,18 @@ class StarCrossdDestiny(_ParserScraper):
return directory + '-' + filename return directory + '-' + filename
class StarfireAgency(WordPressWebcomic): class StarfireAgency(ParserScraper):
url = 'https://poecatcomix.com/starfire-agency-static/' url = 'https://poecatcomix.com/starfirecomic/'
stripUrl = 'https://poecatcomix.com/starfire-agency/%s/' stripUrl = url + '%s/'
firstStripUrl = stripUrl % '2005-09-201' firstStripUrl = stripUrl % 'sfa-issue-1-cover'
imageSearch = '//div[contains(@class, "webcomic-media")]//img' imageSearch = '//img[@class="scale-with-grid wp-post-image"]'
prevSearch = '//a[d:class("fixed-nav-prev")]'
def starter(self): latestSearch = '//div[@class="post-title"]//a'
# Build list of chapters for naming starter = indirectStarter
indexPage = self.getPage(self.url) adult = True
self.chapters = indexPage.xpath('//a[./img[contains(@class, "attachment-large")]]/@href')
latestPage = self.chapters[0]
self.chapters = self.chapters[1:]
self.currentChapter = len(self.chapters)
return latestPage
def namer(self, imageUrl, pageUrl): def namer(self, imageUrl, pageUrl):
page = pageUrl.rstrip('/').rsplit('/', 1)[-1] return pageUrl.rsplit('/', 2)[1] + '.' + imageUrl.rsplit('.', 1)[-1]
page = page.replace('3page00', 'cover3').replace('6429', 'cover7').replace('sfa-6-5-cover', 'cover6')
page = page.replace('sfa01', 'page01').replace('sfa03', 'page03').replace('sfa04', 'page04')
page = page.replace('sfa24', 'page24').replace('sfa07', 'page')
filename = 'sfa%d-%s.%s' % (self.currentChapter, page, imageUrl.rsplit('.', 1)[-1])
if pageUrl in self.chapters:
self.currentChapter = self.currentChapter - 1
return filename
class StarTrip(ComicControlScraper): class StarTrip(ComicControlScraper):

View file

@ -1,65 +0,0 @@
# SPDX-License-Identifier: MIT
# Copyright (C) 2019-2022 Tobias Gruetzmacher
# Copyright (C) 2019-2020 Daniel Ring
from ..scraper import ParserScraper
from .common import WordPressScraper
class StudioKhimera(ParserScraper):
imageSearch = '//figure[@class="gallery-item"]//img/@data-src'
prevSearch = '//a[@rel="prev"]'
def __init__(self, name, sub, last=None, adult=False, fixNames=False):
super().__init__('StudioKhimera/' + name)
self.baseUrl = 'https://%s.studiokhimera.com/' % sub
self.stripUrl = self.baseUrl + '%s/'
self.url = self.baseUrl + 'category/comicChapter/?latest'
self.multipleImagesPerStrip = True
if last:
self.last = True
self.url = self.stripUrl % last
self.endOfLife = True
if adult:
self.adult = True
def starter(self):
# Retrieve list of chapter links
chapterPage = self.getPage(self.baseUrl + 'archive/')
self.chapters = chapterPage.xpath('//main//a/@href')
self.firstStripUrl = self.chapters[0]
return self.chapters[-1]
def getPrevUrl(self, url, data):
# Select previous chapter from list
index = [i for i, ch in enumerate(self.chapters) if ch == url][0]
if index == 0:
return None
return self.chapters[index - 1]
@classmethod
def getmodules(cls):
return (
cls('Mousechievous', 'mousechievous'),
)
class UberQuest(WordPressScraper):
name = 'StudioKhimera/UberQuest'
stripUrl = 'https://uberquest.studiokhimera.com/comic/page/%s/'
url = stripUrl % 'latest'
firstStripUrl = stripUrl % 'cover'
imageSearch = '//div[@class="prj--comic-image"]/img'
prevSearch = '//uq-image-button[d:class("prj--comic-control-prev")]'
def namer(self, imageUrl, pageUrl):
# Fix inconsistent filenames
filename = imageUrl.rsplit('/', 1)[-1]
filename = filename.replace('Page', 'UberQuest')
filename = filename.replace('UberQuest01.', 'UberQuest001.')
filename = filename.replace('UberQuest98.', 'UberQuest098.')
filename = filename.replace('UberQuest99.', 'UberQuest099.')
return filename

View file

@ -16,14 +16,6 @@ from .common import (ComicControlScraper, WordPressScraper, WordPressSpliced,
WordPressNavi, WordPressWebcomic) WordPressNavi, WordPressWebcomic)
class TailsAndTactics(_ParserScraper):
url = 'http://tailsandtactics.com/comic/'
stripUrl = url + '%s/'
firstStripUrl = stripUrl % '1'
imageSearch = '//div[@class="comic-image"]/img'
prevSearch = '//a[text()=" Back"]'
class TekMage(WordPressNavi): class TekMage(WordPressNavi):
url = 'https://tekmagecomic.com/' url = 'https://tekmagecomic.com/'
stripUrl = url + 'comic/%s/' stripUrl = url + 'comic/%s/'

View file

@ -66,6 +66,7 @@ class Tapas(ParserScraper):
cls('AmpleTime', 'Ample-Time'), cls('AmpleTime', 'Ample-Time'),
cls('FANGS', 'fangscomic'), cls('FANGS', 'fangscomic'),
cls('FishNuggets', 'Fish-Nuggets'), cls('FishNuggets', 'Fish-Nuggets'),
cls('Ginpu', 'Ginpu-Studios-Comics'),
cls('HoneyAndTheMoon', 'Honey-and-the-Moon'), cls('HoneyAndTheMoon', 'Honey-and-the-Moon'),
cls('InsignificantOtters', 'IOtters'), cls('InsignificantOtters', 'IOtters'),
cls('MagicalBoy', 'magicalboy'), cls('MagicalBoy', 'magicalboy'),

View file

@ -3,6 +3,7 @@
# Copyright (C) 2012-2014 Bastian Kleineidam # Copyright (C) 2012-2014 Bastian Kleineidam
# Copyright (C) 2015-2020 Tobias Gruetzmacher # Copyright (C) 2015-2020 Tobias Gruetzmacher
# Copyright (C) 2019-2020 Daniel Ring # Copyright (C) 2019-2020 Daniel Ring
import json
from re import compile from re import compile
from urllib.parse import urljoin from urllib.parse import urljoin
from lxml import etree from lxml import etree
@ -13,6 +14,28 @@ from ..util import tagre
from .common import ComicControlScraper, WordPressScraper, WordPressNavi from .common import ComicControlScraper, WordPressScraper, WordPressNavi
class UberQuest(ParserScraper):
baseUrl = 'https://uberquest.studiokhimera.com/'
url = baseUrl + 'wp-json/keeros_comics/v1/chapters'
stripUrl = baseUrl + 'wp-json/wp/v2/cfx_comic_page?page_number=%s'
firstStripUrl = stripUrl % 'cover'
def starter(self):
# Retrieve comic metadata from API
data = self.session.get(self.url)
data.raise_for_status()
return self.stripUrl % data.json()[-1]['pages'][-1]['page_number']
def getPrevUrl(self, url, data):
return self.stripUrl % json.loads(data.text_content())[0]['prev_id']
def fetchUrls(self, url, data, urlSearch):
return [json.loads(data.text_content())[0]['attachment']]
def namer(self, imageUrl, pageUrl):
return 'UberQuest-' + pageUrl.rsplit('=', 1)[-1]
class Underling(WordPressNavi): class Underling(WordPressNavi):
url = ('https://web.archive.org/web/20190806120425/' url = ('https://web.archive.org/web/20190806120425/'
'http://underlingcomic.com/') 'http://underlingcomic.com/')

View file

@ -3,28 +3,10 @@
# Copyright (C) 2012-2014 Bastian Kleineidam # Copyright (C) 2012-2014 Bastian Kleineidam
# Copyright (C) 2015-2020 Tobias Gruetzmacher # Copyright (C) 2015-2020 Tobias Gruetzmacher
# Copyright (C) 2019-2020 Daniel Ring # Copyright (C) 2019-2020 Daniel Ring
from ..scraper import _ParserScraper from ..scraper import ParserScraper, _ParserScraper
from ..helpers import bounceStarter, indirectStarter from ..helpers import bounceStarter, indirectStarter
class VampireHunterBoyfriends(_ParserScraper):
baseUrl = 'https://boneitisindustries.com/'
url = baseUrl + 'comics/vampire-hunter-boyfriends/'
stripUrl = baseUrl + 'comic/%s/'
firstStripUrl = stripUrl % 'vampire-hunter-boyfriends-chapter-1-cover'
imageSearch = '//div[@id="content"]//img[d:class("size-full")]'
prevSearch = '//a[./span[d:class("ticon-chevron-left")]]'
adult = True
def starter(self):
archivePage = self.getPage(self.url)
self.archive = archivePage.xpath('//div[contains(@class, "vcex-portfolio-grid")]//a/@href')
return self.archive[-1]
def getPrevUrl(self, url, data):
return self.archive[self.archive.index(url) - 1]
class Vexxarr(_ParserScraper): class Vexxarr(_ParserScraper):
baseUrl = 'http://www.vexxarr.com/' baseUrl = 'http://www.vexxarr.com/'
url = baseUrl + 'Index.php' url = baseUrl + 'Index.php'
@ -82,3 +64,11 @@ class VirmirWorld(_ParserScraper):
def getIndexStripUrl(self, index): def getIndexStripUrl(self, index):
index = index.split('-') index = index.split('-')
return self.stripUrl % (index[0], index[1]) return self.stripUrl % (index[0], index[1])
class Vreakerz(ParserScraper):
url = 'http://vreakerz.angrykitten.nl/'
stripUrl = url + 'stories/read/%s'
firstStripUrl = stripUrl % '1'
imageSearch = '//img[contains(@src, "storypages")]'
prevSearch = '//a[@class="btn-prior"]'

View file

@ -5,7 +5,7 @@
# Copyright (C) 2019-2020 Daniel Ring # Copyright (C) 2019-2020 Daniel Ring
from re import compile, escape, IGNORECASE from re import compile, escape, IGNORECASE
from ..scraper import _BasicScraper, _ParserScraper from ..scraper import ParserScraper, _BasicScraper, _ParserScraper
from ..util import tagre from ..util import tagre
from ..helpers import bounceStarter from ..helpers import bounceStarter
from .common import ComicControlScraper, WordPressScraper, WordPressNaviIn, WordPressWebcomic from .common import ComicControlScraper, WordPressScraper, WordPressNaviIn, WordPressWebcomic
@ -36,13 +36,12 @@ class WebcomicName(_ParserScraper):
multipleImagesPerStrip = True multipleImagesPerStrip = True
class Weregeek(_ParserScraper): class Weregeek(ParserScraper):
url = 'http://www.weregeek.com/' url = 'http://www.weregeek.com/'
stripUrl = url + '%s/' stripUrl = url + 'comic/%s/'
firstStripUrl = stripUrl % '2006/11/27' firstStripUrl = stripUrl % 'comic-1'
imageSearch = '//div[@id="comic"]/img' imageSearch = '//div[d:class("webcomic-media")]//img'
prevSearch = '//a[./img[@alt="Previous"]]' prevSearch = '//a[d:class("previous-webcomic-link")]'
help = 'Index format: yyyy/mm/dd'
class WereIWolf(_ParserScraper): class WereIWolf(_ParserScraper):

View file

@ -87,6 +87,7 @@ class WebToons(ParserScraper):
cls('BehindTheGIFs', 'comedy/behind-the-gifs', 658), cls('BehindTheGIFs', 'comedy/behind-the-gifs', 658),
cls('BigJo', 'romance/big-jo', 854), cls('BigJo', 'romance/big-jo', 854),
cls('BiteMe', 'thriller/bite-me', 1019), cls('BiteMe', 'thriller/bite-me', 1019),
cls('BitterSweetCoffee', 'challenge/bitter-sweet-coffee', 797203),
cls('Blackened', 'challenge/blackened', 363805), cls('Blackened', 'challenge/blackened', 363805),
cls('BladesOfFurry', 'romance/blades-of-furry', 2383), cls('BladesOfFurry', 'romance/blades-of-furry', 2383),
cls('Blessed', 'drama/blessed', 1193), cls('Blessed', 'drama/blessed', 1193),
@ -105,6 +106,7 @@ class WebToons(ParserScraper):
cls('CARL', 'slice-of-life/carl', 1216), cls('CARL', 'slice-of-life/carl', 1216),
cls('Caster', 'action/caster', 1461), cls('Caster', 'action/caster', 1461),
cls('CastleSwimmer', 'fantasy/castle-swimmer', 1499), cls('CastleSwimmer', 'fantasy/castle-swimmer', 1499),
cls('CatchMeIfYouCan', 'challenge/catch-me-if-you-can-', 434808),
cls('Catharsis', 'fantasy/catharsis', 396), cls('Catharsis', 'fantasy/catharsis', 396),
cls('CatLoafAdventures', 'slice-of-life/cat-loaf-adventures', 1381), cls('CatLoafAdventures', 'slice-of-life/cat-loaf-adventures', 1381),
cls('CChansACatgirl', 'challenge/c-chans-a-catgirl', 263430), cls('CChansACatgirl', 'challenge/c-chans-a-catgirl', 263430),
@ -120,7 +122,7 @@ class WebToons(ParserScraper):
cls('CodeAdam', 'action/code-adam', 1657), cls('CodeAdam', 'action/code-adam', 1657),
cls('CookingComically', 'tiptoon/cooking-comically', 622), cls('CookingComically', 'tiptoon/cooking-comically', 622),
cls('Crumbs', 'romance/crumbs', 1648), cls('Crumbs', 'romance/crumbs', 1648),
cls('CrystalVirus', 'challenge/crystal-virus', 347038), cls('CrystalVirusOtherStory', 'challenge/crystal-virus-other-story', 837028),
cls('CupidsArrows', 'romance/cupids-arrows', 1538), cls('CupidsArrows', 'romance/cupids-arrows', 1538),
cls('CursedPrincessClub', 'comedy/cursed-princess-club', 1537), cls('CursedPrincessClub', 'comedy/cursed-princess-club', 1537),
cls('Cyberbunk', 'sf/cyberbunk', 466), cls('Cyberbunk', 'sf/cyberbunk', 466),
@ -273,6 +275,7 @@ class WebToons(ParserScraper):
cls('MidnightRain', 'drama/midnight-rain', 1797), cls('MidnightRain', 'drama/midnight-rain', 1797),
cls('MidnightRhapsody', 'slice-of-life/midnight-rhapsody', 116), cls('MidnightRhapsody', 'slice-of-life/midnight-rhapsody', 116),
cls('MidnightRhapsodySeason2', 'slice-of-life/midnight-rhapsody-season2', 365), cls('MidnightRhapsodySeason2', 'slice-of-life/midnight-rhapsody-season2', 365),
cls('Miez', 'sf/miez', 2719),
cls('MissAbbottAndTheDoctor', 'romance/miss-abbott-and-the-doctor', 707), cls('MissAbbottAndTheDoctor', 'romance/miss-abbott-and-the-doctor', 707),
cls('MonsterIsle', 'challenge/monster-isle', 531999), cls('MonsterIsle', 'challenge/monster-isle', 531999),
cls('MOONBEARD', 'comedy/moon-beard', 471), cls('MOONBEARD', 'comedy/moon-beard', 471),
@ -301,12 +304,12 @@ class WebToons(ParserScraper):
cls('NoScope', 'sports/no-scope', 1572), cls('NoScope', 'sports/no-scope', 1572),
cls('NotEvenBones', 'thriller/not-even-bones', 1756), cls('NotEvenBones', 'thriller/not-even-bones', 1756),
cls('NothingSpecial', 'fantasy/nothing-special', 1188), cls('NothingSpecial', 'fantasy/nothing-special', 1188),
cls('NotSoLucky', 'challenge/not-so-lucky', 673387),
cls('OddGirlOut', 'drama/odd-girl-out', 1420), cls('OddGirlOut', 'drama/odd-girl-out', 1420),
cls('OhHoly', 'romance/oh-holy', 809), cls('OhHoly', 'romance/oh-holy', 809),
cls('OmniscientReader', 'action/omniscient-reader', 2154), cls('OmniscientReader', 'action/omniscient-reader', 2154),
cls('ORANGEMARMALADE', 'romance/orange-marmalade', 97), cls('ORANGEMARMALADE', 'romance/orange-marmalade', 97),
cls('Outrage', 'super-hero/outrage', 1450), cls('Outrage', 'super-hero/outrage', 1450),
cls('OVERPOWERED', 'challenge/overpowered', 85292),
cls('PacificRimAmara', 'sf/pacific-rim-amara', 1327), cls('PacificRimAmara', 'sf/pacific-rim-amara', 1327),
cls('PandorasBlogs', 'challenge/pandoras-blogs', 532007), cls('PandorasBlogs', 'challenge/pandoras-blogs', 532007),
cls('PaperRoses', 'challenge/paper-roses', 39736), cls('PaperRoses', 'challenge/paper-roses', 39736),
@ -401,6 +404,7 @@ class WebToons(ParserScraper):
cls('TheRoomies', 'challenge/the-roomies-archive', 513669), cls('TheRoomies', 'challenge/the-roomies-archive', 513669),
cls('TheShadowProphet', 'drama/the-shadow-prophet', 1881), cls('TheShadowProphet', 'drama/the-shadow-prophet', 1881),
cls('TheSoundOfYourHeart', 'comedy/the-sound-of-your-heart', 269), cls('TheSoundOfYourHeart', 'comedy/the-sound-of-your-heart', 269),
cls('TheSpectrumOfUs', 'challenge/the-spectrum-of-us', 334525),
cls('TheSteamDragonExpress', 'fantasy/steam-dragon-express', 1270), cls('TheSteamDragonExpress', 'fantasy/steam-dragon-express', 1270),
cls('TheStoriesOfThoseAroundMe', 'romance/the-stories-of-those-around-me', 96), cls('TheStoriesOfThoseAroundMe', 'romance/the-stories-of-those-around-me', 96),
cls('TheStrangeTalesOfOscarZahn', 'fantasy/the-strange-tales-of-oscar-zahn', 685), cls('TheStrangeTalesOfOscarZahn', 'fantasy/the-strange-tales-of-oscar-zahn', 685),
@ -453,6 +457,7 @@ class WebToons(ParserScraper):
cls('WitchCreekRoad', 'horror/witch-creek-road', 1453), cls('WitchCreekRoad', 'horror/witch-creek-road', 1453),
cls('WitchHunt', 'supernatural/witch-hunt', 363), cls('WitchHunt', 'supernatural/witch-hunt', 363),
cls('Wolfsbane', 'horror/wolfsbane', 1826), cls('Wolfsbane', 'horror/wolfsbane', 1826),
cls('WorldsStrongestTroll', 'fantasy/worlds-strongest-troll', 5315),
cls('XINK3R', 'super-hero/xinker', 541), cls('XINK3R', 'super-hero/xinker', 541),
cls('YourAdventure', 'comedy/your-adventure', 506), cls('YourAdventure', 'comedy/your-adventure', 506),
cls('YourLetter', 'drama/your-letter', 1540), cls('YourLetter', 'drama/your-letter', 1540),