1# -*- coding: utf-8 -*- 2# Copyright (C) 2004-2008 Tristan Seligmann and Jonathan Jacobs 3# Copyright (C) 2012-2014 Bastian Kleineidam 4# Copyright (C) 2015-2020 Tobias Gruetzmacher 5# Copyright (C) 2019-2020 Daniel Ring 6 7from __future__ import absolute_import, division, print_function 8 9from re import compile, escape 10 11from ..scraper import _BasicScraper, _ParserScraper 12from ..helpers import indirectStarter, xpath_class 13from ..util import tagre 14from .common import _ComicControlScraper, _WordPressScraper, _WPNavi, _WPWebcomic 15 16 17class Namesake(_ComicControlScraper): 18 url = 'http://namesakecomic.com/' 19 stripUrl = url + 'comic/%s' 20 firstStripUrl = stripUrl % 'the-journey-begins' 21 22 23class NatalieDee(_BasicScraper): 24 url = 'http://www.nataliedee.com/' 25 rurl = escape(url) 26 stripUrl = url + '%s' 27 firstStripUrl = stripUrl % '022806' 28 imageSearch = compile(tagre("img", "src", r'(%s\d+/[^"]+)' % rurl, 29 before="overflow")) 30 prevSearch = compile(tagre("a", "href", r'([^"]+)') + "<< Yesterday") 31 help = 'Index format: mmddyy' 32 33 def namer(self, image_url, page_url): 34 unused, date, filename = image_url.rsplit('/', 2) 35 return '%s-%s' % (date, filename) 36 37 38class Nedroid(_WordPressScraper): 39 url = 'http://nedroid.com/' 40 prevSearch = '//a[@rel="prev"]' 41 42 43class NeoCTC(_ParserScraper): 44 url = 'http://www.hirezfox.com/neoctc/' 45 stripUrl = url + 'd/%s.html' 46 firstStripUrl = stripUrl % '20071205' 47 imageSearch = '//img[contains(@src, "neoctc/comics")]' 48 prevSearch = '//a[./img[@alt="Previous Day"]]' 49 multipleImagesPerStrip = True 50 51 52class NeoEarth(_BasicScraper): 53 url = 'http://www.neo-earth.com/NE/' 54 stripUrl = url + 'index.php?date=%s' 55 firstStripUrl = stripUrl % '2007-03-23' 56 imageSearch = compile(r'<img src="(strips/.+?)"') 57 prevSearch = compile(r'<a href="(.+?)">Previous</a>') 58 help = 'Index format: yyyy-mm-dd' 59 60 61class NerfNow(_WordPressScraper): 62 url = 'https://www.nerfnow.com/' 63 prevSearch = '//li[@id="nav_previous"]/a' 64 65 66class Newshounds(_ParserScraper): 67 stripUrl = 'http://www.newshounds.com/%s.html' 68 url = stripUrl % 'nh2/20140929' 69 firstStripUrl = stripUrl % 'nh1/19971101' 70 imageSearch = '//img[@class="ksc"]' 71 prevSearch = '//a[./img[@alt="Previous comic"]]' 72 endOfLife = True 73 74 def getPrevUrl(self, url, data): 75 # Add navigation link between comic and graphic novel 76 if url == self.stripUrl % 'nh2/20070201': 77 return self.stripUrl % 'nh1/20061208' 78 return super(Newshounds, self).getPrevUrl(url, data) 79 80 81class NewWorld(_WordPressScraper): 82 url = ('https://web.archive.org/web/20190718012133/' 83 'http://www.tfsnewworld.com/') 84 stripUrl = url + '%s/' 85 firstStripUrl = stripUrl % '2007/08/30/63' 86 prevSearch = '//a[@rel="prev"]' 87 endOfLife = True 88 help = 'Index format: yyyy/mm/dd/stripn' 89 90 91class NichtLustig(_BasicScraper): 92 url = 'http://www.nichtlustig.de/main.html' 93 stripUrl = 'http://static.nichtlustig.de/toondb/%s.html' 94 lang = 'de' 95 imageSearch = compile(r'background-image:url\((http://static\.nichtlustig\.de/comics/full/\d+\.jpg)') 96 prevSearch = compile(tagre("a", "href", r'(http://static\.nichtlustig\.de/toondb/\d+\.html)')) 97 latestSearch = compile(tagre("a", "href", r'([^"]*toondb/\d+\.html)')) 98 help = 'Index format: yymmdd' 99 starter = indirectStarter 100 101 102class Nicky510(_WPNavi): 103 url = ('https://web.archive.org/web/20160510215718/' 104 'http://www.nickyitis.com/') 105 endOfLife = True 106 107 108class Nightshift(_ParserScraper): 109 url = 'http://www.poecatcomix.com/comics/nightshift/' 110 stripUrl = url + '%s/' 111 firstStripUrl = stripUrl % 'nightshift-volume1/ns-chapter-1' 112 imageSearch = '//div[@id="gallery-1"]//img' 113 prevSearch = ('//a[./span[text()="PAST CHAPTER"]]', 114 '//a[./span[text()="LAST CHAPTER"]]') 115 latestSearch = '//a[./img[contains(@src, "Latest-Page")]]' 116 starter = indirectStarter 117 multipleImagesPerStrip = True 118 adult = True 119 120 def namer(self, imageUrl, pageUrl): 121 # Prepend chapter title to page filenames 122 chapter = pageUrl.rstrip('/').rsplit('/', 1)[-1].replace('ns-', 'ns1-') 123 page = imageUrl.rsplit('/', 1)[-1] 124 return chapter + '_' + page 125 126 127class Nimona(_ParserScraper): 128 url = ('https://web.archive.org/web/20141008095502/' 129 'http://gingerhaze.com/nimona/') 130 stripUrl = url + 'comic/%s' 131 firstStripUrl = stripUrl % "page-1" 132 imageSearch = '//div[{}]//img'.format(xpath_class('field-name-field-comic-page')) 133 prevSearch = '//a[img[contains(@src, "/comicdrop_prev_label")]]' 134 endOfLife = True 135 136 137class NineToNine(_ParserScraper): 138 url = 'https://www.tigerknight.com/99' 139 stripUrl = url + '/%s' 140 firstStripUrl = stripUrl % '2014-01-01' 141 imageSearch = '//img[@class="comic-image"]' 142 prevSearch = '//a[@class="prev"]' 143 multipleImagesPerStrip = True 144 145 146class NobodyScores(_BasicScraper): 147 url = 'http://nobodyscores.loosenutstudio.com/' 148 rurl = escape(url) 149 stripUrl = url + 'index.php?id=%s' 150 firstStripUrl = stripUrl % '4' 151 imageSearch = compile(tagre("img", "src", r'(%scomix/[^"]+)' % rurl)) 152 multipleImagesPerStrip = True 153 prevSearch = compile(r'<a href="(%sindex.php.+?)">the one before </a>' % rurl) 154 help = 'Index format: nnn' 155 156 157class NoMoreSavePoints(_WordPressScraper): 158 url = 'http://www.flowerlarkstudios.com/comicpage/no-more-save-points/mushroom-hopping/' 159 firstStripUrl = url 160 starter = indirectStarter 161 162 163class NoNeedForBushido(_ParserScraper): 164 url = 'http://nn4b.com/' 165 stripUrl = url + 'comic/%s' 166 imageSearch = '//div[@id="comic-image"]//img' 167 prevSearch = '//a[@rel="prev"]' 168 help = 'Index format: nnn' 169 170 171class NonPlayerCharacter(_ParserScraper): 172 url = 'https://www.lfg.co/' 173 stripUrl = url + 'npc/tale/%s/' 174 firstStripUrl = stripUrl % '1-1' 175 imageSearch = '//div[@id="comic-img"]//img' 176 prevSearch = '//a[@class="comic-nav-prev"]' 177 latestSearch = '//div[@id="feature-npc-footer"]/a[contains(@href, "npc/tale/")]' 178 starter = indirectStarter 179 180 def namer(self, imageUrl, pageUrl): 181 return pageUrl.rstrip('/').rsplit('/', 1)[-1] 182 183 184class NotAVillain(_WPWebcomic): 185 url = 'http://navcomic.com/' 186 stripUrl = url + 'not-a-villain/%s/' 187 firstStripUrl = stripUrl % 'v1-001' 188 189 def namer(self, imageUrl, pageUrl): 190 filename = imageUrl.rsplit('/', 1)[-1] 191 # Fix filenames missing "Page" 192 if filename[2].isdigit(): 193 filename = filename[0] + '-Page' + filename[2:] 194 # Fix filenames of early comics 195 filename = filename.replace('Page-', '1-Page') 196 if filename.startswith('0-Page'): 197 filename = '1' + filename[1:] 198 return filename 199 200 201class NotInventedHere(_ParserScraper): 202 url = 'http://notinventedhe.re/' 203 stripUrl = url + 'on/%s' 204 firstStripUrl = stripUrl % '2009-9-21' 205 imageSearch = '//div[@id="comic-content"]//img' 206 prevSearch = '//a[@id="nav-previous"]' 207 help = 'Index format: yyyy-m-d' 208 209 210class Nukees(_BasicScraper): 211 url = 'http://www.nukees.com/' 212 stripUrl = url + 'd/%s' 213 firstStripUrl = stripUrl % '19970121' 214 imageSearch = compile(r'"comic".+?"(/comics/.+?)"') 215 prevSearch = compile(r'"(/d/.+?)".+?previous') 216 help = 'Index format: yyyymmdd.html' 217