Merge pull request #184 from Techwolfy/upstream-new-comics-2

Add 29 comics, fix bug in MangaDex completion detection
This commit is contained in:
Tobias Gruetzmacher 2021-03-19 14:04:33 +01:00 committed by GitHub
commit 87549b951a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
19 changed files with 153 additions and 59 deletions

View file

@ -99,22 +99,9 @@ class Beetlebum(_BasicScraper):
class Bethellium(_WPWebcomic):
stripUrl = 'http://dbcomics.darkblueworkshop.com/bethellium/%s/'
firstStripUrl = stripUrl % 'chapter-1/cover'
url = firstStripUrl
latestSearch = '//main' + _WPWebcomic.latestSearch
starter = indirectStarter
def getPrevUrl(self, url, data):
prevUrl = super(Bethellium, self).getPrevUrl(url, data)
return prevUrl.replace('%webcomic2_storyline%', 'chapter-2-the-hemlocks-scar')
def namer(self, imageUrl, pageUrl):
# Prepend chapter title to page filenames
chapter = pageUrl.rstrip('/').rsplit('/', 3)[-2]
chapter = chapter.replace('chapter-1', 'chapter-1-the-magic-city')
page = imageUrl.rsplit('/', 1)[-1]
return chapter + '_' + page
url = 'https://bethellium.darkbluecomics.com/'
stripUrl = url + 'comic/%s/'
firstStripUrl = stripUrl % 'cover'
class BetterDays(_ParserScraper):
@ -349,3 +336,10 @@ class ButterSafe(_ParserScraper):
imageSearch = '//div[@id="comic"]/img'
prevSearch = '//a[@rel="prev"]'
help = 'Index format: yyyy/mm/dd/stripname'
class ByTheBook(_WordPressScraper):
url = 'http://www.btbcomic.com/'
stripUrl = url + 'comic/%s/'
firstStripUrl = stripUrl % 'chapter-1-page-0'
adult = True

View file

@ -286,7 +286,7 @@ class CollegeCatastrophe(_ParserScraper):
stripUrl = url + '/%s'
firstStripUrl = stripUrl % '2000-11-10'
imageSearch = '//img[@class="comic-image"]'
prevSearch = '//a[span[contains(text(),"Previous")]]'
prevSearch = '//a[./span[contains(text(), "Previous")]]'
endOfLife = True
multipleImagesPerStrip = True

View file

@ -49,7 +49,7 @@ class ComicFury(_ParserScraper):
help = 'Index format: n'
starter = bounceStarter
def __init__(self, name, sub, lang=None, adult=False):
def __init__(self, name, sub, lang=None, adult=False, endOfLife=False):
super(ComicFury, self).__init__('ComicFury/' + name)
self.prefix = name
self.url = 'http://%s.webcomic.ws/comics/' % sub
@ -59,6 +59,8 @@ class ComicFury(_ParserScraper):
self.lang = lang
if adult:
self.adult = adult
if endOfLife:
self.endOfLife = endOfLife
def namer(self, image_url, page_url):
parts = page_url.split('/')
@ -638,6 +640,7 @@ class ComicFury(_ParserScraper):
cls('MaxFuture', 'maxfuture'),
cls('MAYBELOVE', 'emmacomics'),
cls('MayonakaDensha', 'mayonakadensha'),
cls('MayTheRainCome', 'maytheraincome', endOfLife=True),
cls('MegaMaidenVSTheChopChopPrincess', 'megamaiden'),
cls('MeganKearneysBeautyAndTheBeast', 'batb'),
cls('MelancholyGoRound', 'melancholygoround'),

View file

@ -19,7 +19,7 @@ class _WordPressScraper(_ParserScraper):
class _WordPressSpliced(_ParserScraper):
imageSearch = '//div[@id="spliced-comic"]//img'
imageSearch = '//div[@id="one-comic-option"]//img'
prevSearch = '//a[d:class("previous-comic")]'

View file

