From e5d9002f09eac7ad573ca0f435e6f2388b105782 Mon Sep 17 00:00:00 2001 From: Bastian Kleineidam Date: Wed, 5 Dec 2012 21:52:52 +0100 Subject: [PATCH] Fix more comics. --- Makefile | 2 +- dosagelib/comic.py | 4 +- dosagelib/plugins/keenspot.py | 9 +- dosagelib/plugins/nuklearpower.py | 7 +- dosagelib/plugins/smackjeeves.py | 7 +- dosagelib/plugins/snafu.py | 2 - dosagelib/plugins/universal.py | 4 +- dosagelib/plugins/webcomicnation.py | 8 +- dosagelib/scraper.py | 6 + dosagelib/util.py | 31 ++- scripts/drunkduck.py | 2 +- scripts/gocomics.json | 2 +- scripts/keenspot.py | 291 +++++++++++++++++++++++++++- scripts/mktestpage.py | 19 +- scripts/universal.py | 14 ++ tests/test_comics.py | 2 +- 16 files changed, 366 insertions(+), 44 deletions(-) diff --git a/Makefile b/Makefile index 3b2e45e00..f4d09854b 100644 --- a/Makefile +++ b/Makefile @@ -68,7 +68,7 @@ pyflakes: pyflakes $(PY_FILES_DIRS) count: - @sloccount dosage dosagelib | grep "Total Physical Source Lines of Code" + @sloccount $(PY_FILES_DIRS) | grep "Total Physical Source Lines of Code" clean: find . -name \*.pyc -delete diff --git a/dosagelib/comic.py b/dosagelib/comic.py index 5cc5ed90e..f7a2dc9fb 100644 --- a/dosagelib/comic.py +++ b/dosagelib/comic.py @@ -7,7 +7,7 @@ import rfc822 import time from .output import out -from .util import urlopen, normaliseURL, unquote, strsize +from .util import getImageObject, normaliseURL, unquote, strsize from .events import getHandler class FetchComicError(IOError): @@ -52,7 +52,7 @@ class ComicImage(object): def connect(self): """Connect to host and get meta information.""" try: - self.urlobj = urlopen(self.url, referrer=self.referrer) + self.urlobj = getImageObject(self.url, self.referrer) except IOError as msg: raise FetchComicError('Unable to retrieve URL.', self.url, msg) diff --git a/dosagelib/plugins/keenspot.py b/dosagelib/plugins/keenspot.py index b17c153f1..037679386 100644 --- a/dosagelib/plugins/keenspot.py +++ b/dosagelib/plugins/keenspot.py @@ -9,7 +9,10 @@ from ..util import tagre _imageSearch = compile(tagre("img", "src", r'([^"]*/comics/[^"]+)')) _prevSearch = compile(tagre("a", "href", r'([^"]*/d/\d{8}\.html)') + - '(?:Previous comic|'+tagre("img", "alt", "Previous comic")+')') + '(?:Previous comic' + '|' + + tagre("img", "alt", "Previous comic") + '|' + + tagre("img", "src", "images/back\.gif") + + ')') def add(name, url): classname = 'KeenSpot_%s' % name @@ -17,7 +20,9 @@ def add(name, url): @classmethod def _prevUrlModifier(cls, prevUrl): if prevUrl: - return prevUrl.replace("keenspace", "comicgenesis" + return prevUrl.replace("keenspace.com", "comicgenesis.com" + ).replace("keenspot.com", "comicgenesis.com" + ).replace("toonspace.com", "comicgenesis.com" ).replace("comicgen.com", "comicgenesis.com") globals()[classname] = make_scraper(classname, diff --git a/dosagelib/plugins/nuklearpower.py b/dosagelib/plugins/nuklearpower.py index f22d4ec1a..7c26c7517 100644 --- a/dosagelib/plugins/nuklearpower.py +++ b/dosagelib/plugins/nuklearpower.py @@ -6,16 +6,17 @@ from re import compile from ..scraper import make_scraper from ..util import tagre -_imageSearch = compile(tagre("img", "src", r'(http://www\.nuklearpower\.com/comics/[^"]+)')) +_imageSearch = compile(tagre("img", "src", r'(http://v\.cdn\.nuklearpower\.com/comics/[^"]+)')) _prevSearch = compile(tagre("a", "href", r'([^"]+)') + "Previous") def add(name, shortname): - baseUrl = 'http://www.nuklearpower.com/' + shortname + '/' + baseUrl = 'http://www.nuklearpower.com/' + latestUrl = baseUrl + shortname + '/' classname = 'NuklearPower_%s' % name globals()[classname] = make_scraper(classname, name='NuklearPower/' + name, - latestUrl = baseUrl, + latestUrl = latestUrl, stripUrl = baseUrl + '%s', imageSearch = _imageSearch, prevSearch = _prevSearch, diff --git a/dosagelib/plugins/smackjeeves.py b/dosagelib/plugins/smackjeeves.py index 8f6f0d383..43201bcef 100644 --- a/dosagelib/plugins/smackjeeves.py +++ b/dosagelib/plugins/smackjeeves.py @@ -8,8 +8,8 @@ from ..util import tagre _imageSearch = compile(tagre("img", "src", r'(http://(?:www|img2)\.smackjeeves\.com/images/uploaded/comics/[^"]+)')) _linkSearch = tagre("a", "href", r'([^"]*/comics/\d+/[^"]*)') -_prevSearch = compile(_linkSearch + '(?:]*alt="< Previous"|< Back)') -_nextSearch = compile(_linkSearch + '(?:]*alt="Next >"|Next >)') +_prevSearch = compile(_linkSearch + '(?:]*alt="< Previous"|< Back|. previous)') +_nextSearch = compile(_linkSearch + '(?:]*alt="Next >"|Next >|next )') def add(name): classname = 'SmackJeeves/' + name @@ -39,6 +39,3 @@ add('durian') add('heard') add('mpmcomic') add('nlmo-project') -add('paranoidloyd') -add('thatdreamagain') -add('wowcomics') diff --git a/dosagelib/plugins/snafu.py b/dosagelib/plugins/snafu.py index 9d8f127e3..2c72c9998 100644 --- a/dosagelib/plugins/snafu.py +++ b/dosagelib/plugins/snafu.py @@ -23,10 +23,8 @@ def add(name, host): ) -add('Grim', 'grim') add('KOF', 'kof') add('PowerPuffGirls', 'ppg') -add('Snafu', 'www') add('Tin', 'tin') add('TW', 'tw') add('Sugar', 'sugar') diff --git a/dosagelib/plugins/universal.py b/dosagelib/plugins/universal.py index c22dce8af..988f96ac2 100644 --- a/dosagelib/plugins/universal.py +++ b/dosagelib/plugins/universal.py @@ -18,7 +18,7 @@ _imageSearch = compile(tagre("img", "src", r'(http://assets\.amuniversal\.com/[^ def add(name, shortname): latestUrl = 'http://www.universaluclick.com%s' % shortname - classname = 'UClick_%s' % name + classname = 'Universal_%s' % name @classmethod def namer(cls, imageUrl, pageUrl): @@ -34,7 +34,7 @@ def add(name, shortname): return parse_strdate(strdate).strftime("%Y%m%d") globals()[classname] = make_scraper(classname, - name='UClick/' + name, + name='Universal/' + name, latestUrl = latestUrl, stripUrl = latestUrl + '%s/', imageSearch = _imageSearch, diff --git a/dosagelib/plugins/webcomicnation.py b/dosagelib/plugins/webcomicnation.py index 20a434df5..f9fe565da 100644 --- a/dosagelib/plugins/webcomicnation.py +++ b/dosagelib/plugins/webcomicnation.py @@ -17,18 +17,16 @@ def add(name, subpath): latestUrl = baseUrl + subpath, stripUrl = baseUrl + '?view=archive&chapter=%s', imageSearch = _imageSearch, + multipleImagesPerStrip = True, prevSearch = _prevSearch, + # the prevSearch is a redirect + prevUrlMatchesStripUrl = False, help = 'Index format: nnnn (non-contiguous)', ) add('AgnesQuill', 'daveroman/agnes/') -add('Elvenbaath', 'tdotodot2k/elvenbaath/') -add('IrrationalFears', 'uvernon/irrationalfears/') -add('KismetHuntersMoon', 'laylalawlor/huntersmoon/') -add('SaikoAndLavender', 'gc/saiko/') add('MyMuse', 'gc/muse/') add('NekkoAndJoruba', 'nekkoandjoruba/nekkoandjoruba/') add('JaxEpoch', 'johngreen/quicken/') -add('QuantumRockOfAges', 'DreamchildNYC/quantum/') add('ClownSamurai', 'qsamurai/clownsamurai/') diff --git a/dosagelib/scraper.py b/dosagelib/scraper.py index 2fe29146e..46d9104bc 100644 --- a/dosagelib/scraper.py +++ b/dosagelib/scraper.py @@ -22,11 +22,17 @@ class _BasicScraper(object): @cvar prevSearch: A compiled regex that will locate the URL for the previous strip when applied to a strip page. ''' + # if more than one image per URL is expected multipleImagesPerStrip = False + + # set to False if previous URLs do not match the strip URL (ie. because of redirects) + prevUrlMatchesStripUrl = True + # usually the index format help help = 'Sorry, no help for this comic yet.' + def __init__(self, indexes=None): """Initialize internal variables.""" self.urls = set() diff --git a/dosagelib/util.py b/dosagelib/util.py index 4cfd76f67..518034e4d 100644 --- a/dosagelib/util.py +++ b/dosagelib/util.py @@ -21,7 +21,12 @@ if os.name == 'nt': has_curses = has_module("curses") -MAX_FILESIZE = 1024*1024*1 # 1MB +# Maximum content size for HTML pages +MaxContentBytes = 1024 * 1024 * 2 # 2 MB + +# Maximum content size for images +MaxImageBytes = 1024 * 1024 * 20 # 20 MB + def tagre(tag, attribute, value, quote='"', before="", after=""): """Return a regular expression matching the given HTML tag, attribute @@ -71,9 +76,9 @@ def case_insensitive_re(name): baseSearch = re.compile(tagre("base", "href", '([^"]*)')) -def getPageContent(url): +def getPageContent(url, max_content_bytes=MaxContentBytes): # read page data - page = urlopen(url) + page = urlopen(url, max_content_bytes=max_content_bytes) data = page.text # determine base URL baseUrl = None @@ -85,6 +90,11 @@ def getPageContent(url): return data, baseUrl +def getImageObject(url, referrer, max_content_bytes=MaxImageBytes): + """Get response object for given image URL.""" + return urlopen(url, referrer=referrer, max_content_bytes=max_content_bytes) + + def fetchUrl(url, urlSearch): data, baseUrl = getPageContent(url) match = urlSearch.search(data) @@ -116,7 +126,6 @@ def fetchUrls(url, imageSearch, prevSearch=None): prevUrl = match.group(1) if not prevUrl: raise ValueError("Match empty previous URL at %s with pattern %s" % (url, prevSearch.pattern)) - out.write('matched previous URL %r' % prevUrl, 2) prevUrl = normaliseURL(urlparse.urljoin(baseUrl, prevUrl)) else: out.write('no previous URL %s at %s' % (prevSearch.pattern, url), 2) @@ -174,7 +183,7 @@ def normaliseURL(url): return urlparse.urlunparse(pu) -def urlopen(url, referrer=None, retries=3, retry_wait_seconds=5): +def urlopen(url, referrer=None, retries=3, retry_wait_seconds=5, max_content_bytes=None): out.write('Open URL %s' % url, 2) assert retries >= 0, 'invalid retry value %r' % retries assert retry_wait_seconds > 0, 'invalid retry seconds value %r' % retry_wait_seconds @@ -183,7 +192,8 @@ def urlopen(url, referrer=None, retries=3, retry_wait_seconds=5): if referrer: headers['Referer'] = referrer try: - req = requests.get(url, headers=headers, config=config) + req = requests.get(url, headers=headers, config=config, prefetch=False) + check_content_size(url, req.headers, max_content_bytes) req.raise_for_status() return req except requests.exceptions.RequestException as err: @@ -191,6 +201,15 @@ def urlopen(url, referrer=None, retries=3, retry_wait_seconds=5): out.write(msg) raise IOError(msg) +def check_content_size(url, headers, max_content_bytes): + if not max_content_bytes: + return + if 'content-length' in headers: + size = int(headers['content-length']) + if size > max_content_bytes: + msg = 'URL content of %s with %d Bytes exceeds %d Bytes.' % (url, size, max_content_bytes) + raise IOError(msg) + def get_columns (fp): """Return number of columns for given file.""" diff --git a/scripts/drunkduck.py b/scripts/drunkduck.py index 37de0e065..9739dde96 100755 --- a/scripts/drunkduck.py +++ b/scripts/drunkduck.py @@ -170,7 +170,7 @@ def handle_url(url, url_matcher, num_matcher, res): end = match.end(1) mo = num_matcher.search(data[end:]) if not mo: - print("ERROR:", repr(data[end:end+300], file=sys.stderr)) + print("ERROR:", repr(data[end:end+300]), file=sys.stderr) continue num = int(mo.group(1)) res[name] = num diff --git a/scripts/gocomics.json b/scripts/gocomics.json index 76e60d720..93ac58e8d 100644 --- a/scripts/gocomics.json +++ b/scripts/gocomics.json @@ -1 +1 @@ -{"060": "/0-60", "2CowsandaChicken": "/2cowsandachicken", "4PunkyPuppies": "/four-punky-puppies", "9ChickweedLane": "/9chickweedlane", "9to5": "/9to5", "ABenePlacito": "/a-bene-placito", "ACMEINKD": "/acme-inkd", "ARomanticLife": "/a-romantic-life", "Abaca": "/abaca", "AcadasiaDown": "/acadasia-down", "AdamAtHome": "/adamathome", "AdmiralSquirt": "/admiral-squirt", "AdultChildren": "/adult-children", "AdventuresofMartyandTurkey": "/marty-and-turkey", "AgainstTheGrain": "/against-the-grain", "Agnes": "/agnes", "AlisonWard": "/alison-ward", "AlleyOop": "/alley-oop", "AlmostGrounded": "/almost-grounded", "AmaZnEvents": "/amaznevents", "Andertoons": "/andertoons", "Andnow": "/and-now", "AndyCapp": "/andycapp", "Anecdote": "/anecdote", "AngryLittleGirls": "/angry-little-girls", "AnimalAntics": "/animal-antics", "AnimalCrackers": "/animalcrackers", "Annie": "/annie", "Apocalypseharry": "/apocalypseharry", "AppleCreekComics": "/apple-creek", "ArDuffle": "/arduffle", "ArloandJanis": "/arloandjanis", "AskShagg": "/askshagg", "Asymptote": "/asymptote", "BC": "/bc", "BERSERKALERT": "/berserk-alert", "BETWEENTHELINES": "/between-the-lines", "BUNS": "/buns", "BUSHYTALES": "/bushy-tales", "BackintheDay": "/backintheday", "BadReporter": "/badreporter", "Badlands": "/badlands", "Baldo": "/baldo", "BallardStreet": "/ballardstreet", "BananaTriangle": "/banana-triangle", "Barefoot": "/barefoot", "BarkeaterLake": "/barkeaterlake", "BarkingCrayon": "/barking-crayon", "BarneyAndClyde": "/barneyandclyde", "BasicInstructions": "/basicinstructions", "BatkidandBatrat": "/batkid-and-batrat", "BeMisery": "/bemisery", "Beanie": "/beanie", "Beardo": "/beardo", "Beebleville": "/beebleville", "Ben": "/ben", "BenSargent": "/bensargent", "BenjaminBreadman": "/benjamin-breadman", "BergerAndWyse": "/berger-and-wyse", "BestInShow": "/best-in-show", "Betty": "/betty", "Bewley": "/bewley", "BiffAndRiley": "/biff-and-riley", "BigMonkeyComic": "/big-monkey-comic", "BigNate": "/bignate", "BigTop": "/bigtop", "Biographic": "/biographic", "Birdbrains": "/birdbrains", "Bliss": "/bliss", "BloomCounty": "/bloomcounty", "BlueSkiestoons": "/blue-skies-toons", "Bluebonnets": "/cowsandstuff", "BoNanas": "/bonanas", "BobGorrell": "/bobgorrell", "BobtheSquirrel": "/bobthesquirrel", "Bonner": "/bonner", "Boomerangs": "/boomerangs", "Bottomliners": "/bottomliners", "BoundandGagged": "/boundandgagged", "BreakofDay": "/break-of-day", "Brevity": "/brevity", "BrewsterRockit": "/brewsterrockit", "BrilliantMines": "/brilliant-mines", "Broham": "/broham", "BroomHilda": "/broomhilda", "BubblesandSnail": "/bubbles-and-snail", "Buni": "/buni", "Buster": "/buster", "BuzzaWuzza": "/buzza-wuzza", "CAFFEINATED": "/CAFFEINATED", "CANDYBLONDELL": "/candyblondell", "CafconLeche": "/cafeconleche", "CalvinandHobbes": "/calvinandhobbes", "Candorville": "/candorville", "CaricaturesbyKerryWaghorn": "/facesinthenews", "CarlsLife": "/carlslife", "Cartertoons": "/cartertoons", "CaseyandKyle": "/casey-and-kyle", "Cathy": "/cathy", "CestlaVie": "/cestlavie", "ChanLowe": "/chanlowe", "CharmysArmy": "/charmy-s-army", "CheapThrillsCuisine": "/cheap-thrills-cuisine", "ChipBok": "/chipbok", "ChrisBritt": "/chrisbritt", "ChubbyGirlComics": "/chubbygirlcomics", "ChuckAsay": "/chuckasay", "ChuckleBros": "/chucklebros", "CircusPeople": "/circus-people", "CitizenDog": "/citizendog", "ClayBennett": "/claybennett", "ClayJones": "/clayjones", "Cleats": "/cleats", "ClosetoHome": "/closetohome", "CockroachComix": "/cockroachcomix", "CoffeeShopTidbits": "/coffee-shop-tidbits", "Committed": "/committed", "Computoon": "/compu-toon", "Confabulation": "/confabulation", "Cornered": "/cornered", "CowSheepandaGnomeNamedHelga": "/cow-sheep-and-a-gnome-named-helga", "CowTown": "/cowtown", "CowandBoy": "/cowandboy", "Crabbels": "/crabbels", "Creek": "/creek", "Critterdoodles": "/critterdoodles", "CrocAndGator": "/croc-and-gator", "Crumb": "/crumb", "CubienBouncy": "/cubie-n-bouncy", "CuldeSac": "/culdesac", "DALTONDOG": "/dalton-dog", "DaddysHome": "/daddyshome", "DailyPinky": "/daily-pinky", "DanWasserman": "/danwasserman", "DanaSummers": "/danasummers", "DarkSideoftheHorse": "/darksideofthehorse", "DarkWIndow": "/dark-window", "DeepCover": "/deepcover", "DellAndSteve": "/dell-steve", "DevinCraneComicStripGhostwriter": "/devincranecomicstripghostwriter", "DiamondLil": "/diamondlil", "DickLocher": "/dicklocher", "DickTracy": "/dicktracy", "Dilbert": "/dilbert", "DilbertClassics": "/dilbert-classics", "DitzAbledPrincess": "/ditzabled-princess", "DixieDrive": "/dixie-drive", "DogEatDoug": "/dogeatdoug", "DogsofCKennel": "/dogsofckennel", "DomesticAbuse": "/domesticabuse", "DontPicktheFlowers": "/dont-pick-the-flowers", "DoodleDaysComics": "/doodle-days", "Doonesbury": "/doonesbury", "DrX": "/dr-x", "Drabble": "/drabble", "Dragin": "/dragin", "DrewLitton": "/drewlitton", "DrewSheneman": "/drewsheneman", "DudeandDude": "/dudedude", "DumbQuestionBadAnswer": "/dumb-question-bad-answer", "DustSpecks": "/dust-specks", "EGGMEN": "/eggmen", "EclecticCartoons": "/eclectic-cartoons", "Eddie": "/eddie", "Eek": "/eek", "Endtown": "/endtown", "EngagAndNevets": "/engag-nevets", "Enlightoons": "/enlightoons", "ErictheCircle": "/eric-the-circle", "EttoreandBaldo": "/ettore-and-baldo", "FMinus": "/fminus", "FamilyTree": "/familytree", "Farcus": "/farcus", "FaronSquare": "/faron-square", "FatCats": "/fat-cats", "Featherweight": "/featherweight", "FloandFriends": "/floandfriends", "FoolishMortals": "/foolish-mortals", "ForBetterorForWorse": "/forbetterorforworse", "ForHeavensSake": "/forheavenssake", "ForMyOwnGood": "/for-my-own-good", "FortKnox": "/fortknox", "FoxTrot": "/foxtrot", "FoxTrotClassics": "/foxtrotclassics", "FrankAndErnest": "/frankandernest", "FrankAndSteinway": "/frank-and-steinway", "FrankBlunt": "/frankblunt", "FrankSonata": "/frank-sonata", "Frazz": "/frazz", "FredBasset": "/fredbasset", "FreeRange": "/freerange", "FreshlySqueezed": "/freshlysqueezed", "FrikkFrakkAndFrank": "/frikk-frakk-frank", "FrizziToons": "/frizzitoons", "FrogApplause": "/frogapplause", "Garfield": "/garfield", "GarfieldMinusGarfield": "/garfieldminusgarfield", "GaryMarkstein": "/garymarkstein", "GaryVarvel": "/garyvarvel", "GasolineAlley": "/gasolinealley", "Geech": "/geech", "Generations": "/generations", "GetAGrip": "/get-a-grip", "GetFuzzy": "/getfuzzy", "GetaLife": "/getalife", "GilThorp": "/gilthorp", "GingerMeggs": "/gingermeggs", "GiveOver": "/give-over", "GlennMcCoy": "/glennmccoy", "GlenviewRevue": "/glenview-revue", "GoodwithCoffee": "/good-with-coffee", "GorDominical": "/espanol/gor-dominical", "Graffiti": "/graffiti", "GrandAvenue": "/grand-avenue", "GrandmaSnoops": "/grandmasnoops", "GrayMatters": "/gray-matters", "GreenPieces": "/green-pieces", "Grizz": "/grizz", "HUBRIS": "/hubris", "HaikuEwe": "/haikuewe", "HamShears": "/ham-shears", "HanginOut": "/hangin-out", "HankandDalesOurWorld": "/hank-and-dales-our-world", "HaphazardHumor": "/haphazard-humor", "HarambeeHills": "/harambeehills", "HartsPass": "/harts-pass", "HealthCapsules": "/healthcapsules", "HeartoftheCity": "/heartofthecity", "Heathcliff": "/heathcliff", "HeavenlyNostrils": "/heavenly-nostrils", "HenryPayne": "/henrypayne", "HerbandJamaal": "/herbandjamaal", "Herman": "/herman", "HistoryBluffs": "/historybluffs", "HogHollow": "/hog-hallow", "HomeandAway": "/homeandaway", "HoodootheUnwiseOwl": "/hoodootheunwiseowl", "HumblebeeandBob": "/humblebee-and-bob", "Humoresque": "/humoresque ", "INCOMPATIBLES": "/incompatibles", "ImaDillo": "/i-m-a-dillo", "ImagineThis": "/imaginethis", "InTheSandbox": "/inthesandbox", "IncidentalComics": "/incidentalcomics", "InfinityBurger": "/infinity-burger", "InkPen": "/inkpen", "InkeeDoodles": "/arctic-blast", "InspectorDangersCrimeQuiz": "/inspector-dangers-crime-quiz", "IntheBleachers": "/inthebleachers", "IntheSticks": "/inthesticks", "ItsAllAboutYou": "/itsallaboutyou", "JackOhman": "/jackohman", "JackRadioComics": "/jack-radio-comics", "JanesWorld": "/janesworld", "JeffDanziger": "/jeffdanziger", "JeffStahler": "/jeffstahler", "JerryHolbert": "/jerryholbert", "JillpokeBohemia": "/jillpoke-bohemia", "JimMorin": "/jimmorin", "JimsJournal": "/jimsjournal", "JoeHeller": "/joe-heller", "JoeVanilla": "/joevanilla", "JoelPett": "/joelpett", "JohnDeering": "/johndeering", "JolleyStuffBrowser": "/jolleystuff-browser", "JumpStart": "/jumpstart", "KALEECHIKORNERS": "/kaleechi-korners", "KSquaredComics": "/k-squared-comics", "KeepingUpWithJones": "/keeping-up-with-jones", "KenCatalino": "/kencatalino", "KevinKallaugher": "/kevinkallaugher", "KidCity": "/kidcity", "KidInc": "/kid-inc", "KidSpot": "/kidspot", "KitNCarlyle": "/kitandcarlyle", "KitchenCapers": "/kitchen-capers", "Kliban": "/kliban", "KlibansCats": "/klibans-cats", "KookieCrumbz": "/kookie-crumbz", "KozmooftheCosmos": "/kozmoofthecosmos", "LaCucaracha": "/lacucaracha", "LaloAlcaraz": "/laloalcaraz", "LarryvilleBlue": "/larryville-blue", "LastKiss": "/lastkiss", "Leadbellies": "/leadbellies", "LegendofBill": "/legendofbill", "LibertyMeadows": "/libertymeadows", "LifeafterDeath": "/life-after-death", "LilAbner": "/lil-abner", "LilEarlLovestoDRAW": "/lil-earl-loves-to-draw", "Lio": "/lio", "LisaBenson": "/lisabenson", "LittleDogLost": "/littledoglost", "Lola": "/lola", "LooseParts": "/looseparts", "LostSideofSuburbia": "/lostsideofsuburbia", "LoveIs": "/loveis", "Luann": "/luann", "Lucan": "/lucan", "LucasLuminous": "/lucas-luminous", "LuckyCow": "/luckycow", "LumandAbner": "/lum-and-abner", "LumpedIn": "/lumped-in", "Mac": "/mac", "MadDogGhettoCop": "/maddogghettocop", "MadMouse": "/mad-mouse", "MaggiesComics": "/maggies-comics", "MagicCoffeeHair": "/magic-coffee-hair", "MagicinaMinute": "/magicinaminute", "Maintaining": "/maintaining", "MariasDay": "/marias-day", "Markonpaper": "/mark-on-paper", "Marmaduke": "/marmaduke", "MarshallRamsey": "/marshallramsey", "MartyandSpud": "/marty-and-spud", "MaryBWary": "/mary-b-wary", "MattBors": "/matt-bors", "MattDavies": "/mattdavies", "MattWuerker": "/mattwuerker", "McArroni": "/mcarroni", "MeandJerseyD": "/meandjerseyd", "MediumLarge": "/medium-large", "MegClassics": "/meg-classics", "MemoirsofaHoofDog": "/hoof-dog", "MichaelRamirez": "/michaelramirez", "MikeLester": "/mike-lester", "MikeLuckovich": "/mikeluckovich", "MikeThompson": "/mikethompson", "MikeduJour": "/mike-du-jour", "Milton50": "/milton-5-0", "Mindframe": "/mindframe", "MinimumSecurity": "/minimumsecurity", "MiscSoup": "/misc-soup", "MixedMedications": "/mixedmedications", "ModeratelyConfused": "/moderately-confused", "MollyandtheBear": "/mollyandthebear", "Momma": "/momma", "Monty": "/monty", "MortMonday": "/mort-monday", "MortsIsland": "/noahs-island", "MotleyClassics": "/motley-classics", "MrGigiandtheSquid": "/mr-gigi-and-the-squid", "MrTodd": "/mr-todd", "MustardandBoloney": "/mustard-and-boloney", "MuttAndJeff": "/muttandjeff", "MyCage": "/mycage", "MyGuardianGrandpa": "/my-guardian-grandpa", "MythTickle": "/mythtickle", "NEUROTICA": "/neurotica", "Nancy": "/nancy", "NavyBean": "/navybean", "NeatStep": "/neatstep", "NedAndLarry": "/ned-and-larry", "NeighborhoodZone": "/neightborhood-zone", "NestHeads": "/nestheads", "NewAdventuresofQueenVictoria": "/thenewadventuresofqueenvictoria", "NickAnderson": "/nickanderson", "NoPlaceLikeHolmes": "/no-place-like-holmes", "NobodysHome": "/nobodys-home", "NonSequitur": "/nonsequitur", "NothingisNotSomething": "/nothing-is-not-something", "OHBABY": "/ohbaby", "ONIONAndPEA": "/onion-and-pea", "OddsandNubs": "/odds-and-nubs", "OfMiceandMud": "/of-mice-and-mud", "OfftheMark": "/offthemark", "OldUncleHoracesbookofGreatWisdom": "/old-uncle-horaces-book-of-great-wisdom", "OllieandQuentin": "/ollie-and-quentin", "OnAClaireDay": "/onaclaireday", "OneBigHappy": "/onebighappy", "OneFellSwoop": "/one-fell-swoop", "OntheGrind": "/on-the-grind", "OrangesareFunny": "/oranges-are-funny", "OrdinaryBill": "/ordinary-bill", "OutoftheGenePoolReRuns": "/outofthegenepool", "Overboard": "/overboard", "OvertheHedge": "/overthehedge", "OysterWar": "/oyster-war", "PCandPixel": "/pcandpixel", "PIGGENS": "/piggens", "PIGTIMES": "/pigtimes", "PS": "/ps", "PatOliphant": "/patoliphant", "PaulSzep": "/paulszep", "Peanizles": "/peanizles", "Peanuts": "/peanuts", "PeanutsHolidayCountdown": "/peanuts-holiday-countdown", "PearlsBeforeSwine": "/pearlsbeforeswine", "Peeples": "/peeples", "PeteyandthePack": "/petey-and-the-pack", "Pibgorn": "/pibgorn", "PibgornSketches": "/pibgornsketches", "Pickles": "/pickles", "Pinkerton": "/pinkerton", "PlanB": "/planb", "Pluggers": "/pluggers", "PoliceLimit": "/policelimit", "PoochCafe": "/poochcafe", "PopDog": "/pop-dog", "PreTeena": "/preteena", "PricklyCity": "/pricklycity", "Primusthebadphilosopher": "/primus-the-bad-philosopher", "PublicEd": "/publiced", "Putz": "/putz", "RANDUMBTHOUGHTS": "/randumb-thoughts", "RabbitsAgainstMagic": "/rabbitsagainstmagic", "Rackafracka": "/rackafracka", "RaisingDuncan": "/raising-duncan", "RalftheDestroyer": "/ralf-the-destroyer", "RealLifeAdventures": "/reallifeadventures", "RealityCheck": "/realitycheck", "Rechid": "/rechid", "RedMeat": "/redmeat", "RedandRover": "/redandrover", "ReplyAll": "/replyall", "RipHaywire": "/riphaywire", "RipleysBelieveItorNot": "/ripleysbelieveitornot", "Risible": "/risible", "RobRogers": "/robrogers", "RobertAriail": "/robert-ariail", "RogersBlues": "/roger-s-blues", "RogueSymmetry": "/rogue_symmetry", "RoseisRose": "/roseisrose", "Rubes": "/rubes", "RudyPark": "/rudypark", "STEPDAD": "/stepdad", "Sabine": "/sabine", "SavageChickens": "/savage-chickens", "ScaryGary": "/scarygary", "ScottStantis": "/scottstantis", "SecondPrize": "/secondprize", "SherlockUnleashed": "/sherlock-unleashed", "SherpaAid": "/sherpaaid", "ShirleyandSonClassics": "/shirley-and-son-classics", "Shoe": "/shoe", "Shoecabbage": "/shoecabbage", "Shortcuts": "/shortcuts", "SickWit": "/sickwit", "SignGarden": "/signgarden", "SigneWilkinson": "/signewilkinson", "SkinHorse": "/skinhorse", "Skippy": "/skippy", "Skylarking": "/skylarking", "Slowpoke": "/slowpoke", "SmallWorld": "/smallworld", "Smith": "/smith", "SnowSez": "/snowsez", "SoccerEarth": "/soccer-earth", "SookyRottweiler": "/sooky-rottweiler", "SouptoNutz": "/soup-to-nutz", "SpaceTimeFunnies": "/spacetimefunnies", "SparComics": "/sparcomics", "Spareroom": "/spareroom", "SpeedBump": "/speedbump", "SportsbyVoort": "/sports-by-voort", "SpottheFrog": "/spot-the-frog", "StankoAndTibor": "/stankotibor", "Starslip": "/starslip", "SteveBenson": "/stevebenson", "SteveBreen": "/stevebreen", "SteveKelley": "/stevekelley", "SteveSack": "/stevesack", "StoneSoup": "/stonesoup", "StrangeBrew": "/strangebrew", "StrangerThings": "/stranger-things", "StuartCarlson": "/stuartcarlson", "SuburbanFairyTales": "/suburbanfairytales", "SueReallyRules": "/sue-really-rules", "SunnyStreet": "/sunny-street", "SuperSiblings": "/super-siblings", "SurvivingSingle": "/surviving-single", "Sylvia": "/sylvia", "TOBY": "/toby", "TalesofTerraTopia": "/terratopia", "TankMcNamara": "/tankmcnamara", "Tarzan": "/tarzan", "TedRall": "/tedrall", "TenCats": "/ten-cats", "Thatababy": "/thatababy", "ThatisPriceless": "/that-is-priceless", "ThatsLife": "/thats-life", "TheAcademiaWaltz": "/academiawaltz", "TheAngryGamer": "/the-angry-gamer", "TheArgyleSweater": "/theargylesweater", "TheBarn": "/thebarn", "TheBellies": "/the-bellies", "TheBigPicture": "/thebigpicture", "TheBoobiehatch": "/the-boobiehatch", "TheBoondocks": "/boondocks", "TheBornLoser": "/the-born-loser", "TheBuckets": "/thebuckets", "TheBureaucrats": "/bureaucrats", "TheCardinal": "/thecardinal", "TheCity": "/thecity", "TheDeadlys": "/the-deadlys", "TheDinetteSet": "/dinetteset", "TheDoozies": "/thedoozies", "TheDuplex": "/duplex", "TheElderberries": "/theelderberries", "TheFastLane": "/fast-lane", "TheFlyingMcCoys": "/theflyingmccoys", "TheFurtherAdventuresofMackieWhite": "/the-further-adventures-of-mackie-white", "TheFuscoBrothers": "/thefuscobrothers", "TheGoldenKid": "/golden-kid", "TheGreatKhan": "/great-khan", "TheGreenMonkeys": "/thegreenmonkeys", "TheGrizzwells": "/thegrizzwells", "TheHouseofUnCommons": "/house-of-uncommons", "TheHumbleStumble": "/humble-stumble", "TheIllConceivedNotionsofJehosophatGrymm": "/the-ill-conceived-notions-of-jehosophat-grymm", "TheKChronicles": "/thekchronicles", "TheKnightLife": "/theknightlife", "TheLeftyBoscoPictureShow": "/leftyboscopictureshow", "TheLightedLab": "/the-lighted-lab", "TheLilMiesters": "/the-lil-miesters", "TheLostBear": "/the-lost-bear", "TheMeaningofLila": "/meaningoflila", "TheMiddletons": "/themiddletons", "TheNormClassics": "/thenorm", "TheOgre": "/the-ogre", "TheOtherCoast": "/theothercoast", "TheSingleDadDiaries": "/single-dad-diaries", "TheSunnySideofKeuka": "/sunny-side-of-keuka", "TheSunshineClub": "/the-sunshine-club", "TheWagesofSin": "/wages-of-sin", "ThereisStrangenessintheUniverse": "/there-is-strangeness-in-the-universe", "ThinLines": "/thinlines", "ThrompTM": "/thromp", "TinySepuku": "/tinysepuku", "TodaysDogg": "/todays-dogg", "TomToles": "/tomtoles", "TomtheDancingBug": "/tomthedancingbug", "Tomversation": "/tomversation", "TonyAuth": "/tonyauth", "TooMuchCoffeeMan": "/toomuchcoffeeman", "Toocrazy": "/too-crazy", "TopicToons": "/topictoons", "Trivquiz": "/trivquiz", "Twaggies": "/twaggies", "TwoBits": "/two-bits", "TyreAndKerb": "/tyre-and-kerb", "USAcres": "/us-acres", "UncleArtsFunland": "/uncleartsfunland", "UnstrangePhenomena": "/unstrange-phenomena", "VanGogh": "/van-gogh", "Vernscartoons": "/vernscartoons", "ViewsAfrica": "/viewsafrica", "ViewsAmerica": "/viewsamerica", "ViewsAsia": "/viewsasia", "ViewsBusiness": "/viewsbusiness", "ViewsEurope": "/viewseurope", "ViewsLatinAmerica": "/viewslatinamerica", "ViewsMidEast": "/viewsmideast", "ViewsoftheWorld": "/viewsoftheworld", "ViiviAndWagner": "/viivi-and-wagner", "WTDuck": "/wtduck", "WaltHandelsman": "/walthandelsman", "WatchYourHead": "/watchyourhead", "WeePals": "/weepals", "WendlesLife": "/wendleslife", "WhiskeyFalls": "/whiskey-falls", "WhosOnDeck": "/whos-on-deck", "Windsock": "/windsock", "WitoftheWorld": "/witoftheworld", "WizardofId": "/wizardofid", "WorkingDaze": "/working-daze", "WorkingItOut": "/workingitout", "ZackHill": "/zackhill", "ZhoodBahzvoi": "/zhood-bahzvoi", "Ziggy": "/ziggy", "ZonnosPeople": "/zonno-s-people", "Zootopia": "/zootopia", "artPOWERS": "/artpowers", "doublenegative": "/double-negative", "gregAbeg": "/gregabeg", "hbenson7": "/hbenson7", "laughwebcom": "/laughweb-com", "monday": "/monday", "nanoworld": "/nano-world", "think": "/think", "wrobbertcartoons": "/wrobbertcartoons"} \ No newline at end of file +{"060": "/0-60", "2CowsandaChicken": "/2cowsandachicken", "4PunkyPuppies": "/four-punky-puppies", "9ChickweedLane": "/9chickweedlane", "9to5": "/9to5", "ABenePlacito": "/a-bene-placito", "ACMEINKD": "/acme-inkd", "ARomanticLife": "/a-romantic-life", "Abaca": "/abaca", "AcadasiaDown": "/acadasia-down", "AdamAtHome": "/adamathome", "AdmiralSquirt": "/admiral-squirt", "AdultChildren": "/adult-children", "AdventuresofMartyandTurkey": "/marty-and-turkey", "AgainstTheGrain": "/against-the-grain", "Agnes": "/agnes", "AlisonWard": "/alison-ward", "AlleyOop": "/alley-oop", "AlmostGrounded": "/almost-grounded", "AmaZnEvents": "/amaznevents", "Andertoons": "/andertoons", "Andnow": "/and-now", "AndyCapp": "/andycapp", "Anecdote": "/anecdote", "AngryLittleGirls": "/angry-little-girls", "AnimalAntics": "/animal-antics", "AnimalCrackers": "/animalcrackers", "Annie": "/annie", "AppleCreekComics": "/apple-creek", "ArDuffle": "/arduffle", "ArloandJanis": "/arloandjanis", "AskShagg": "/askshagg", "Asymptote": "/asymptote", "BC": "/bc", "BERSERKALERT": "/berserk-alert", "BUNS": "/buns", "BUSHYTALES": "/bushy-tales", "BackintheDay": "/backintheday", "BadReporter": "/badreporter", "Badlands": "/badlands", "Baldo": "/baldo", "BallardStreet": "/ballardstreet", "BananaTriangle": "/banana-triangle", "Barefoot": "/barefoot", "BarkeaterLake": "/barkeaterlake", "BarkingCrayon": "/barking-crayon", "BarneyAndClyde": "/barneyandclyde", "BasicInstructions": "/basicinstructions", "BeMisery": "/bemisery", "Beanie": "/beanie", "Beardo": "/beardo", "Beebleville": "/beebleville", "Ben": "/ben", "BenSargent": "/bensargent", "BenjaminBreadman": "/benjamin-breadman", "BergerAndWyse": "/berger-and-wyse", "BestInShow": "/best-in-show", "Betty": "/betty", "Bewley": "/bewley", "BiffAndRiley": "/biff-and-riley", "BigMonkeyComic": "/big-monkey-comic", "BigNate": "/bignate", "BigTop": "/bigtop", "Biographic": "/biographic", "Birdbrains": "/birdbrains", "Bliss": "/bliss", "BloomCounty": "/bloomcounty", "BlueSkiestoons": "/blue-skies-toons", "Bluebonnets": "/cowsandstuff", "BoNanas": "/bonanas", "BobGorrell": "/bobgorrell", "BobtheSquirrel": "/bobthesquirrel", "Boomerangs": "/boomerangs", "Bottomliners": "/bottomliners", "BoundandGagged": "/boundandgagged", "BreakofDay": "/break-of-day", "Brevity": "/brevity", "BrewsterRockit": "/brewsterrockit", "BrilliantMines": "/brilliant-mines", "Broham": "/broham", "BroomHilda": "/broomhilda", "BubblesandSnail": "/bubbles-and-snail", "Buni": "/buni", "BuzzaWuzza": "/buzza-wuzza", "CAFFEINATED": "/CAFFEINATED", "CANDYBLONDELL": "/candyblondell", "CafconLeche": "/cafeconleche", "CalvinandHobbes": "/calvinandhobbes", "Candorville": "/candorville", "CaricaturesbyKerryWaghorn": "/facesinthenews", "CarlsLife": "/carlslife", "Cartertoons": "/cartertoons", "CaseyandKyle": "/casey-and-kyle", "Cathy": "/cathy", "CestlaVie": "/cestlavie", "ChanLowe": "/chanlowe", "CharmysArmy": "/charmy-s-army", "CheapThrillsCuisine": "/cheap-thrills-cuisine", "ChipBok": "/chipbok", "ChrisBritt": "/chrisbritt", "ChubbyGirlComics": "/chubbygirlcomics", "ChuckAsay": "/chuckasay", "ChuckleBros": "/chucklebros", "CircusPeople": "/circus-people", "CitizenDog": "/citizendog", "ClayBennett": "/claybennett", "ClayJones": "/clayjones", "Cleats": "/cleats", "ClosetoHome": "/closetohome", "CockroachComix": "/cockroachcomix", "CoffeeShopTidbits": "/coffee-shop-tidbits", "Committed": "/committed", "Computoon": "/compu-toon", "Confabulation": "/confabulation", "Cornered": "/cornered", "CowSheepandaGnomeNamedHelga": "/cow-sheep-and-a-gnome-named-helga", "CowTown": "/cowtown", "CowandBoy": "/cowandboy", "Crabbels": "/crabbels", "Creek": "/creek", "Critterdoodles": "/critterdoodles", "CrocAndGator": "/croc-and-gator", "Crumb": "/crumb", "CubienBouncy": "/cubie-n-bouncy", "CuldeSac": "/culdesac", "DaddysHome": "/daddyshome", "DailyPinky": "/daily-pinky", "DanWasserman": "/danwasserman", "DanaSummers": "/danasummers", "DarkSideoftheHorse": "/darksideofthehorse", "DarkWIndow": "/dark-window", "DeepCover": "/deepcover", "DevinCraneComicStripGhostwriter": "/devincranecomicstripghostwriter", "DiamondLil": "/diamondlil", "DickLocher": "/dicklocher", "DickTracy": "/dicktracy", "DilbertClassics": "/dilbert-classics", "DitzAbledPrincess": "/ditzabled-princess", "DixieDrive": "/dixie-drive", "DogEatDoug": "/dogeatdoug", "DogsofCKennel": "/dogsofckennel", "DomesticAbuse": "/domesticabuse", "DontPicktheFlowers": "/dont-pick-the-flowers", "DoodleDaysComics": "/doodle-days", "Doonesbury": "/doonesbury", "DrX": "/dr-x", "Drabble": "/drabble", "Dragin": "/dragin", "DrewLitton": "/drewlitton", "DrewSheneman": "/drewsheneman", "DudeandDude": "/dudedude", "DumbQuestionBadAnswer": "/dumb-question-bad-answer", "DustSpecks": "/dust-specks", "EGGMEN": "/eggmen", "EclecticCartoons": "/eclectic-cartoons", "Eddie": "/eddie", "Eek": "/eek", "Endtown": "/endtown", "EngagAndNevets": "/engag-nevets", "Enlightoons": "/enlightoons", "ErictheCircle": "/eric-the-circle", "EttoreandBaldo": "/ettore-and-baldo", "FMinus": "/fminus", "FamilyTree": "/familytree", "Farcus": "/farcus", "FaronSquare": "/faron-square", "FatCats": "/fat-cats", "Featherweight": "/featherweight", "FloandFriends": "/floandfriends", "FoolishMortals": "/foolish-mortals", "ForBetterorForWorse": "/forbetterorforworse", "ForHeavensSake": "/forheavenssake", "ForMyOwnGood": "/for-my-own-good", "FortKnox": "/fortknox", "FoxTrot": "/foxtrot", "FoxTrotClassics": "/foxtrotclassics", "FrankAndErnest": "/frankandernest", "FrankAndSteinway": "/frank-and-steinway", "FrankBlunt": "/frankblunt", "FrankSonata": "/frank-sonata", "Frazz": "/frazz", "FredBasset": "/fredbasset", "FreeRange": "/freerange", "FreshlySqueezed": "/freshlysqueezed", "FrizziToons": "/frizzitoons", "FrogApplause": "/frogapplause", "Garfield": "/garfield", "GarfieldMinusGarfield": "/garfieldminusgarfield", "GaryMarkstein": "/garymarkstein", "GaryVarvel": "/garyvarvel", "GasolineAlley": "/gasolinealley", "Geech": "/geech", "Generations": "/generations", "GetAGrip": "/get-a-grip", "GetFuzzy": "/getfuzzy", "GetaLife": "/getalife", "GilThorp": "/gilthorp", "GingerMeggs": "/gingermeggs", "GiveOver": "/give-over", "GlennMcCoy": "/glennmccoy", "GlenviewRevue": "/glenview-revue", "GoodwithCoffee": "/good-with-coffee", "GorDominical": "/espanol/gor-dominical", "Graffiti": "/graffiti", "GrandAvenue": "/grand-avenue", "GrandmaSnoops": "/grandmasnoops", "GrayMatters": "/gray-matters", "GreenPieces": "/green-pieces", "Grizz": "/grizz", "HUBRIS": "/hubris", "HaikuEwe": "/haikuewe", "HamShears": "/ham-shears", "HanginOut": "/hangin-out", "HankandDalesOurWorld": "/hank-and-dales-our-world", "HaphazardHumor": "/haphazard-humor", "HarambeeHills": "/harambeehills", "HartsPass": "/harts-pass", "HealthCapsules": "/healthcapsules", "HeartoftheCity": "/heartofthecity", "Heathcliff": "/heathcliff", "HeavenlyNostrils": "/heavenly-nostrils", "HenryPayne": "/henrypayne", "HerbandJamaal": "/herbandjamaal", "Herman": "/herman", "HistoryBluffs": "/historybluffs", "HogHollow": "/hog-hallow", "HomeandAway": "/homeandaway", "HoodootheUnwiseOwl": "/hoodootheunwiseowl", "HumblebeeandBob": "/humblebee-and-bob", "Humoresque": "/humoresque ", "INCOMPATIBLES": "/incompatibles", "ImaDillo": "/i-m-a-dillo", "ImagineThis": "/imaginethis", "InTheSandbox": "/inthesandbox", "IncidentalComics": "/incidentalcomics", "InfinityBurger": "/infinity-burger", "InkPen": "/inkpen", "InspectorDangersCrimeQuiz": "/inspector-dangers-crime-quiz", "IntheBleachers": "/inthebleachers", "IntheSticks": "/inthesticks", "ItsAllAboutYou": "/itsallaboutyou", "JackOhman": "/jackohman", "JackRadioComics": "/jack-radio-comics", "JanesWorld": "/janesworld", "JeffDanziger": "/jeffdanziger", "JeffStahler": "/jeffstahler", "JerryHolbert": "/jerryholbert", "JillpokeBohemia": "/jillpoke-bohemia", "JimMorin": "/jimmorin", "JimsJournal": "/jimsjournal", "JoeHeller": "/joe-heller", "JoeVanilla": "/joevanilla", "JoelPett": "/joelpett", "JohnDeering": "/johndeering", "JolleyStuffBrowser": "/jolleystuff-browser", "JumpStart": "/jumpstart", "KALEECHIKORNERS": "/kaleechi-korners", "KSquaredComics": "/k-squared-comics", "KeepingUpWithJones": "/keeping-up-with-jones", "KenCatalino": "/kencatalino", "KevinKallaugher": "/kevinkallaugher", "KidCity": "/kidcity", "KidInc": "/kid-inc", "KidSpot": "/kidspot", "KitNCarlyle": "/kitandcarlyle", "KitchenCapers": "/kitchen-capers", "Kliban": "/kliban", "KlibansCats": "/klibans-cats", "KookieCrumbz": "/kookie-crumbz", "KozmooftheCosmos": "/kozmoofthecosmos", "LaCucaracha": "/lacucaracha", "LaloAlcaraz": "/laloalcaraz", "LarryvilleBlue": "/larryville-blue", "LastKiss": "/lastkiss", "Leadbellies": "/leadbellies", "LegendofBill": "/legendofbill", "LibertyMeadows": "/libertymeadows", "LifeafterDeath": "/life-after-death", "LilAbner": "/lil-abner", "LilEarlLovestoDRAW": "/lil-earl-loves-to-draw", "Lio": "/lio", "LisaBenson": "/lisabenson", "LittleDogLost": "/littledoglost", "Lola": "/lola", "LooseParts": "/looseparts", "LostSideofSuburbia": "/lostsideofsuburbia", "LoveIs": "/loveis", "Luann": "/luann", "Lucan": "/lucan", "LucasLuminous": "/lucas-luminous", "LuckyCow": "/luckycow", "LumandAbner": "/lum-and-abner", "LumpedIn": "/lumped-in", "Mac": "/mac", "MadDogGhettoCop": "/maddogghettocop", "MadMouse": "/mad-mouse", "MagicCoffeeHair": "/magic-coffee-hair", "MagicinaMinute": "/magicinaminute", "Maintaining": "/maintaining", "MariasDay": "/marias-day", "Markonpaper": "/mark-on-paper", "Marmaduke": "/marmaduke", "MarshallRamsey": "/marshallramsey", "MartyandSpud": "/marty-and-spud", "MaryBWary": "/mary-b-wary", "MattBors": "/matt-bors", "MattDavies": "/mattdavies", "MattWuerker": "/mattwuerker", "McArroni": "/mcarroni", "MeandJerseyD": "/meandjerseyd", "MediumLarge": "/medium-large", "MegClassics": "/meg-classics", "MemoirsofaHoofDog": "/hoof-dog", "MichaelRamirez": "/michaelramirez", "MikeLester": "/mike-lester", "MikeLuckovich": "/mikeluckovich", "MikeThompson": "/mikethompson", "MikeduJour": "/mike-du-jour", "Milton50": "/milton-5-0", "Mindframe": "/mindframe", "MinimumSecurity": "/minimumsecurity", "MiscSoup": "/misc-soup", "MixedMedications": "/mixedmedications", "ModeratelyConfused": "/moderately-confused", "MollyandtheBear": "/mollyandthebear", "Momma": "/momma", "Monty": "/monty", "MortMonday": "/mort-monday", "MortsIsland": "/noahs-island", "MotleyClassics": "/motley-classics", "MrGigiandtheSquid": "/mr-gigi-and-the-squid", "MrTodd": "/mr-todd", "MustardandBoloney": "/mustard-and-boloney", "MuttAndJeff": "/muttandjeff", "MyCage": "/mycage", "MyGuardianGrandpa": "/my-guardian-grandpa", "MythTickle": "/mythtickle", "NEUROTICA": "/neurotica", "Nancy": "/nancy", "NavyBean": "/navybean", "NeatStep": "/neatstep", "NedAndLarry": "/ned-and-larry", "NeighborhoodZone": "/neightborhood-zone", "NestHeads": "/nestheads", "NewAdventuresofQueenVictoria": "/thenewadventuresofqueenvictoria", "NickAnderson": "/nickanderson", "NoPlaceLikeHolmes": "/no-place-like-holmes", "NobodysHome": "/nobodys-home", "NonSequitur": "/nonsequitur", "NothingisNotSomething": "/nothing-is-not-something", "OHBABY": "/ohbaby", "ONIONAndPEA": "/onion-and-pea", "OddsandNubs": "/odds-and-nubs", "OfftheMark": "/offthemark", "OldUncleHoracesbookofGreatWisdom": "/old-uncle-horaces-book-of-great-wisdom", "OllieandQuentin": "/ollie-and-quentin", "OnAClaireDay": "/onaclaireday", "OneBigHappy": "/onebighappy", "OneFellSwoop": "/one-fell-swoop", "OntheGrind": "/on-the-grind", "OrangesareFunny": "/oranges-are-funny", "OrdinaryBill": "/ordinary-bill", "OutoftheGenePoolReRuns": "/outofthegenepool", "Overboard": "/overboard", "OvertheHedge": "/overthehedge", "PCandPixel": "/pcandpixel", "PIGGENS": "/piggens", "PatOliphant": "/patoliphant", "PaulSzep": "/paulszep", "Peanizles": "/peanizles", "Peanuts": "/peanuts", "PeanutsHolidayCountdown": "/peanuts-holiday-countdown", "PearlsBeforeSwine": "/pearlsbeforeswine", "Peeples": "/peeples", "PeteyandthePack": "/petey-and-the-pack", "Pibgorn": "/pibgorn", "PibgornSketches": "/pibgornsketches", "Pickles": "/pickles", "Pinkerton": "/pinkerton", "PlanB": "/planb", "Pluggers": "/pluggers", "PoliceLimit": "/policelimit", "PoochCafe": "/poochcafe", "PopDog": "/pop-dog", "PreTeena": "/preteena", "PricklyCity": "/pricklycity", "Primusthebadphilosopher": "/primus-the-bad-philosopher", "PublicEd": "/publiced", "Putz": "/putz", "RANDUMBTHOUGHTS": "/randumb-thoughts", "RabbitsAgainstMagic": "/rabbitsagainstmagic", "Rackafracka": "/rackafracka", "RaisingDuncan": "/raising-duncan", "RalftheDestroyer": "/ralf-the-destroyer", "RealLifeAdventures": "/reallifeadventures", "RealityCheck": "/realitycheck", "Rechid": "/rechid", "RedMeat": "/redmeat", "RedandRover": "/redandrover", "ReplyAll": "/replyall", "RichardsPoorAlmanac": "/richards-poor-almanac", "RipHaywire": "/riphaywire", "RipleysBelieveItorNot": "/ripleysbelieveitornot", "Risible": "/risible", "RobRogers": "/robrogers", "RobertAriail": "/robert-ariail", "RogersBlues": "/roger-s-blues", "RogueSymmetry": "/rogue_symmetry", "RoseisRose": "/roseisrose", "Rubes": "/rubes", "RudyPark": "/rudypark", "STEPDAD": "/stepdad", "Sabine": "/sabine", "SavageChickens": "/savage-chickens", "ScaryGary": "/scarygary", "ScottStantis": "/scottstantis", "SecondPrize": "/secondprize", "SherlockUnleashed": "/sherlock-unleashed", "ShirleyandSonClassics": "/shirley-and-son-classics", "Shoe": "/shoe", "Shoecabbage": "/shoecabbage", "Shortcuts": "/shortcuts", "SickWit": "/sickwit", "SignGarden": "/signgarden", "SigneWilkinson": "/signewilkinson", "SkinHorse": "/skinhorse", "Skippy": "/skippy", "Skylarking": "/skylarking", "Slowpoke": "/slowpoke", "SmallWorld": "/smallworld", "Smith": "/smith", "SnowSez": "/snowsez", "SoccerEarth": "/soccer-earth", "SookyRottweiler": "/sooky-rottweiler", "SouptoNutz": "/soup-to-nutz", "SpaceTimeFunnies": "/spacetimefunnies", "Spareroom": "/spareroom", "SpeedBump": "/speedbump", "SportsbyVoort": "/sports-by-voort", "SpottheFrog": "/spot-the-frog", "StankoAndTibor": "/stankotibor", "Starslip": "/starslip", "SteveBenson": "/stevebenson", "SteveBreen": "/stevebreen", "SteveKelley": "/stevekelley", "SteveSack": "/stevesack", "StoneSoup": "/stonesoup", "StrangeBrew": "/strangebrew", "StrangerThings": "/stranger-things", "StuartCarlson": "/stuartcarlson", "SuburbanFairyTales": "/suburbanfairytales", "SueReallyRules": "/sue-really-rules", "SunnyStreet": "/sunny-street", "SuperSiblings": "/super-siblings", "SurvivingSingle": "/surviving-single", "Sylvia": "/sylvia", "TOBY": "/toby", "TalesofTerraTopia": "/terratopia", "TankMcNamara": "/tankmcnamara", "Tarzan": "/tarzan", "TedRall": "/tedrall", "TenCats": "/ten-cats", "Thatababy": "/thatababy", "ThatisPriceless": "/that-is-priceless", "ThatsLife": "/thats-life", "TheAcademiaWaltz": "/academiawaltz", "TheAngryGamer": "/the-angry-gamer", "TheArgyleSweater": "/theargylesweater", "TheBarn": "/thebarn", "TheBellies": "/the-bellies", "TheBigPicture": "/thebigpicture", "TheBoobiehatch": "/the-boobiehatch", "TheBoondocks": "/boondocks", "TheBornLoser": "/the-born-loser", "TheBuckets": "/thebuckets", "TheBureaucrats": "/bureaucrats", "TheCardinal": "/thecardinal", "TheCity": "/thecity", "TheDeadlys": "/the-deadlys", "TheDinetteSet": "/dinetteset", "TheDoozies": "/thedoozies", "TheDuplex": "/duplex", "TheElderberries": "/theelderberries", "TheFastLane": "/fast-lane", "TheFlyingMcCoys": "/theflyingmccoys", "TheFurtherAdventuresofMackieWhite": "/the-further-adventures-of-mackie-white", "TheFuscoBrothers": "/thefuscobrothers", "TheGoldenKid": "/golden-kid", "TheGreatKhan": "/great-khan", "TheGreenMonkeys": "/thegreenmonkeys", "TheGrizzwells": "/thegrizzwells", "TheHouseofUnCommons": "/house-of-uncommons", "TheHumbleStumble": "/humble-stumble", "TheIllConceivedNotionsofJehosophatGrymm": "/the-ill-conceived-notions-of-jehosophat-grymm", "TheKChronicles": "/thekchronicles", "TheKnightLife": "/theknightlife", "TheLeftyBoscoPictureShow": "/leftyboscopictureshow", "TheLightedLab": "/the-lighted-lab", "TheLilMiesters": "/the-lil-miesters", "TheLostBear": "/the-lost-bear", "TheMeaningofLila": "/meaningoflila", "TheMiddletons": "/themiddletons", "TheNormClassics": "/thenorm", "TheOgre": "/the-ogre", "TheOtherCoast": "/theothercoast", "TheSingleDadDiaries": "/single-dad-diaries", "TheSunnySideofKeuka": "/sunny-side-of-keuka", "TheSunshineClub": "/the-sunshine-club", "TheWagesofSin": "/wages-of-sin", "ThereisStrangenessintheUniverse": "/there-is-strangeness-in-the-universe", "ThinLines": "/thinlines", "ThrompTM": "/thromp", "TinySepuku": "/tinysepuku", "TodaysDogg": "/todays-dogg", "TomToles": "/tomtoles", "TomtheDancingBug": "/tomthedancingbug", "Tomversation": "/tomversation", "TonyAuth": "/tonyauth", "TooMuchCoffeeMan": "/toomuchcoffeeman", "Toocrazy": "/too-crazy", "TopicToons": "/topictoons", "Trivquiz": "/trivquiz", "Twaggies": "/twaggies", "TwoBits": "/two-bits", "TyreAndKerb": "/tyre-and-kerb", "USAcres": "/us-acres", "UncleArtsFunland": "/uncleartsfunland", "UnstrangePhenomena": "/unstrange-phenomena", "VanGogh": "/van-gogh", "Vernscartoons": "/vernscartoons", "ViewsAfrica": "/viewsafrica", "ViewsAmerica": "/viewsamerica", "ViewsAsia": "/viewsasia", "ViewsBusiness": "/viewsbusiness", "ViewsEurope": "/viewseurope", "ViewsLatinAmerica": "/viewslatinamerica", "ViewsMidEast": "/viewsmideast", "ViewsoftheWorld": "/viewsoftheworld", "ViiviAndWagner": "/viivi-and-wagner", "WTDuck": "/wtduck", "WaltHandelsman": "/walthandelsman", "WatchYourHead": "/watchyourhead", "WeePals": "/weepals", "WendlesLife": "/wendleslife", "WhiskeyFalls": "/whiskey-falls", "WhosOnDeck": "/whos-on-deck", "Windsock": "/windsock", "WitoftheWorld": "/witoftheworld", "WizardofId": "/wizardofid", "WorkingDaze": "/working-daze", "WorkingItOut": "/workingitout", "ZackHill": "/zackhill", "ZhoodBahzvoi": "/zhood-bahzvoi", "Ziggy": "/ziggy", "ZonnosPeople": "/zonno-s-people", "Zootopia": "/zootopia", "artPOWERS": "/artpowers", "doublenegative": "/double-negative", "gregAbeg": "/gregabeg", "hbenson7": "/hbenson7", "laughwebcom": "/laughweb-com", "monday": "/monday", "nanoworld": "/nano-world", "think": "/think", "wrobbertcartoons": "/wrobbertcartoons"} \ No newline at end of file diff --git a/scripts/keenspot.py b/scripts/keenspot.py index b10022457..e2465859d 100755 --- a/scripts/keenspot.py +++ b/scripts/keenspot.py @@ -47,23 +47,269 @@ exclude_comics = [ "beerkada", # no images "BelovedLeader", # broken images "BigMouthComics", # page does not follow standard layout - "", # page is gone - "", # page is gone - "", # page is gone + "BilltheMagician", # page does not follow standard layout + "BlackBlue", # page moved + "BlackMagic", # page does not follow standard layout + "BloodBound", # page moved + "bloodofthedragon", # page does not follow standard layout + "BloodWing", # broken images "BlueZombie", # broken page "BoomerExpress", # redirection to another page + "BobOnline", # missing images + "BottomFlavor", # page does not follow standard layout + "BradTheVampire", # page does not follow standard layout + "BreakpointCity", # page moved + "Brinkerhoff", # page redirected + "CampusSafari", # page moved + "CapturetheMoment", # page moved + "CaseyandAndy", # page moved + "Catalyst", # page moved + "Cats", # broken images + "Chair", # page moved + "ChildrenAtPlay", # page does not follow standard layout + "chu", # broken images + "CoACityofAscii", # only ascii images + "ComicMischief", # page moved + "ComputerGameAddicts", # page moved + "Concession", # page moved + "CorridorZ", # page does not follow standard layout + "CrashBoomMagic", # page moved + "CrazySlowlyGoing", # page has 403 forbidden + "CrimsonWings", # page moved + "DakotasRidge", # page moved + "DATAROM", # broken images + "DazeinaHaze", # page moved + "DIABOLICA", # broken images + "DIfIK", # page does not follow standard layout + "DigitalWar", # page is gone + "DimBulbComics", # page is gone + "DIVE", # page is gone + "DominicDeegan", # page moved "DungeonDamage", # page does not follow standard layout + "Dylan", # page has 403 forbidden "EarthRiser", # redirects to a new page + "EdgetheDevilhunter", # page is gone + "EdibleDirt", # page moved + "Einstien27sDesk", # page is gone + "ElfOnlyInn", # page moved + "Ensuing", # broken links + "etch", # broken images + "EternalCaffeineJunkie", # page does not follow standard layout + "EternityComplex", # page does not follow standard layout + "Evilish", # page moved + "EvolBara", # page is gone + "FaerieTales", # page does not follow standard layout + "FairyTaleNewVillage", # missing images + "Fate27sTear", # page moved "FaultyLogic", # page does not follow standard layout + "FireontheMountain", # page does not follow standard layout + "FiveBucksanHour", # page is gone + "Flatwood", # page moved + "FLEMComics", # page moved + "FletchersCave", # page is broken + "ForcesofGoodandEvil", # page does not follow standard layout + "FurryBlackDevil", # page moved + "Galacticus", # page has 403 forbidden + "GeebasonParade", # page does not follow standard layout + "geeks", # page moved + "GeminiBright", # page does not follow standard layout + "GemutationsPlague", # page does not follow standard layout + "GeorgetheSecond", # page does not follow standard layout + "Ghostz", # page does not follow standard layout + "GODLIKE", # page has 403 forbidden "GoForIt", # page is gone - "JuvenileDiversion", # page moved + "GothBoy", # page moved + "Grimage", # page moved + "GrossePointeDogs", # page is broken + "GUComics", # page moved + "HardUnderbelly", # page does not follow standard layout + "HazardousScience", # page is gone + "HereThereBeDragons", # page moved + "HighMaintenance", # missing images + "HighSchoolRPG", # page does not follow standard layout + "Horndog", # page moved + "HorseshoesandHandgrenades", # missing images + "HotelGrim", # missing images + "IAlwaysWakeUpLazy", # page moved + "ihatesteve", # page is gone + "IllicitMiracles", # page does not follow standard layout + "IndefensiblePositions", # page does not follow standard layout + "InsanityFair", # page does not follow standard layout + "InsideJoke", # page is gone + "InsidetheBox", # page has 403 forbidden + "InternationalHopeFoundation", # page does not follow standard layout + "JamieandNick", # page moved + "JasonLovesHisGrandpa", # page is gone + "JavanteasFate", # page is gone + "JBBcomics", # page is gone + "JedandDark", # page does not follow standard layout + "JoBeth", # page moved + "Joyride", # page moved + "JustAnotherEscape", # page moved "JustWeird", # page has 403 forbidden - "Michikomonogatari", # page does not follow standard layout - "MobileMadness", # page does not follow standard layout + "JuvenileDiversion", # page moved + "JWalkinAndapos", # missing images + "KarmaSlave", # page moved + "KeenLace", # page is gone + "khaoskomic", # page moved + "KillingTime", # page is gone "KnightsOfTheNexus", # page does not follow standard layout + "KoFightClub", # page moved + "LabGoatsInc", # page moved + "LandofGreed", # page is gone + "LeanOnMe", # page has 403 forbidden + "LegendsofRovana", # page has 403 forbidden + "LifeatBayside", # page does not follow standard layout + "LifeinaNutshell", # page does not follow standard layout + "Lifesuchasitis", # page has 403 forbidden + "LinktotheBoards", # page does not follow standard layout + "LinT", # page moved + "LiterallySpeaking", # page does not follow standard layout + "LoxieAndZoot", # page does not follow standard layout + "Lunchtable", # missing images + "MadWorld", # page has 403 forbidden + "Magellan", # page does not follow standard layout + "Marachan", # missing images + "MassProduction", # page does tno follow standard layout + "MayIHelpYou", # page has 403 forbidden + "Meiosis", # page moved + "Michikomonogatari", # page does not follow standard layout + "MidnorthFlourCo", # page has 403 forbidden + "MintCondition", # page moved + "MisadventuresinPhysics", # page has 403 forbidden + "MobileMadness", # page does not follow standard layout + "MyAngelYouAreAngel", # page is gone + "MyBrainHurts", # page does not follow standard layout + "NAFTANorthAmericanFreeToonAgreementalsoYankuckcanee", # page does not follow standard layout + "NeglectedMarioCharacterComix", # page does not follow standard layout + "Nemutionjewel", # page does not follow standard layout + "Nerdgasm", # missing images + "Nerdz", # page is gone + "Nervillsaga", # page does not follow standard layout + "NetherOakasuburbanadventure", # page does not follow standard layout + "NoNeedForBushido", # page moved + "nothingcomesnaturally", # page does not follow standard layout + "NymphsoftheWest", # too few images + "OffTheWall", # page does not follow standard layout + "OneHourAxis", # page is gone + "OnlyOne", # page is gone + "OopsNevermind", # page is gone + "PacoStand", # page has 403 forbidden + "Pander", # page is gone + "PANDORA", # page is missing pages + "PhilosophyBites", # missing images + "PhilosophyMonkey", # page is gone + "PicpakDog", # page moved + "PictureDiary", # page is gone + "PillarsofFaith", # page does not follow standard layout + "Pimpette", # page moved + "PokC3A9Chow", # page has 403 forbidden + "PolleninArabia", # page does not follow standard layout + "PranMan", # page moved + "QueensOfRandomness", # broken images + "QuestionableTales", # page does not follow standard layout + "RadioactiveFanboys", # page does not follow standard layout + "RandomAssembly", # page is gone + "RandomInk", # page is gone + "ReceptorFatigue", # page does not follow standard layout + "Remsi", # page does not follow standard layout + "Reset", # page does not follow standard layout + "ResistanceLine", # page does not follow standard layout + "ReturntoDonnelly", # page is gone + "Riboflavin", # page does not follow standard layout + "RitualsandOfferings", # page is gone + "RiverCityHigh", # page is gone + "RM27sothercomics", # page does not follow standard layout "RogerAndDominic", # page does not follow standard layout + "RoleoftheDie", # page is gone + "RonnieRaccoon", # page moved + "RosalarianAndapossRandomCreepyTales", # page is gone + "RulesofMakeBelieve", # page is gone + "Rveillerie", # page has 403 forbidden + "SaintPeter27sCross", # page does not follow standard layout + "Saturnalia", # page moved + "SavageIslands", # page has 403 forbidden "SaveMeGebus", # page does not follow standard layout + "Sawdust", # page has 403 forbidden + "Scooterboy1234", # page has 403 forbidden + "SecondNight", # page moved + "Sempiternal", # page moved + "Senioritis", # page has 403 forbidden + "ShivaeStudios", # page moved + "ShonenAiKudasai", # page is gone + "ShootMeNow", # page does not follow standard layout + "SidandLasker", # page moved + "SillyConeV", # page is gone + "Skunk", # page moved + "SLAGIT", # missing images + "SmithStone", # page has 403 forbidden + "SnowflakeStudios", # page is gone + "Sock27d", # page is gone + "Soks", # page is gone + "SoManyLevels", # page moved + "SomethingSoft", # page is gone + "Sorcery101", # page moved + "SpellBinder", # page is gone + "SPQRBlues", # page moved + "StationV3", # page moved + "SticksandStuff", # page does not follow standard layout + "StickyFingers", # page does not follow standard layout + "Stubble", # page moved + "SurrealKins", # page is gone + "SwirlyMarkYume", # page does not follow standard layout + "SynapticMisfiring", # page is gone + "TalesoftheQuestor", # page moved + "TAVISION", # page moved + "ThatWasMcPherson", # page moved + "The6GUYSInMyHead", # page has 403 forbidden + "TheAdventuresofCaptainMooki", # page moved + "TheAdventuresofLi27lDenverPastrami", # page is gone + "TheAdventuresofPeppyThePipingPirate", # page is gone + "TheAmoeba", # page is gone "TheAvatar", # page does not follow standard layout + "TheBessEffectGerman", # page moved + "TheBestandtheBrightest", # page moved + "TheDevilsPanties", # page moved + "TheDoctorPepperShow", # page has 403 forbidden + "TheGods27Pack", # page has 403 forbidden + "TheMadBrothers", # page does not follow standard layout + "TheMediocres", # missing images + "TheNamelessStory", # page has 403 forbidden + "Thenoob", # page moved + "TheOrangeArrow", # page is gone + "TheSailorNeopetsRPG", # page does not follow standard layout + "TheWayoftheWorld", # page moved + "TheWorldofUh", # broken images + "TheWotch", # page does not follow standard layout + "ThunderandLightning", # page moved + "TinysWorld", # page does not follow standard layout + "ToonPimp27sPalace", # page moved + "Tossers", # page moved + "Towner", # page does not follow standard layout + "Townies", # page is gone + "TracyandTristan", # page moved + "TrialsintheLight", # page does not follow standard layout + "ttskr", # page does not follow standard layout + "twelvedragons", # page does not follow standard layout + "TwoEvilScientists", # page moved + "TwoLumps", # page moved + "TwoSidesWide", # page moved + "Vendetta", # page moved + "VictimsoftheSystem", # page moved + "Victor", # page moved + "WARPZONEthinkwithinthecube", # page does not follow standard layout + "WayoftheDodo", # page does not follow standard layout + "Wedontgetiteither", # page moved + "WeishauptScholars", # page does not follow standard layout + "Werechild", # page has 403 forbidden + "WhiskeyAndMelancholy", # missing pages + "YellowMoon", # page has 403 forbidden + "YouScrewedUp", # missing images + "YUMEdream", # page moved + "Zap", # page moved + "ZebraGirl", # page moved + "Zeek", # page moved + "Zootz", # page is gone ] # links to last valid strips @@ -72,8 +318,37 @@ url_overrides = { "AmazonSpaceRangers": "http://amazons.comicgenesis.com/d/20051015.html", "ArroganceinSimplicity": "http://arrogance.comicgenesis.com/d/20030217.html", "ATasteofEvil": "http://atasteofevil.comicgenesis.com/d/20050314.html", - "": "", - "": "", + "CanYouKeepaSecret": "http://cykas.comicgenesis.com/d/20041035.html", + "CapturetheMoment": "http://capturethemoment.comicgenesis.com/d/20100927.html", + "CornerAlley13": "http://corneralley.comicgenesis.com/d/20101010.html", + "Countyoursheep": "http://countyoursheep.keenspot.com/", + "FreakU": "http://freaku.comicgenesis.com//d/20080827.html", + "FreeParking": "http://freeparking.comicgenesis.com//d/20051029.html", + "GamerPsychotica": "http://gp.comicgenesis.com/d/20060113.html", + "GoneAstray": "http://goneastray.comicgenesis.com/d/20100305.html", + "GoodnEvil": "http://gne.comicgenesis.com/d/20040814.html", + "HalflightBreaking": "http://halflight.comicgenesis.com/d/20021031.html", + "HealerOnFeatheredWings": "http://selsachronicles.comicgenesis.com/", + "HowNottoRunAComic": "http://hownottorunacomic.comicgenesis.com/d/19950719.html", + "HurricaneParty": "http://hurricaneparty.comicgenesis.com/d/20040123.html", + "MacHall": "http://machall.comicgenesis.com/d/20020125.html", + "MaryQuiteContrary": "http://marycontrary.comicgenesis.com/d/20070824.html", + "MoonCrest24": "http://mooncrest.comicgenesis.com/d/20121117.html", + "MrPinkBlob": "http://mrpinkblob.comicgenesis.com/d/100.html", + "NekkoandJoruba": "http://nekkoandjoruba.comicgenesis.com/d/20050816.html", + "No4thWalltoBreak": "http://no4thwalltobreak.comicgenesis.com/d/20041025.html", + "OtakuKyokai": "http://otakukyokai.comicgenesis.com/d/20060818.html", + "PandP": "http://pandpcomic.comicgenesis.com/d/20021002.html", + "Paradigm": "http://paradigm.comicgenesis.com/d/20020716.html", + "ParallelDementia": "http://paralleldementia.comicgenesis.com/d/20071221.html", + "PET": "http://petcomic.comicgenesis.com/d/20070413.html", + "PlanetsCollide": "http://ruthcomix.comicgenesis.com/d/20010706.html", + "RuneMaster": "http://runemaster.comicgenesis.com/d/20050607.html", + "ShinobiHigh": "http://shinobihigh.comicgenesis.com/d/20020118.html", + "spacejams": "http://spacejams.comicgenesis.com/d/20020820.html", + "TheAdventuresofVindibuddSuperheroInTraining": "http://vindibudd.comicgenesis.com/d/20070720.html", + "TriumphantLosers": "http://triumphantlosers.comicgenesis.com/d/20081006.html", + "Zortic": "http://zortic.comicgenesis.com/d/20030922.html", } def handle_url(url, res): diff --git a/scripts/mktestpage.py b/scripts/mktestpage.py index 00f61bec0..c07912b2d 100755 --- a/scripts/mktestpage.py +++ b/scripts/mktestpage.py @@ -17,12 +17,21 @@ htmltemplate = """ + + -

Dosage test results from %(date)s

-
    -%(content)s -
+

Dosage test results from %(date)s

+
+%(content)s +
+ """ @@ -80,7 +89,7 @@ def get_content(filename): inner = '%s' % (url, css, name) else: inner = '%s' % (css, name) - res.append('
  • %s
  • ' % inner) + res.append('
    %s
    ' % inner) return os.linesep.join(res) diff --git a/scripts/universal.py b/scripts/universal.py index fd2a671e5..79024903b 100755 --- a/scripts/universal.py +++ b/scripts/universal.py @@ -20,6 +20,20 @@ url_matcher = re.compile(r'
  • ([^<]+)') # names of comics to exclude exclude_comics = [ + "BusinessAndFinance", # not a comic + "ComicPanel", # not a comic + "ComicsAZ", # not a comic + "ComicStrip", # not a comic + "Espaol", # not a comic + "Family", # not a comic + "ForKids", # not a comic + "JamesBond", # not a comic + "Men", # not a comic + "NEA", # not a comic + "Pets", # not a comic + "SundayOnly", # not a comic + "WebExclusive", # not a comic + "Women", # not a comic ] diff --git a/tests/test_comics.py b/tests/test_comics.py index 108674b79..9e2b4586f 100644 --- a/tests/test_comics.py +++ b/tests/test_comics.py @@ -43,7 +43,7 @@ class _ComicTester(TestCase): self.check(images > 0, 'failed to find images at %s' % strip.stripUrl) if not self.scraperclass.multipleImagesPerStrip: self.check(images == 1, 'found %d instead of 1 image at %s' % (images, strip.stripUrl)) - if num > 0: + if num > 0 and self.scraperclass.prevUrlMatchesStripUrl: self.check_stripurl(strip) num += 1 if self.scraperclass.prevSearch: