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 8from re import compile, escape 9 10from ..util import tagre 11from ..scraper import _BasicScraper, _ParserScraper 12from ..helpers import indirectStarter, joinPathPartsNamer, xpath_class 13from .common import _ComicControlScraper, _WPNaviIn, _WordPressScraper 14 15 16class FalconTwin(_BasicScraper): 17 url = 'http://www.falcontwin.com/' 18 stripUrl = url + 'index.html?strip=%s' 19 firstStripUrl = stripUrl % '0' 20 imageSearch = compile(r'"(strips/.+?)"') 21 prevSearch = compile(r'"prev"><a href="(index.+?)"') 22 help = 'Index format: nnn' 23 24 25class Faneurysm(_WPNaviIn): 26 url = 'http://hijinksensue.com/comic/think-only-tree/' 27 firstStripUrl = 'http://hijinksensue.com/comic/captains-prerogative/' 28 endOfLife = True 29 30 31class FantasyRealms(_ParserScraper): 32 stripUrl = ('https://web.archive.org/web/20161204192651/' 33 'http://fantasyrealmsonline.com/manga/%s.php') 34 url = stripUrl % '091' 35 firstStripUrl = stripUrl % '001' 36 imageSearch = '//img[contains(@src, "/manga/0")]' 37 prevSearch = '//a[img[contains(@src, "nav-back")]]' 38 endOfLife = True 39 help = 'Index format: nnn' 40 41 42class FarToTheNorth(_ComicControlScraper): 43 url = 'http://www.farnorthcomic.com/' 44 stripUrl = url + 'comic/%s' 45 firstStripUrl = stripUrl % 'don39t-tell' 46 47 48class FauxPas(_ParserScraper): 49 url = 'http://www.ozfoxes.net/cgi/pl-fp1.cgi' 50 stripUrl = url + '?%s' 51 firstStripUrl = stripUrl % '1' 52 imageSearch = '//img[@name]' 53 prevSearch = '//a[img[@alt="Previous"]]' 54 help = 'Index format: nnn' 55 56 57class FireflyCross(_WordPressScraper): 58 url = 'http://www.fireflycross.pensandtales.com/' 59 firstStripUrl = url + '?comic=05062002' 60 61 62class FirstWorldProblems(_ParserScraper): 63 url = ('https://web.archive.org/web/20150710053456/' 64 'http://bradcolbow.com/archive/C5/') 65 stripUrl = url + '%s/' 66 firstStripUrl = stripUrl % 'P10' 67 imageSearch = '//div[{}]//img'.format(xpath_class('entry')) 68 prevSearch = '//a[{}]'.format(xpath_class('prev')) 69 multipleImagesPerStrip = True 70 endOfLife = True 71 72 73class FlakyPastry(_BasicScraper): 74 baseUrl = 'http://flakypastry.runningwithpencils.com/' 75 url = baseUrl + 'index.php' 76 stripUrl = baseUrl + 'comic.php?strip_id=%s' 77 firstStripUrl = stripUrl % '0' 78 imageSearch = compile(r'<img src="(comics/.+?)"') 79 prevSearch = compile(r'<a href="(.+?)".+?btn_back') 80 help = 'Index format: nnnn' 81 82 83class Flemcomics(_ParserScraper): 84 url = ('https://web.archive.org/web/20180414110349/' 85 'http://www.flemcomics.com/') 86 stripUrl = url + 'd/%s.html' 87 firstStripUrl = stripUrl % '19980101' 88 imageSearch = '//img[{}]'.format(xpath_class('ksc')) 89 prevSearch = '//a[@rel="prev"]' 90 endOfLife = True 91 help = 'Index format: yyyymmdd' 92 93 94class Flipside(_ParserScraper): 95 url = 'http://flipside.keenspot.com/comic.php' 96 stripUrl = url + '?i=%s' 97 firstStripUrl = stripUrl % '1' 98 imageSearch = '//img[contains(@src, "comic/")]' 99 prevSearch = '//a[@rel="prev"]' 100 help = 'Index format: nnnn' 101 102 103class FonFlatter(_ParserScraper): 104 url = 'https://www.fonflatter.de/' 105 stripUrl = url + '%s/' 106 firstStripUrl = url + '2005/09/20/01-begegnung-mit-batman/' 107 lang = 'de' 108 imageSearch = r'//img[re:test(@src, "/fred_\d+")]' 109 prevSearch = '//a[@rel="prev"]' 110 help = 'Index format: yyyy/mm/dd/number-stripname' 111 112 def shouldSkipUrl(self, url, data): 113 return url in ( 114 self.stripUrl % "2006/11/30/adventskalender", 115 self.stripUrl % "2006/09/21/danke", 116 self.stripUrl % "2006/08/23/zgf-zuweilen-gestellte-fragen", 117 self.stripUrl % "2005/10/19/naq-never-asked-questions", 118 ) 119 120 121class ForestHill(_WordPressScraper): 122 url = 'https://www.foresthillcomic.org/' 123 124 125class ForLackOfABetterComic(_BasicScraper): 126 url = 'http://forlackofabettercomic.com/' 127 rurl = r'http://(?:www\.)?forlackofabettercomic\.com/' 128 stripUrl = url + '?id=%s' 129 firstStripUrl = stripUrl % '1' 130 imageSearch = compile(tagre("img", "src", r'(%simg/comic/\d+[^"]+)' % rurl, after="comicimg")) 131 prevSearch = compile(tagre("a", "href", r'(%s\?id\=\d+)' % rurl) + r'Prev') 132 help = 'Index format: number' 133 134 135class FoxDad(_ParserScraper): 136 url = 'https://foxdad.com/' 137 stripUrl = url + 'post/%s' 138 firstStripUrl = stripUrl % '149683014997/some-people-are-just-different-support-the-comic' 139 imageSearch = '//figure[@class="photo-hires-item"]//img' 140 prevSearch = '//a[@class="previous-button"]' 141 142 def namer(self, imageUrl, pageUrl): 143 page = self.getPage(pageUrl) 144 post = page.xpath('//link[@type="application/json+oembed"]')[0].get('href') 145 post = post.replace('https://www.tumblr.com/oembed/1.0?url=https://foxdad.com/post', '') 146 post = post.replace('-support-me-on-patreon', '') 147 return post.replace('/', '-') 148 149 150class FoxTails(_ParserScraper): 151 stripUrl = 'http://foxtails.magickitsune.com/strips/%s.html' 152 url = stripUrl % 'current' 153 firstStripUrl = stripUrl % '20041024' 154 imageSearch = '//img[contains(@src, "img/2")]' 155 prevSearch = '//a[./img[contains(@src, "prev")]]' 156 endOfLife = True 157 158 def getPrevUrl(self, url, data): 159 # Include pre-reboot archive 160 if url == self.stripUrl % '20090906': 161 return self.stripUrl % '20090704' 162 return super(FoxTails, self).getPrevUrl(url, data) 163 164 165class Fragile(_ParserScraper): 166 url = ('https://web.archive.org/web/20190308203109/' 167 'http://www.fragilestory.com/') 168 imageSearch = '//div[@id="comic_strip"]/a[@class="nobg"]/img' 169 prevSearch = '//div[@id="nav_comic_a"]/a[2]' 170 firstStripUrl = url + 'strips/chapter_01' 171 endOfLife = True 172 173 174class FredoAndPidjin(_ParserScraper): 175 url = 'https://www.pidjin.net/' 176 stripUrl = url + '%s/' 177 firstStripUrl = stripUrl % '2006/02/19/goofy-monday' 178 imageSearch = '//div[%s]//img' % xpath_class("episode") 179 multipleImagesPerStrip = True 180 prevSearch = '//span[%s]/a' % xpath_class("prev") 181 latestSearch = '//section[%s]//a' % xpath_class("latest") 182 starter = indirectStarter 183 namer = joinPathPartsNamer((0, 1, 2)) 184 185 186class Freefall(_ParserScraper): 187 url = 'http://freefall.purrsia.com/' 188 stripUrl = url + 'ff%d/%s%05d.htm' 189 firstStripUrl = stripUrl % (100, 'fv', 1) 190 imageSearch = '//img[contains(@src, "/ff")]' 191 prevSearch = '//a[text()="Previous"]' 192 multipleImagesPerStrip = True 193 194 def getIndexStripUrl(self, index): 195 # Get comic strip URL from index 196 index = int(index) 197 chapter = index + 100 - (index % 100) 198 color = 'fc' if index > 1252 else 'fv' 199 return self.stripUrl % (chapter, color, index) 200 201 202class FreighterTails(_ParserScraper): 203 url = 'http://www.mzzkiti.com/' 204 stripUrl = url + 'log%s.htm' 205 firstStripUrl = stripUrl % '001' 206 imageSearch = ('//img[contains(@src, "Strip")]', 207 '//img[contains(@src, "Caption")]') 208 prevSearch = '//a[./img[contains(@src, "prev")]]' 209 endOfLife = True 210 211 212class FullFrontalNerdity(_BasicScraper): 213 url = 'http://ffn.nodwick.com/' 214 rurl = escape(url) 215 stripUrl = url + '?p=%s' 216 firstStripUrl = stripUrl % '6' 217 imageSearch = compile(tagre("img", "src", r'(%sffnstrips/\d+-\d+-\d+\.[^"]+)' % rurl)) 218 prevSearch = compile(tagre("a", "href", r'(%s\?p=\d+)' % rurl, after="prev")) 219 help = 'Index format: number' 220 221 222class FunInJammies(_WordPressScraper): 223 url = ('https://web.archive.org/web/20170205105241/' 224 'http://funinjammies.com/') 225 stripUrl = url + 'comic.php?issue=%s' 226 firstStripUrl = stripUrl % '1' 227 prevSearch = '//a[text()="< Prev"]' 228 endOfLife = True 229 help = 'Index format: n (unpadded)' 230 231 232class FurPiled(_ParserScraper): 233 stripUrl = ('https://web.archive.org/web/20160404074145/' 234 'http://www.liondogworks.com/images/fp-%03d.jpg') 235 url = stripUrl % 427 236 firstStripUrl = stripUrl % 1 237 endOfLife = True 238 239 def getPrevUrl(self, url, data): 240 # Skip missing pages 241 nextStrip = int(url.rsplit('/', 1)[-1].split('.', 1)[0].replace('fp-', '')) - 1 242 if nextStrip in [407, 258, 131, 110, 97, 31]: 243 nextStrip = nextStrip - 1 244 return self.stripUrl % nextStrip 245 246 def fetchUrls(self, url, data, urlSearch): 247 # URLs are direct links to images 248 return [url] 249 250 251class FurthiaHigh(_ParserScraper): 252 url = 'http://furthiahigh.concessioncomic.com/' 253 stripUrl = url + 'index.php?pid=%s' 254 firstStripUrl = stripUrl % '20080128' 255 imageSearch = '//img[contains(@alt, "Comic")]' 256 prevSearch = '//a[./img[@alt="Previous"]]' 257 multipleImagesPerStrip = True 258