@ -365,6 +365,14 @@ class Drowtales(_ParserScraper):
help = 'Index format: number'
class DungeonsAndDenizens(_WPNavi):
url = ('https://web.archive.org/web/20160308001834/'
'http://dungeond.com/')
stripUrl = url + '%s/'
firstStripUrl = stripUrl % '2005/08/23/08232005'
endOfLife = True
class DumbingOfAge(_WPNavi):
url = 'http://www.dumbingofage.com/'
stripUrl = url + '%s/'

View file

@ -20,6 +20,15 @@ class FalconTwin(_BasicScraper):
help = 'Index format: nnn'
class FalseStart(_ParserScraper):
url = 'https://boneitiscomics.com/falsestart.php'
stripUrl = url + '?pg=%s'
firstStripUrl = stripUrl % '1'
imageSearch = '//div[@class="page"]//img'
prevSearch = '//a[@id="prev"]'
adult = True
class Faneurysm(_WPNaviIn):
url = 'http://hijinksensue.com/comic/think-only-tree/'
firstStripUrl = 'http://hijinksensue.com/comic/captains-prerogative/'

View file

@ -46,10 +46,16 @@ class LazJonesAndTheMayfieldRegulators(_ParserScraper):
class LazJonesAndTheMayfieldRegulatorsSideStories(LazJonesAndTheMayfieldRegulators):
name = 'LazJonesAndTheMayfieldRegulators/SideStories'
baseUrl = 'https://www.lazjones.com/'
url = baseUrl + 'sidestories'
url = baseUrl + 'comics'
stripUrl = baseUrl + 'comic/%s'
firstStripUrl = stripUrl % 'journal01'
def getPrevUrl(self, url, data):
# Fix broken navigation links
if url == self.url and data.xpath(self.prevSearch + '/@href')[0] == self.stripUrl % 'summer00':
return self.stripUrl % 'summer21'
return super(LazJonesAndTheMayfieldRegulators, self).getPrevUrl(url, data)
class LeastICouldDo(_ParserScraper):
url = 'https://leasticoulddo.com/'

View file

@ -84,6 +84,15 @@ class MarriedToTheSea(_ParserScraper):
return '%s-%s' % (date, filename)
class MarryMe(_ParserScraper):
url = 'http://marryme.keenspot.com/'
stripUrl = url + 'd/%s.html'
firstStripUrl = stripUrl % '20120730'
imageSearch = '//img[@class="ksc"]'
prevSearch = '//a[@rel="prev"]'
endOfLife = True
class MaxOveracts(_ParserScraper):
url = 'http://occasionalcomics.com/'
stripUrl = url + '%s/'
@ -179,26 +188,16 @@ class MonsieurLeChien(_BasicScraper):
class Moonlace(_WPWebcomic):
stripUrl = 'http://dbcomics.darkblueworkshop.com/moonlace/%s/'
firstStripUrl = stripUrl % 'prologue/page-1'
url = firstStripUrl
latestSearch = '//main' + _WPWebcomic.latestSearch
url = 'https://moonlace.darkbluecomics.com/'
stripUrl = url + 'comic/%s/'
firstStripUrl = stripUrl % 'page-0-1'
adult = True
def starter(self):
# Set age-gate cookie
self.session.cookies.set('age_gate', '1', domain='darkblueworkshop.com')
self.session.cookies.set('age_gate', '1', domain='moonlace.darkblueworkshop.com')
return indirectStarter(self)
def namer(self, imageUrl, pageUrl):
# Prepend chapter title to page filenames
chapter = pageUrl.rstrip('/').rsplit('/', 3)[-2]
chapter = chapter.replace('prologue', 'chapter-0-prologue')
chapter = chapter.replace('chapter-1', 'chapter-1-heritage')
chapter = chapter.replace('chapter2', 'chapter-2')
page = imageUrl.rsplit('/', 1)[-1]
return chapter + '_' + page
class Moonsticks(_ParserScraper):
url = "http://moonsticks.org/"

View file

@ -25,6 +25,8 @@ class MangaDex(_ParserScraper):
mangaData = manga.json()
# Determine if manga is complete and/or adult
if mangaData['manga']['last_chapter'] != '0':
for ch in mangaData['chapter']:
if mangaData['chapter'][ch]['chapter'] == mangaData['manga']['last_chapter']:
self.endOfLife = True
if mangaData['manga']['hentai'] != '0':
self.adult = True
@ -71,8 +73,11 @@ class MangaDex(_ParserScraper):
return (
cls('AttackonTitan', 429),
cls('Beastars', 20523),
cls('BokuNoKokoroNoYabaiYatsu', 23811),
cls('DeliciousinDungeon', 13871),
cls('DragonDrive', 5165),
cls('FuguushokuKajishiDakedoSaikyouDesu', 56319),
cls('GanbareDoukiChan', 46585),
cls('HangingOutWithAGamerGirl', 42490),
cls('HoriMiya', 6770),
cls('HowToOpenATriangularRiceball', 19305),
@ -84,19 +89,23 @@ class MangaDex(_ParserScraper):
cls('Lv2KaraCheatDattaMotoYuushaKouhoNoMattariIsekaiLife', 33797),
cls('MaouNoOreGaDoreiElfWoYomeNiShitandaGaDouMederebaIi', 25495),
cls('ModernMoGal', 30308),
cls('MyTinySenpaiFromWork', 43610),
cls('OMaidensinYourSavageSeason', 22030),
cls('OokamiShounenWaKyouMoUsoOKasaneru', 14569),
cls('OokamiToKoshinryou', 1168),
cls('OtomeYoukaiZakuro', 4533),
cls('OversimplifiedSCP', 32834),
cls('PashiriNaBokuToKoisuruBanchouSan', 25862),
cls('PleaseDontBullyMeNagatoro', 22631),
cls('PleaseDontBullyMeNagatoroComicAnthology', 31004),
cls('PleaseTellMeGalkochan', 12702),
cls('SaekiSanWaNemutteru', 28834),
cls('SenpaiGaUzaiKouhaiNoHanashi', 23825),
cls('SewayakiKitsuneNoSenkoSan', 22723),
cls('SousouNoFrieren', 48045),
cls('SwordArtOnline', 1360),
cls('SwordArtOnlineProgressive', 9604),
cls('TamenDeGushi', 13939),
cls('TheWolfAndRedRidingHood', 31079),
cls('TomoChanWaOnnanoko', 15722),
cls('TonikakuKawaii', 23439),

View file

@ -153,7 +153,7 @@ class NineToNine(_ParserScraper):
stripUrl = url + '/%s'
firstStripUrl = stripUrl % '2014-01-01'
imageSearch = '//img[@class="comic-image"]'
prevSearch = '//a[@class="prev"]'
prevSearch = '//a[./span[contains(text(), "Previous")]]'
multipleImagesPerStrip = True

View file

@ -214,7 +214,6 @@ class Removed(Scraper):
cls('DamnLol'),
cls('DeathToTheExtremist'),
cls('DoctorCat', 'brk'),
cls('DungeonsAndDenizens'),
cls('EerieCuties'),
cls('Ellerbisms'),
cls('Eriadan'),
@ -630,8 +629,6 @@ class Removed(Scraper):
cls('ComicFury/TheUnthinkableHybrid'),
cls('ComicFury/TwentyFourSeven'),
cls('ComicFury/TwentyFourSevenFans'),
cls('TheCyantianChronicles/CookieCaper'),
cls('TheCyantianChronicles/Pawprints'),
cls('GoComics/2CowsAndAChicken'),
cls('GoComics/AskAPortlySyndicatePerson'),
cls('GoComics/Bewley'),
@ -775,7 +772,6 @@ class Removed(Scraper):
cls('SmackJeeves/BoogeyDancingMonkeyPot'),
cls('SmackJeeves/BreachOfAgency'),
cls('SmackJeeves/Burn'),
cls('SmackJeeves/ByTheBook'),
cls('SmackJeeves/CafeSuada'),
cls('SmackJeeves/Cambion'),
cls('SmackJeeves/CaptiveSoul'),
@ -1271,6 +1267,8 @@ class Removed(Scraper):
cls('Shivae/Extras'),
cls('SnafuComics/Titan'),
cls('StuffNoOneToldMe'),
cls('TheCyantianChronicles/CookieCaper'),
cls('TheCyantianChronicles/Pawprints'),
cls('VictimsOfTheSystem'),
cls('WebDesignerCOTW'),
)
@ -1424,6 +1422,7 @@ class Renamed(Scraper):
cls('GoComics/WebcomicName', 'WebcomicName'),
cls('Shivae/BlackRose', 'BlackRose'),
cls('SmackJeeves/BlackTapestries', 'ComicFury/BlackTapestries'),
cls('SmackJeeves/ByTheBook', 'ByTheBook'),
cls('SmackJeeves/FurryExperience', 'ComicFury/FurryExperience'),
cls('SmackJeeves/GrowingTroubles', 'ComicFury/GrowingTroubles'),
cls('SmackJeeves/TheRealmOfKaerwyn', 'ComicFury/TheRealmOfKaerwyn'),

View file

@ -248,11 +248,12 @@ class PoppyOPossum(_WordPressScraper):
class PowerNap(_ParserScraper):
url = 'http://www.powernapcomic.com/'
url = 'https://www.powernapcomic.com/powernap/'
stripUrl = url + 'd/%s.html'
firstStripUrl = stripUrl % '20110617'
imageSearch = '//img[contains(@src, "/pnap")]'
imageSearch = '//center/img'
prevSearch = '//a[./img[contains(@src, "previous")]]'
endOfLife = True
def imageUrlModifier(self, url, data):
return url.replace('\n', '').strip()

View file

@ -11,7 +11,7 @@ class QuantumVibe(_ParserScraper):
stripUrl = url + 'strip?page=%s'
firstStripUrl = stripUrl % '1'
imageSearch = '//img[contains(@src, "disppageV3?story=qv")]'
prevSearch = '//a[./img[contains(@src, "nav/prevstrip")]]'
prevSearch = '//a[./img[@alt="Previous Strip"]]'
class QuestionableContent(_ParserScraper):

View file

@ -78,6 +78,23 @@ class RealmOfAtland(_BasicScraper):
help = 'Index format: nnn'
class Recursion(_ParserScraper):
url = 'https://recursioncomic.com/'
stripUrl = url + '%s'
firstStripUrl = stripUrl % '0001'
imageSearch = '//div[@class="content"]//img'
prevSearch = '//link[@rel="prev"]'
def namer(self, imageUrl, pageUrl):
# Fix inconsistent filenames
filename = imageUrl.rsplit('/', 1)[-1]
filename = filename.replace('0bf62e92-2c98-4fb2-8ed7-4584980beb17', 'page0005')
filename = filename.replace('76112837-c5cd-4df7-8c53-3ed5c25194cf', 'page0003')
filename = filename.replace('ed271080-6b1b-4d7a-8509-b2d8a15da805', 'page0002')
filename = filename.replace('7b194ef7-ac77-4b5c-aed0-826901d13d04', 'page0001')
return filename
class RedMeat(_ParserScraper):
url = 'http://www.redmeat.com/max-cannon/FreshMeat'
imageSearch = '//div[@class="comicStrip"]//img'

View file

@ -312,15 +312,21 @@ class SluggyFreelance(_ParserScraper):
class SMBC(_ComicControlScraper):
url = 'http://www.smbc-comics.com/'
firstStripUrl = url + 'comic/2002-09-05'
multipleImagesPerStrip = True
url = 'https://www.smbc-comics.com/'
stripUrl = url + 'comic/%s'
firstStripUrl = stripUrl % '2002-09-05'
imageSearch = ['//img[@id="cc-comic"]', '//div[@id="aftercomic"]/img']
textSearch = '//img[@id="cc-comic"]/@title'
multipleImagesPerStrip = True
def namer(self, image_url, page_url):
"""Remove random noise from name."""
return image_url.rsplit('-', 1)[-1]
def namer(self, imageUrl, pageUrl):
# Remove random noise from filename
filename = imageUrl.rsplit('/', 1)[-1]
if '-' in filename and len(filename.rsplit('-', 1)[-1]) > 12:
filename = filename.rsplit('-', 1)[-1]
elif len(filename) > 22 and filename[0] == '1':
filename = filename[10:]
return filename
class SnowFlame(_WordPressScraper):
@ -672,7 +678,7 @@ class Supercell(_ParserScraper):
url = 'https://www.supercellcomic.com/'
stripUrl = url + 'pages/%s.html'
firstStripUrl = stripUrl % '0001'
imageSearch = '//div[@class="comicpage"]//img'
imageSearch = '//img[@class="comicStretch"]'
prevSearch = '//div[@class="comicnav"]/a[./img[contains(@src, "comnav_02")]]'
@ -702,5 +708,5 @@ class SwordsAndSausages(_ParserScraper):
stripUrl = url + '/%s'
firstStripUrl = stripUrl % '1-1'
imageSearch = '//img[@class="comic-image"]'
prevSearch = '//a[@class="prev"]'
prevSearch = '//a[./span[contains(text(), "Previous")]]'
multipleImagesPerStrip = True

View file

@ -1,6 +1,6 @@
# SPDX-License-Identifier: MIT
# Copyright (C) 2019-2021 Tobias Gruetzmacher
# Copyright (C) 2019-2020 Daniel Ring
# Copyright (C) 2019-2021 Daniel Ring
from .common import _WordPressSpliced
@ -21,6 +21,12 @@ class AlienDice(_WordPressSpliced):
stripUrl = url + 'comic/%s/'
firstStripUrl = stripUrl % '05162001'
def getPrevUrl(self, url, data):
# Fix broken navigation
if url == self.stripUrl % 'day-29-part-2-page-3-4':
return self.stripUrl % 'day-29-part-2-page-3-2'
return super(AlienDice, self).getPrevUrl(url, data)
def namer(self, imageUrl, pageUrl):
# Fix inconsistent filename
return imageUrl.rsplit('/', 1)[-1].replace('20010831', '2001-08-31')
@ -28,12 +34,16 @@ class AlienDice(_WordPressSpliced):
class AlienDiceLegacy(_WordPressSpliced):
name = 'AlienDice/Legacy'
url = 'https://aliendice.com/chapter/legacy/'
stripUrl = url + 'page/%s/'
firstStripUrl = stripUrl % '45'
prevSearch = '//div[d:class("nav-previous")]/a'
baseUrl = 'https://aliendice.com/'
url = baseUrl + 'series/legacy/'
stripUrl = baseUrl + 'comic/%s/'
firstStripUrl = stripUrl % 'legacy-1'
endOfLife = True
def isfirststrip(self, url):
# Strip series identifier
return super(AlienDiceLegacy, self).isfirststrip(url.rsplit('?', 1)[0])
class BlackRose(_WordPressSpliced):
url = 'https://www.blackrose.monster/'
@ -60,9 +70,9 @@ class TheCyantianChronicles(_WithSid):
cls('CesileesDiary', 'cesilees-diary', '12062001-2', 16726, eol=True),
cls('Darius', 'darius', '03102010', 14353, eol=True),
cls('DracoVulpes', 'draco-vulpes', 'draco-vulpes', 13788),
cls('GenoworksSaga', 'genoworks-saga', '07012004', 13794, eol=True),
cls('GenoworksSaga', 'genoworks-saga', '07012004', 13794),
cls('GralenCraggHall', 'kiet', '07152002', 13798, eol=True),
cls('Kiet', 'kiet-2', 'kiet-c01', 14351, eol=True),
cls('Kiet', 'kiet-2', 'kiet-c01', 14351),
cls('NoAngel', 'no-angel', '08112001', 16644, eol=True),
cls('RandomRamblings', 'gallery', 'cookie-war', 13801),
cls('SinkOrSwim', 'sink-or-swim', '05112001', 13796, eol=True),
@ -77,7 +87,7 @@ class Shivae(_WordPressSpliced):
class ShivaeComics(_WithSid):
baseUrl = 'https://shivae.net/index.php/'
baseUrl = 'https://shivae.net/'
def __init__(self, name, path, first, sid, eol=False):
super().__init__('Shivae/' + name, sid)

View file

@ -23,6 +23,14 @@ class TailsAndTactics(_ParserScraper):
prevSearch = '//a[text()=" Back"]'
class TaleOfTenThousand(_ParserScraper):
url = 'http://www.t10k.club/'
stripUrl = url + 'comic/%s'
firstStripUrl = stripUrl % '1-01_00'
imageSearch = '//article[@id="comic"]//img'
prevSearch = '//a[d:class("prev")]'
class TekMage(_WPNavi):
url = 'https://tekmagecomic.com/'
stripUrl = url + 'comic/%s/'

View file

@ -7,6 +7,15 @@ from ..scraper import _ParserScraper
from ..helpers import bounceStarter, indirectStarter
class VampireHunterBoyfriends(_ParserScraper):
url = 'https://boneitiscomics.com/vhb.php'
stripUrl = url + '?pg=%s'
firstStripUrl = stripUrl % '1'
imageSearch = '//div[@class="page"]//img'
prevSearch = '//a[@id="prev"]'
adult = True
class Vexxarr(_ParserScraper):
baseUrl = 'http://www.vexxarr.com/'
url = baseUrl + 'Index.php'

View file

@ -87,6 +87,8 @@ class WebToons(_ParserScraper):
cls('BehindTheGIFs', 'comedy/behind-the-gifs', 658),
cls('BigJo', 'romance/big-jo', 854),
cls('BiteMe', 'thriller/bite-me', 1019),
cls('Blackened', 'challenge/blackened', 363805),
cls('BladesOfFurry', 'romance/blades-of-furry', 2383),
cls('Blessed', 'drama/blessed', 1193),
cls('BloodInk', 'action/blood-ink', 1490),
cls('BloodlessWars', 'sf/bloodless-wars', 1622),
@ -109,19 +111,23 @@ class WebToons(_ParserScraper):
cls('CherryBlossoms', 'romance/cherry-blossoms', 1005),
cls('Chiller', 'thriller/chiller', 536),
cls('ChocoLatte', 'romance/choco-latte', 1691),
cls('CChansACatgirl', 'challenge/c-chans-a-catgirl', 263430),
cls('CityOfBlank', 'sf/city-of-blank', 1895),
cls('CityOfWalls', 'drama/city-of-wall', 505),
cls('CityVamps', 'challenge/city-vamps-', 119224),
cls('ClusterFudge', 'slice-of-life/cluster-fudge', 355),
cls('CodeAdam', 'action/code-adam', 1657),
cls('CookingComically', 'tiptoon/cooking-comically', 622),
cls('CrapIDrewOnMyLunchBreak', 'challenge/crap-i-drew-on-my-lunch-break', 124756),
cls('Crumbs', 'romance/crumbs', 1648),
cls('CrystalVirus', 'challenge/crystal-virus', 347038),
cls('CupidsArrows', 'romance/cupids-arrows', 1538),
cls('CursedPrincessClub', 'comedy/cursed-princess-club', 1537),
cls('Cyberbunk', 'sf/cyberbunk', 466),
cls('Cyberforce', 'super-hero/cyberforce', 531),
cls('CykoKO', 'super-hero/cyko-ko', 560),
cls('Darbi', 'action/darbi', 1098),
cls('DatingWithATail', 'romance/dating-with-a-tail', 1263),
cls('Davinchibi', 'fantasy/davinchibi', 1190),
cls('DaYomanvilleGang', 'drama/da-yomanville-gang', 1578),
cls('DaysOfHana', 'drama/days-of-hana', 1246),
@ -140,6 +146,7 @@ class WebToons(_ParserScraper):
cls('DownToEarth', 'romance/down-to-earth', 1817),
cls('Dragnarok', 'fantasy/dragnarok', 1018),
cls('DragnarokDescendants', 'fantasy/dragnarok-descendants', 1433),
cls('DrawnToYou', 'challenge/drawn-to-you', 172022),
cls('DrFrost', 'drama/dr-frost', 371),
cls('DungeonMinis', 'challenge/dungeonminis', 64132),
cls('Dustinteractive', 'comedy/dustinteractive', 907),
@ -167,6 +174,7 @@ class WebToons(_ParserScraper):
cls('FourLeaf', 'fantasy/four-leaf', 1454),
cls('FreakingRomance', 'romance/freaking-romance', 1467),
cls('FridayForbiddenTales', 'thriller/friday', 388),
cls('FutureYou', 'challenge/future-you', 288439),
cls('GameMasters', 'challenge/game-masters', 237252),
cls('GenshinImpact', 'challenge/genshin-impact', 242646),
cls('Gepetto', 'sf/gepetto', 81),
@ -212,6 +220,7 @@ class WebToons(_ParserScraper):
cls('JingleJungle', 'slice-of-life/jingle-jungle', 282),
cls('JustAskYuli', 'slice-of-life/just-ask-yuli', 402),
cls('JustForKicks', 'slice-of-life/just-for-kicks', 1152),
cls('JustFriends', 'challenge/just-friends', 190722),
cls('JustPancakes', 'comedy/just-pancakes', 1651),
cls('KidsAreAllRight', 'drama/kids-are-all-right', 283),
cls('Killstagram', 'thriller/killstagram', 1971),
@ -237,6 +246,7 @@ class WebToons(_ParserScraper):
cls('Lorna', 'slice-of-life/lorna', 1284),
cls('LostInTranslation', 'drama/lost-in-translation', 1882),
cls('LoveAdviceFromTheGreatDukeOfHell', 'comedy/love-advice', 1498),
cls('LoveMeKnot', 'romance/love-me-knot', 2224),
cls('Lozolz', 'tiptoon/lozolz', 1268),
cls('LUFF', 'romance/luff', 1489),
cls('Luggage', 'fantasy/luggage', 1642),
@ -263,9 +273,11 @@ class WebToons(_ParserScraper):
cls('Murrz', 'slice-of-life/murrz', 1281),
cls('Muted', 'supernatural/muted', 1566),
cls('MyBoo', 'supernatural/my-boo', 1185),
cls('MyAssassinGirlfriend', 'challenge/my-assassin-girlfriend', 249007),
cls('MyDearColdBloodedKing', 'romance/my-dear-cold-blooded-king', 961),
cls('MyDeepestSecret', 'thriller/my-deepest-secret', 1580),
cls('MyDictatorBoyfriend', 'comedy/my-dictator-boyfriend', 1391),
cls('MyDragonGirlfriend', 'challenge/my-dragon-girlfriend', 162918),
cls('MyGiantNerdBoyfriend', 'slice-of-life/my-giant-nerd-boyfriend', 958),
cls('MyKittyAndOldDog', 'slice-of-life/my-kitty-and-old-dog', 184),
cls('MyNameIsBenny', 'slice-of-life/my-name-is-benny', 1279),
@ -290,7 +302,9 @@ class WebToons(_ParserScraper):
cls('OVERPOWERED', 'challenge/overpowered', 85292),
cls('PacificRimAmara', 'sf/pacific-rim-amara', 1327),
cls('PenguinLovesMev', 'slice-of-life/penguin-loves-mev', 86),
cls('Petrichor', 'challenge/petrichor', 100835),
cls('PhantomParadise', 'fantasy/phantom-paradise', 1250),
cls('Phase', 'romance/phase', 2117),
cls('Pigminted', 'slice-of-life/pigminted', 482),
cls('PinchPoint', 'challenge/pinch-point-reborn', 334640),
cls('Plum', 'sports/plum', 1605),
@ -335,6 +349,7 @@ class WebToons(_ParserScraper):
cls('SoulOnHold', 'supernatural/soul-on-hold', 1701),
cls('SpaceBoy', 'sf/space-boy', 400),
cls('SpaceVixen', 'challenge/space-vixen-deep-space-k9', 207049),
cls('SpellsFromHell', 'fantasy/spells-from-hell', 2431),
cls('SpiritFingers', 'drama/spirit-fingers', 1577),
cls('Spirits', 'fantasy/spirits-re', 1348),
cls('StalkerXStalker', 'challenge/stalker-x-stalker', 245662),
@ -421,6 +436,7 @@ class WebToons(_ParserScraper):
cls('XINK3R', 'super-hero/xinker', 541),
cls('YourAdventure', 'comedy/your-adventure', 506),
cls('YourLetter', 'drama/your-letter', 1540),
cls('YouveGottaBeKittenMe', 'challenge/youve-gotta-be-kitten-me', 383661),
cls('YumisCells', 'slice-of-life/yumi-cell', 478),
cls('YunaAndKawachan', 'drama/yuna-and-kawachan', 1840),
cls('ZeroGame', 'fantasy/zero-game', 1704),