mirror of
https://github.com/wassname/FanFicFare.git
synced 2026-09-13 12:11:20 +08:00
Compare commits
63
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a4e499866e | ||
|
|
5736f4f181 | ||
|
|
e04453d73f | ||
|
|
c3778502dc | ||
|
|
925b12e776 | ||
|
|
62ed503d10 | ||
|
|
7e35d0b710 | ||
|
|
20c7e7f075 | ||
|
|
9f61cff7cd | ||
|
|
cb5587b0c7 | ||
|
|
f2a74c9ffc | ||
|
|
eb0f013550 | ||
|
|
6674e19f94 | ||
|
|
29b1ca9a7e | ||
|
|
7cae65300a | ||
|
|
88fe13f603 | ||
|
|
a9b6989341 | ||
|
|
a54277058c | ||
|
|
4c27e19aa8 | ||
|
|
6f5ed2bcac | ||
|
|
cc0bccd420 | ||
|
|
85bbcac92e | ||
|
|
f8776e118a | ||
|
|
31b7257496 | ||
|
|
b5d00951de | ||
|
|
c73f7693a4 | ||
|
|
e35927c9a2 | ||
|
|
e8e93b010a | ||
|
|
6414a09dbd | ||
|
|
d5e7907068 | ||
|
|
3175346214 | ||
|
|
8b31ba59af | ||
|
|
92c60d065e | ||
|
|
ba6852eec4 | ||
|
|
72086e6ecf | ||
|
|
f8a2cb949f | ||
|
|
07d1a1096f | ||
|
|
9f4fe192be | ||
|
|
56cd2b2039 | ||
|
|
b2a41a9b10 | ||
|
|
55e18f9446 | ||
|
|
855c284389 | ||
|
|
a31de1d5ef | ||
|
|
7ac00b53ab | ||
|
|
9c0519316d | ||
|
|
d9fbccbef5 | ||
|
|
0c622b379e | ||
|
|
83d210566b | ||
|
|
ab0b25317b | ||
|
|
e10ae5fbe4 | ||
|
|
62eb103ff5 | ||
|
|
8e984e62fb | ||
|
|
fd270789ac | ||
|
|
f6bd941369 | ||
|
|
54ae77082a | ||
|
|
b3c30f6a21 | ||
|
|
84bc9b3a3e | ||
|
|
e59673fdd7 | ||
|
|
8d2b9646fb | ||
|
|
7fc3a2ad2d | ||
|
|
8c0a216e46 | ||
|
|
9b08fe3bfb | ||
|
|
b4ffb2f9d9 |
@@ -1,6 +1,6 @@
|
||||
# ffd-retief-hrd fanfictiondownloader
|
||||
application: fanfictiondownloader
|
||||
version: 4-4-63
|
||||
version: 4-4-70
|
||||
runtime: python27
|
||||
api_version: 1
|
||||
threadsafe: true
|
||||
|
||||
@@ -26,7 +26,7 @@ class FanFictionDownLoaderBase(InterfaceActionBase):
|
||||
description = 'UI plugin to download FanFiction stories from various sites.'
|
||||
supported_platforms = ['windows', 'osx', 'linux']
|
||||
author = 'Jim Miller'
|
||||
version = (1, 7, 30)
|
||||
version = (1, 7, 41)
|
||||
minimum_calibre_version = (0, 8, 57)
|
||||
|
||||
#: This field defines the GUI plugin class that contains all the code
|
||||
|
||||
@@ -17,6 +17,7 @@ from PyQt4.Qt import (QDialog, QWidget, QVBoxLayout, QHBoxLayout, QLabel,
|
||||
|
||||
from calibre.gui2.ui import get_gui
|
||||
from calibre.gui2 import dynamic, info_dialog
|
||||
from calibre.constants import numeric_version as calibre_version
|
||||
|
||||
from calibre_plugins.fanfictiondownloader_plugin.prefs import prefs, PREFS_NAMESPACE
|
||||
from calibre_plugins.fanfictiondownloader_plugin.dialogs \
|
||||
@@ -168,6 +169,8 @@ class ConfigWidget(QWidget):
|
||||
prefs['updatecover'] = self.basic_tab.updatecover.isChecked()
|
||||
prefs['updateepubcover'] = self.basic_tab.updateepubcover.isChecked()
|
||||
prefs['keeptags'] = self.basic_tab.keeptags.isChecked()
|
||||
prefs['suppressauthorsort'] = self.basic_tab.suppressauthorsort.isChecked()
|
||||
prefs['suppresstitlesort'] = self.basic_tab.suppresstitlesort.isChecked()
|
||||
prefs['showmarked'] = self.basic_tab.showmarked.isChecked()
|
||||
prefs['urlsfromclip'] = self.basic_tab.urlsfromclip.isChecked()
|
||||
prefs['updatedefault'] = self.basic_tab.updatedefault.isChecked()
|
||||
@@ -176,7 +179,9 @@ class ConfigWidget(QWidget):
|
||||
prefs['includeimages'] = self.basic_tab.includeimages.isChecked()
|
||||
prefs['lookforurlinhtml'] = self.basic_tab.lookforurlinhtml.isChecked()
|
||||
prefs['checkforseriesurlid'] = self.basic_tab.checkforseriesurlid.isChecked()
|
||||
prefs['checkforurlchange'] = self.basic_tab.checkforurlchange.isChecked()
|
||||
prefs['injectseries'] = self.basic_tab.injectseries.isChecked()
|
||||
prefs['smarten_punctuation'] = self.basic_tab.smarten_punctuation.isChecked()
|
||||
|
||||
if self.readinglist_tab:
|
||||
# lists
|
||||
@@ -320,6 +325,12 @@ class BasicTab(QWidget):
|
||||
self.updateepubcover.setChecked(prefs['updateepubcover'])
|
||||
self.l.addWidget(self.updateepubcover)
|
||||
|
||||
self.smarten_punctuation = QCheckBox('Smarten Punctuation (EPUB only)',self)
|
||||
self.smarten_punctuation.setToolTip("Run Smarten Punctuation from Calibre's Polish Book feature on each EPUB download and update.")
|
||||
self.smarten_punctuation.setChecked(prefs['smarten_punctuation'])
|
||||
if calibre_version >= (0, 9, 39):
|
||||
self.l.addWidget(self.smarten_punctuation)
|
||||
|
||||
cali_gb = groupbox = QGroupBox("Updating Calibre Options")
|
||||
self.l = QVBoxLayout()
|
||||
groupbox.setLayout(self.l)
|
||||
@@ -339,11 +350,26 @@ class BasicTab(QWidget):
|
||||
self.keeptags.setChecked(prefs['keeptags'])
|
||||
self.l.addWidget(self.keeptags)
|
||||
|
||||
self.suppressauthorsort = QCheckBox('Force Author into Author Sort?',self)
|
||||
self.suppressauthorsort.setToolTip("If checked, the author(s) as given will be used for the Author Sort, too.\nIf not checked, calibre will apply it's built in algorithm which makes 'Bob Smith' sort as 'Smith, Bob', etc.")
|
||||
self.suppressauthorsort.setChecked(prefs['suppressauthorsort'])
|
||||
self.l.addWidget(self.suppressauthorsort)
|
||||
|
||||
self.suppresstitlesort = QCheckBox('Force Title into Title Sort?',self)
|
||||
self.suppresstitlesort.setToolTip("If checked, the title as given will be used for the Title Sort, too.\nIf not checked, calibre will apply it's built in algorithm which makes 'The Title' sort as 'Title, The', etc.")
|
||||
self.suppresstitlesort.setChecked(prefs['suppresstitlesort'])
|
||||
self.l.addWidget(self.suppresstitlesort)
|
||||
|
||||
self.checkforseriesurlid = QCheckBox("Check for existing Series Anthology books?",self)
|
||||
self.checkforseriesurlid.setToolTip("Check for existings Series Anthology books using each new story's series URL before downloading.\nOffer to skip downloading if a Series Anthology is found.")
|
||||
self.checkforseriesurlid.setChecked(prefs['checkforseriesurlid'])
|
||||
self.l.addWidget(self.checkforseriesurlid)
|
||||
|
||||
self.checkforurlchange = QCheckBox("Check for changed Story URL?",self)
|
||||
self.checkforurlchange.setToolTip("Warn you if an update will change the URL of an existing book.")
|
||||
self.checkforurlchange.setChecked(prefs['checkforurlchange'])
|
||||
self.l.addWidget(self.checkforurlchange)
|
||||
|
||||
self.lookforurlinhtml = QCheckBox("Search EPUB text for Story URL?",self)
|
||||
self.lookforurlinhtml.setToolTip("Look for first valid story URL inside EPUB text if not found in metadata.\nSomewhat risky, could find wrong URL depending on EPUB content.\nAlso finds and corrects bad ffnet URLs from ficsaver.com files.")
|
||||
self.lookforurlinhtml.setChecked(prefs['lookforurlinhtml'])
|
||||
@@ -495,7 +521,7 @@ class PersonalIniTab(QWidget):
|
||||
self.ini = QTextEdit(self)
|
||||
try:
|
||||
self.ini.setFont(QFont("Courier",
|
||||
self.plugin_action.gui.font().pointSize()+1));
|
||||
self.plugin_action.gui.font().pointSize()+1))
|
||||
except Exception as e:
|
||||
print("Couldn't get font: %s"%e)
|
||||
self.ini.setLineWrapMode(QTextEdit.NoWrap)
|
||||
@@ -531,7 +557,7 @@ class ShowDefaultsIniDialog(QDialog):
|
||||
self.ini.setToolTip("These are all of the plugin's configurable options\nand their default settings.")
|
||||
try:
|
||||
self.ini.setFont(QFont("Courier",
|
||||
get_gui().font().pointSize()+1));
|
||||
get_gui().font().pointSize()+1))
|
||||
except Exception as e:
|
||||
print("Couldn't get font: %s"%e)
|
||||
self.ini.setLineWrapMode(QTextEdit.NoWrap)
|
||||
|
||||
@@ -164,7 +164,7 @@ class DroppableQTextEdit(QTextEdit):
|
||||
|
||||
def canInsertFromMimeData(self, source):
|
||||
if source.hasUrls():
|
||||
return True;
|
||||
return True
|
||||
else:
|
||||
return QTextEdit.canInsertFromMimeData(self,source)
|
||||
|
||||
@@ -208,7 +208,7 @@ class AddNewDialog(SizePersistedDialog):
|
||||
self.groupbox.setChecked(False)
|
||||
self.groupbox.setFlat(True)
|
||||
print("style:%s"%self.groupbox.styleSheet())
|
||||
self.groupbox.setStyleSheet(gpstyle);
|
||||
self.groupbox.setStyleSheet(gpstyle)
|
||||
|
||||
self.gbf = QFrame()
|
||||
self.gbl = QVBoxLayout()
|
||||
@@ -383,6 +383,7 @@ class AddNewDialog(SizePersistedDialog):
|
||||
'collision': unicode(self.collision.currentText()),
|
||||
'updatemeta': self.updatemeta.isChecked(),
|
||||
'updateepubcover': self.updateepubcover.isChecked(),
|
||||
'smarten_punctuation':self.prefs['smarten_punctuation']
|
||||
}
|
||||
|
||||
if self.merge:
|
||||
@@ -618,7 +619,8 @@ class UpdateExistingDialog(SizePersistedDialog):
|
||||
def __init__(self, gui, header, prefs, icon, books,
|
||||
save_size_name='fanfictiondownloader_plugin:update list dialog'):
|
||||
SizePersistedDialog.__init__(self, gui, save_size_name)
|
||||
|
||||
|
||||
self.prefs = prefs
|
||||
self.setWindowTitle(header)
|
||||
self.setWindowIcon(icon)
|
||||
|
||||
@@ -736,6 +738,7 @@ class UpdateExistingDialog(SizePersistedDialog):
|
||||
'collision': unicode(self.collision.currentText()),
|
||||
'updatemeta': self.updatemeta.isChecked(),
|
||||
'updateepubcover': self.updateepubcover.isChecked(),
|
||||
'smarten_punctuation':self.prefs['smarten_punctuation']
|
||||
}
|
||||
|
||||
class StoryListTableWidget(QTableWidget):
|
||||
|
||||
+160
-23
@@ -7,13 +7,16 @@ __license__ = 'GPL v3'
|
||||
__copyright__ = '2012, Jim Miller'
|
||||
__docformat__ = 'restructuredtext en'
|
||||
|
||||
import time, os, copy, threading, re, platform
|
||||
import time, os, copy, threading, re, platform, sys
|
||||
from StringIO import StringIO
|
||||
from functools import partial
|
||||
from datetime import datetime
|
||||
from string import Template
|
||||
import urllib
|
||||
import email
|
||||
import traceback
|
||||
|
||||
from PyQt4.Qt import (QApplication, QMenu, QToolButton)
|
||||
from PyQt4.Qt import (QApplication, QMenu, QToolButton, QTimer)
|
||||
|
||||
from PyQt4.Qt import QPixmap, Qt
|
||||
from PyQt4.QtCore import QBuffer
|
||||
@@ -21,7 +24,7 @@ from PyQt4.QtCore import QBuffer
|
||||
from calibre.constants import numeric_version as calibre_version
|
||||
|
||||
from calibre.ptempfile import PersistentTemporaryFile, PersistentTemporaryDirectory, remove_dir
|
||||
from calibre.ebooks.metadata import MetaInformation, authors_to_string
|
||||
from calibre.ebooks.metadata import MetaInformation
|
||||
from calibre.ebooks.metadata.meta import get_metadata
|
||||
from calibre.gui2 import error_dialog, warning_dialog, question_dialog, info_dialog
|
||||
from calibre.gui2.dialogs.message_box import ViewLog
|
||||
@@ -38,7 +41,7 @@ from calibre_plugins.fanfictiondownloader_plugin.common_utils import (set_plugin
|
||||
|
||||
from calibre_plugins.fanfictiondownloader_plugin.fanficdownloader import adapters, exceptions
|
||||
from calibre_plugins.fanfictiondownloader_plugin.fanficdownloader.epubutils import get_dcsource, get_dcsource_chaptercount, get_story_url_from_html
|
||||
from calibre_plugins.fanfictiondownloader_plugin.fanficdownloader.geturls import get_urls_from_page
|
||||
from calibre_plugins.fanfictiondownloader_plugin.fanficdownloader.geturls import get_urls_from_page, get_urls_from_html, get_urls_from_text
|
||||
|
||||
from calibre_plugins.fanfictiondownloader_plugin.ffdl_util import (get_ffdl_adapter, get_ffdl_config, get_ffdl_personalini)
|
||||
from calibre_plugins.fanfictiondownloader_plugin.config import (permitted_values, rejecturllist)
|
||||
@@ -144,6 +147,72 @@ class FanFictionDownLoaderPlugin(InterfaceAction):
|
||||
self.macmenuhack = os.access(file_path, os.F_OK)
|
||||
return self.macmenuhack
|
||||
|
||||
accepts_drops = True
|
||||
|
||||
def accept_enter_event(self, event, mime_data):
|
||||
if mime_data.hasFormat("application/calibre+from_library") or \
|
||||
mime_data.hasFormat("text/plain") or \
|
||||
mime_data.hasFormat("text/uri-list"):
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def accept_drag_move_event(self, event, mime_data):
|
||||
return self.accept_enter_event(event, mime_data)
|
||||
|
||||
def drop_event(self, event, mime_data):
|
||||
|
||||
dropped_ids=None
|
||||
urllist=[]
|
||||
|
||||
mime = 'application/calibre+from_library'
|
||||
if mime_data.hasFormat(mime):
|
||||
dropped_ids = tuple(map(int, str(mime_data.data(mime)).split()))
|
||||
|
||||
mimetype='text/uri-list'
|
||||
filelist="%s"%event.mimeData().data(mimetype)
|
||||
if filelist:
|
||||
for f in filelist.splitlines():
|
||||
#print("filename:%s"%f)
|
||||
if f.endswith(".eml"):
|
||||
fhandle = urllib.urlopen(f)
|
||||
msg = email.message_from_file(fhandle)
|
||||
if msg.is_multipart():
|
||||
for part in msg.walk():
|
||||
#print("part type:%s"%part.get_content_type())
|
||||
if part.get_content_type() == "text/html":
|
||||
#print("URL list:%s"%get_urls_from_data(part.get_payload(decode=True)))
|
||||
urllist.extend(get_urls_from_html(part.get_payload(decode=True)))
|
||||
if part.get_content_type() == "text/plain":
|
||||
#print("part content:text/plain")
|
||||
#print("part content:%s"%part.get_payload(decode=True))
|
||||
urllist.extend(get_urls_from_text(part.get_payload(decode=True)))
|
||||
else:
|
||||
urllist.extend(get_urls_from_text("%s"%msg))
|
||||
else:
|
||||
urllist.extend(get_urls_from_text(f))
|
||||
else:
|
||||
mimetype='text/plain'
|
||||
if mime_data.hasFormat(mimetype):
|
||||
#print("text/plain:%s"%event.mimeData().data(mimetype))
|
||||
urllist.extend(get_urls_from_text(event.mimeData().data(mimetype)))
|
||||
|
||||
#print("urllist:%s\ndropped_ids:%s"%(urllist,dropped_ids))
|
||||
if urllist or dropped_ids:
|
||||
QTimer.singleShot(1, partial(self.do_drop,
|
||||
dropped_ids=dropped_ids,
|
||||
urllist=urllist))
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def do_drop(self,dropped_ids=None,urllist=None):
|
||||
# shouldn't ever be both.
|
||||
if dropped_ids:
|
||||
self.update_dialog(dropped_ids)
|
||||
elif urllist:
|
||||
self.add_dialog("\n".join(urllist))
|
||||
|
||||
def about_to_show_menu(self):
|
||||
self.rebuild_menus()
|
||||
|
||||
@@ -554,19 +623,21 @@ class FanFictionDownLoaderPlugin(InterfaceAction):
|
||||
# Now that we've
|
||||
self.prep_downloads( options, update_books, merge=True )
|
||||
|
||||
def update_dialog(self):
|
||||
def update_dialog(self, id_list=None):
|
||||
if not self.is_library_view():
|
||||
self.gui.status_bar.show_message(_('Cannot Update Books from Device View'), 3000)
|
||||
return
|
||||
|
||||
if not id_list:
|
||||
id_list = self.gui.library_view.get_selected_ids()
|
||||
|
||||
if len(self.gui.library_view.get_selected_ids()) == 0:
|
||||
if len(id_list) == 0:
|
||||
self.gui.status_bar.show_message(_('No Selected Books to Update'), 3000)
|
||||
return
|
||||
#print("update_dialog()")
|
||||
|
||||
db = self.gui.current_db
|
||||
book_list = map( partial(self.make_book_id_only), self.gui.library_view.get_selected_ids() )
|
||||
#book_ids = self.gui.library_view.get_selected_ids()
|
||||
book_list = map( self.make_book_id_only, id_list )
|
||||
|
||||
for j, book in enumerate(book_list):
|
||||
book['listorder'] = j
|
||||
@@ -848,7 +919,7 @@ class FanFictionDownLoaderPlugin(InterfaceAction):
|
||||
|
||||
if book_id and mi: # book_id and mi only set if matched by title/author.
|
||||
liburl = self.get_story_url(db,book_id)
|
||||
if book['url'] != liburl:
|
||||
if book['url'] != liburl and prefs['checkforurlchange']:
|
||||
if collision in (OVERWRITE,OVERWRITEALWAYS):
|
||||
updat="overwrit"
|
||||
else:
|
||||
@@ -906,6 +977,8 @@ class FanFictionDownLoaderPlugin(InterfaceAction):
|
||||
skip_date_update = True
|
||||
elif chaptercount > urlchaptercount:
|
||||
raise NotGoingToDownload("Existing epub contains %d chapters, web site only has %d. Use Overwrite to force update." % (chaptercount,urlchaptercount),'dialog_error.png')
|
||||
elif chaptercount == 0:
|
||||
raise NotGoingToDownload("FFDL doesn't recognize chapters in existing epub, epub is probably from a different source. Use Overwrite to force update.",'dialog_error.png')
|
||||
|
||||
if collision == OVERWRITE and \
|
||||
db.has_format(book_id,formmapping[fileform],index_is_id=True):
|
||||
@@ -931,7 +1004,7 @@ class FanFictionDownLoaderPlugin(InterfaceAction):
|
||||
mi = db.get_metadata(book_id,index_is_id=True)
|
||||
if not book['series'] and mi.series != None:
|
||||
book['calibre_series'] = (mi.series,mi.series_index)
|
||||
print("calibre_series:%s [%s]"%book['calibre_series'])
|
||||
#print("calibre_series:%s [%s]"%book['calibre_series'])
|
||||
|
||||
if book['good']: # there shouldn't be any !'good' books at this point.
|
||||
# if still 'good', make a temp file to write the output to.
|
||||
@@ -1036,7 +1109,17 @@ class FanFictionDownLoaderPlugin(InterfaceAction):
|
||||
|
||||
if options['collision'] == CALIBREONLY or \
|
||||
( (options['updatemeta'] or book['added']) and book['good'] ):
|
||||
self.update_metadata(db, book['calibre_id'], book, mi, options)
|
||||
try:
|
||||
self.update_metadata(db, book['calibre_id'], book, mi, options)
|
||||
except:
|
||||
det_msg = "".join(traceback.format_exception(*sys.exc_info()))+"\nStory Details:\n%s"%pretty_book(book)
|
||||
print("Error Updating Metadata:\n%s"%det_msg)
|
||||
error_dialog(self.gui,
|
||||
"Error Updating Metadata",
|
||||
"<p>An error has occurred while FFDL was updating calibre's metadata for <a href='%s'>%s</a>.</p>"%(book['url'],book['title'])+
|
||||
"The ebook has been updated, but the metadata has not.",
|
||||
det_msg=det_msg,
|
||||
show=True)
|
||||
|
||||
def update_books_finish(self, book_list, options={}, showlist=True):
|
||||
'''Notify calibre about updated rows, update external plugins
|
||||
@@ -1087,10 +1170,20 @@ class FanFictionDownLoaderPlugin(InterfaceAction):
|
||||
self.gui.library_view.sort_by_named_field('marked', True)
|
||||
|
||||
self.gui.status_bar.show_message(_('Finished Adding/Updating %d books.'%(len(update_list) + len(add_list))), 3000)
|
||||
|
||||
|
||||
1+1
|
||||
|
||||
print("all done, remove temp dir.")
|
||||
|
||||
1+1
|
||||
|
||||
remove_dir(options['tdir'])
|
||||
|
||||
1+1
|
||||
|
||||
print("removed temp dir.")
|
||||
|
||||
|
||||
if 'Count Pages' in self.gui.iactions and len(prefs['countpagesstats']) and len(all_ids):
|
||||
cp_plugin = self.gui.iactions['Count Pages']
|
||||
cp_plugin.count_statistics(all_ids,prefs['countpagesstats'])
|
||||
@@ -1298,14 +1391,23 @@ class FanFictionDownLoaderPlugin(InterfaceAction):
|
||||
oldmi = db.get_metadata(book_id,index_is_id=True)
|
||||
if prefs['keeptags']:
|
||||
old_tags = db.get_tags(book_id)
|
||||
#print("old_tags:%s"%old_tags)
|
||||
#print("mi.tags:%s"%mi.tags)
|
||||
# remove old Completed/In-Progress only if there's a new one.
|
||||
if 'Completed' in mi.tags or 'In-Progress' in mi.tags:
|
||||
old_tags = filter( lambda x : x not in ('Completed', 'In-Progress'), old_tags)
|
||||
# remove old Last Update tags if there are new ones.
|
||||
if len(filter( lambda x : not x.startswith("Last Update"), mi.tags)) > 0:
|
||||
old_tags = filter( lambda x : not x.startswith("Last Update"), old_tags)
|
||||
|
||||
# mi.tags needs to be list, but set kills dups.
|
||||
mi.tags = list(set(list(old_tags)+mi.tags))
|
||||
# this way also removes case-mismatched dups, keeping old_tags version.
|
||||
foldedcase_tags = dict()
|
||||
for t in list(mi.tags) + list(old_tags):
|
||||
foldedcase_tags[t.lower()] = t
|
||||
|
||||
mi.tags = foldedcase_tags.values()
|
||||
#print("mi.tags:%s"%mi.tags)
|
||||
|
||||
if book['all_metadata']['langcode']:
|
||||
mi.languages=[book['all_metadata']['langcode']]
|
||||
@@ -1338,6 +1440,8 @@ class FanFictionDownLoaderPlugin(InterfaceAction):
|
||||
pass
|
||||
|
||||
db.set_metadata(book_id,mi)
|
||||
# mi.authors gets run through the string_to_authors and split on '&' ',' 'and' and 'with'
|
||||
db.set_authors(book_id,book['author']) # author is a list.
|
||||
|
||||
# do configured column updates here.
|
||||
#print("all_metadata: %s"%book['all_metadata'])
|
||||
@@ -1362,7 +1466,7 @@ class FanFictionDownLoaderPlugin(InterfaceAction):
|
||||
continue
|
||||
label = coldef['label']
|
||||
if coldef['datatype'] in ('enumeration','text','comments','datetime','series'):
|
||||
db.set_custom(book_id, book['all_metadata'][meta], label=label, commit=False)
|
||||
db.set_custom(book_id, book['all_metadata'][meta], label, commit=False)
|
||||
elif coldef['datatype'] in ('int','float'):
|
||||
num = unicode(book['all_metadata'][meta]).replace(",","")
|
||||
db.set_custom(book_id, num, label=label, commit=False)
|
||||
@@ -1385,14 +1489,11 @@ class FanFictionDownLoaderPlugin(InterfaceAction):
|
||||
if "," in custcol:
|
||||
(custcol,flag) = map( lambda x: x.strip(), custcol.split(",") )
|
||||
|
||||
print("meta:(%s) => custcol:(%s), flag(%s) "%(meta,custcol,flag))
|
||||
|
||||
if meta not in book['all_metadata']:
|
||||
print("No value for %s, skipping custom column(%s) update."%(meta,custcol))
|
||||
continue
|
||||
|
||||
if custcol not in custom_columns:
|
||||
print("No custom column(%s), skipping."%(custcol))
|
||||
continue
|
||||
else:
|
||||
coldef = custom_columns[custcol]
|
||||
@@ -1429,12 +1530,26 @@ class FanFictionDownLoaderPlugin(InterfaceAction):
|
||||
# Moved down so author's already in the DB.
|
||||
if 'authorUrl' in book['all_metadata']:
|
||||
authurls = book['all_metadata']['authorUrl'].split(", ")
|
||||
for i, auth in enumerate(book['author']):
|
||||
#print("===Update author url for %s to %s"%(auth,authurls[i]))
|
||||
autid=db.get_author_id(auth)
|
||||
db.set_link_field_for_author(autid, unicode(authurls[i]),
|
||||
commit=False, notify=False)
|
||||
authorlist = [ a.replace('&',';') for a in book['author'] ]
|
||||
if hasattr(db, 'new_api'): # new_api starts in calibre 1.0.0
|
||||
authorids = db.new_api.get_item_ids('authors',authorlist)
|
||||
authordata = db.new_api.author_data(authorids.values())
|
||||
# print("\n\nauthorids:%s"%authorids)
|
||||
# print("authordata:%s"%authordata)
|
||||
|
||||
author_id_to_link_map = dict()
|
||||
for i, author in enumerate(authorlist):
|
||||
author_id_to_link_map[authorids[author]] = authurls[i]
|
||||
|
||||
# print("author_id_to_link_map:%s\n\n"%author_id_to_link_map)
|
||||
db.new_api.set_link_for_authors(author_id_to_link_map)
|
||||
else:
|
||||
# keep for pre-calibre 1.0.0
|
||||
for i, auth in enumerate(authorlist):
|
||||
#print("===Update author url for %s to %s"%(auth,authurls[i]))
|
||||
autid=db.get_author_id(auth)
|
||||
db.set_link_field_for_author(autid, unicode(authurls[i]),
|
||||
commit=False, notify=False)
|
||||
db.commit()
|
||||
|
||||
if 'Generate Cover' in self.gui.iactions and (book['added'] or not prefs['gcnewonly']):
|
||||
@@ -1534,6 +1649,14 @@ class FanFictionDownLoaderPlugin(InterfaceAction):
|
||||
|
||||
def make_mi_from_book(self,book):
|
||||
mi = MetaInformation(book['title'],book['author']) # author is a list.
|
||||
if prefs['suppressauthorsort']:
|
||||
# otherwise author names will have calibre's sort algs
|
||||
# applied automatically.
|
||||
mi.author_sort = ' & '.join(book['author'])
|
||||
if prefs['suppresstitlesort']:
|
||||
# otherwise titles will have calibre's sort algs applied
|
||||
# automatically.
|
||||
mi.title_sort = book['title']
|
||||
mi.set_identifiers({'url':book['url']})
|
||||
mi.publisher = book['publisher']
|
||||
mi.tags = book['tags']
|
||||
@@ -1780,7 +1903,7 @@ class FanFictionDownLoaderPlugin(InterfaceAction):
|
||||
book['title'] = series
|
||||
for sr in serieslist:
|
||||
if series != sr:
|
||||
book['title'] = deftitle;
|
||||
book['title'] = deftitle
|
||||
break
|
||||
|
||||
configuration = get_ffdl_config(book['url'],fileform)
|
||||
@@ -1819,3 +1942,17 @@ def split_text_to_urls(urls):
|
||||
def escapehtml(txt):
|
||||
return txt.replace("&","&").replace(">",">").replace("<","<")
|
||||
|
||||
def pretty_book(d, indent=0, spacer=' '):
|
||||
kindent = spacer * indent
|
||||
|
||||
# if isinstance(d, list):
|
||||
# return '\n'.join([(pretty_book(v, indent, spacer)) for v in d])
|
||||
|
||||
if isinstance(d, dict):
|
||||
for k in ('password','username'):
|
||||
if k in d and d[k]:
|
||||
d[k]='<was set, removed for security>'
|
||||
return '\n'.join(['%s%s:\n%s' % (kindent, k, pretty_book(v, indent + 1, spacer))
|
||||
for k, v in d.items()])
|
||||
return "%s%s"%(kindent, d)
|
||||
|
||||
|
||||
+22
-4
@@ -14,6 +14,7 @@ from StringIO import StringIO
|
||||
|
||||
from calibre.utils.ipc.server import Server
|
||||
from calibre.utils.ipc.job import ParallelJob
|
||||
from calibre.constants import numeric_version as calibre_version
|
||||
|
||||
from calibre_plugins.fanfictiondownloader_plugin.dialogs import (NotGoingToDownload,
|
||||
OVERWRITE, OVERWRITEALWAYS, UPDATE, UPDATEALWAYS, ADDNEW, SKIP, CALIBREONLY)
|
||||
@@ -49,7 +50,7 @@ def do_download_worker(book_list, options,
|
||||
args = ['calibre_plugins.fanfictiondownloader_plugin.jobs',
|
||||
'do_download_for_worker',
|
||||
(book,options)]
|
||||
job = ParallelJob('arbitrary',
|
||||
job = ParallelJob('arbitrary_n',
|
||||
"url:(%s) id:(%s)"%(book['url'],book['calibre_id']),
|
||||
done=None,
|
||||
args=args)
|
||||
@@ -84,7 +85,7 @@ def do_download_worker(book_list, options,
|
||||
book_id = job._book['calibre_id']
|
||||
#title = job._title
|
||||
count = count + 1
|
||||
notification(float(count)/total, 'Downloaded Story')
|
||||
notification(float(count)/total, '%d of %d stories finished downloading'%(count,total))
|
||||
# Add this job's output to the current log
|
||||
print('Logfile for book ID %s (%s)'%(book_id, job._book['title']))
|
||||
print(job.details)
|
||||
@@ -106,7 +107,7 @@ def do_download_worker(book_list, options,
|
||||
# return the book list as the job result
|
||||
return book_list
|
||||
|
||||
def do_download_for_worker(book,options):
|
||||
def do_download_for_worker(book,options,notification=lambda x,y:x):
|
||||
'''
|
||||
Child job, to extract isbn from formats for this specific book,
|
||||
when run as a worker job
|
||||
@@ -206,6 +207,23 @@ def do_download_for_worker(book,options):
|
||||
book['comment'] = 'Update %s completed, added %s chapters for %s total.'%\
|
||||
(options['fileform'],(urlchaptercount-chaptercount),urlchaptercount)
|
||||
|
||||
if options['smarten_punctuation'] and options['fileform'] == "epub" \
|
||||
and calibre_version >= (0, 9, 39):
|
||||
# do smarten_punctuation from calibre's polish feature
|
||||
from calibre.ebooks.oeb.polish.main import polish, ALL_OPTS
|
||||
from calibre.utils.logging import Log
|
||||
from collections import namedtuple
|
||||
|
||||
data = {'smarten_punctuation':True}
|
||||
opts = ALL_OPTS.copy()
|
||||
opts.update(data)
|
||||
O = namedtuple('Options', ' '.join(ALL_OPTS.iterkeys()))
|
||||
opts = O(**opts)
|
||||
|
||||
log = Log(level=Log.DEBUG)
|
||||
# report = []
|
||||
polish({outfile:outfile}, opts, log, print) # report.append
|
||||
|
||||
except NotGoingToDownload as d:
|
||||
book['good']=False
|
||||
book['comment']=unicode(d)
|
||||
@@ -218,6 +236,6 @@ def do_download_for_worker(book,options):
|
||||
book['status'] = 'Error'
|
||||
print("Exception: %s:%s"%(book,unicode(e)))
|
||||
traceback.print_exc()
|
||||
|
||||
|
||||
#time.sleep(10)
|
||||
return book
|
||||
|
||||
@@ -30,6 +30,8 @@ default_prefs['updatemeta'] = True
|
||||
default_prefs['updatecover'] = False
|
||||
default_prefs['updateepubcover'] = False
|
||||
default_prefs['keeptags'] = False
|
||||
default_prefs['suppressauthorsort'] = False
|
||||
default_prefs['suppresstitlesort'] = False
|
||||
default_prefs['showmarked'] = False
|
||||
default_prefs['urlsfromclip'] = True
|
||||
default_prefs['updatedefault'] = True
|
||||
@@ -40,7 +42,9 @@ default_prefs['adddialogstaysontop'] = False
|
||||
default_prefs['includeimages'] = False
|
||||
default_prefs['lookforurlinhtml'] = False
|
||||
default_prefs['checkforseriesurlid'] = True
|
||||
default_prefs['checkforurlchange'] = True
|
||||
default_prefs['injectseries'] = False
|
||||
default_prefs['smarten_punctuation'] = False
|
||||
|
||||
default_prefs['send_lists'] = ''
|
||||
default_prefs['read_lists'] = ''
|
||||
|
||||
+57
-6
@@ -16,7 +16,22 @@
|
||||
[defaults]
|
||||
|
||||
## [defaults] section applies to all formats and sites but may be
|
||||
## overridden at several levels
|
||||
## overridden at several levels. Example:
|
||||
|
||||
## [defaults]
|
||||
## titlepage_entries: category,genre, status
|
||||
## [www.whofic.com]
|
||||
## # overrides defaults.
|
||||
## titlepage_entries: category,genre, status,dateUpdated,rating
|
||||
## [epub]
|
||||
## # overrides defaults & site section
|
||||
## titlepage_entries: category,genre, status,datePublished,dateUpdated,dateCreated
|
||||
## [www.whofic.com:epub]
|
||||
## # overrides defaults, site section & format section
|
||||
## titlepage_entries: category,genre, status,datePublished
|
||||
## [overrides]
|
||||
## # overrides all other sections
|
||||
## titlepage_entries: category
|
||||
|
||||
## Some sites also require the user to confirm they are adult for
|
||||
## adult content. Uncomment by removing '#' in front of is_adult.
|
||||
@@ -133,6 +148,9 @@ zip_filename: ${title}-${siteabbrev}_${storyId}${formatext}.zip
|
||||
## zip_filename.
|
||||
allow_unsafe_filename: false
|
||||
|
||||
## The regex pattern of 'unsafe' filename chars for above.
|
||||
#output_filename_safepattern:[^a-zA-Z0-9_\. \[\]\(\)&'-]+
|
||||
|
||||
## entries to make epub subjects and calibre tags
|
||||
## lastupdate creates two tags: "Last Update Year/Month: %Y/%m" and "Last Update: %Y/%m/%d"
|
||||
include_subject_tags: extratags, genre, category, characters, ships, lastupdate, status
|
||||
@@ -149,6 +167,9 @@ extratags: FanFiction
|
||||
#extraships:
|
||||
#extrawarnings:
|
||||
|
||||
## Add this to genre if there's more than one category.
|
||||
#add_genre_when_multi_category: Crossover
|
||||
|
||||
## number of seconds to sleep between calls to the story site. May by
|
||||
## useful if pulling large numbers of stories or if the site is slow.
|
||||
#slow_down_sleep_time:0.5
|
||||
@@ -171,6 +192,11 @@ extratags: FanFiction
|
||||
## Note that if metakey == conditionalkey the conditional is ignored.
|
||||
## You can use \s in the replacement to add explicit spaces. (The config parser
|
||||
## tends to discard trailing spaces.)
|
||||
## replace_metadata <entry>_LIST options: FFDL replace_metadata lines
|
||||
## operate on individual list items for list entries. But if you
|
||||
## want to do a replacement on the joined string for the whole list,
|
||||
## you can by using <entry>_LIST. Example, if you added
|
||||
## calibre_author: calibre_author_LIST=>^(.{,100}).*$=>\1
|
||||
#replace_metadata:
|
||||
# genre,category=>Sci-Fi=>SF
|
||||
# Puella Magi Madoka Magica.* => Madoka
|
||||
@@ -233,6 +259,24 @@ chapter_title_strip_pattern:^[0-9]+[\.: -]+
|
||||
## "The Beginning" => "1. The Beginning"
|
||||
chapter_title_add_pattern:${index}. ${title}
|
||||
|
||||
## Reorder ships so b/a and c/b/a become a/b and a/b/c. Only separates
|
||||
## on '/', so use replace_metadata to change separator first if
|
||||
## needed. Something like: ships=>[ ]*(/|&|&)[ ]*=>/ You can use
|
||||
## ships_LIST to change the / back to something else if you want.
|
||||
sort_ships:false
|
||||
|
||||
## join_string_<entry> options -- FFDL list entries are comma
|
||||
## separated by default. You can use this to change that. For example,
|
||||
## if you want authors separated with ' & ' instead, use
|
||||
## join_string_calibre_author:\s&\s. (\s == space)
|
||||
#join_string_author:,\s
|
||||
|
||||
## keep_in_order_<entry> options: FFDL sorts list entries by default
|
||||
## (except for author/authorUrl/authorId). But if you want to use an
|
||||
## extra entry derived from author, it ends up sorted. For example, if
|
||||
## you added calibre_author: keep_in_order_calibre_author:true
|
||||
#keep_in_order_author:true
|
||||
|
||||
|
||||
## Each output format has a section that overrides [defaults]
|
||||
[html]
|
||||
@@ -421,8 +465,8 @@ nook_img_fix:true
|
||||
## mobi TOC cannot be turned off right now.
|
||||
#include_tocpage: true
|
||||
|
||||
## Each site has a section that overrides [defaults] *and* the format
|
||||
## sections test1.com specifically is not a real story site. Instead,
|
||||
## Each site has a section that overrides [defaults].
|
||||
## test1.com specifically is not a real story site. Instead,
|
||||
## it is a fake site for testing configuration and output. It uses
|
||||
## URLs like: http://test1.com?sid=12345
|
||||
[test1.com]
|
||||
@@ -479,7 +523,8 @@ extratags: FanFiction,Testing,HTML
|
||||
#is_adult:true
|
||||
|
||||
## AO3 adapter defines a few extra metadata entries.
|
||||
extra_valid_entries:fandoms,freeformtags,freefromtags,ao3categories,comments,kudos,hits,bookmarks,collections
|
||||
## If there's ever more than 4 series, add series04,series04Url etc.
|
||||
extra_valid_entries:fandoms,freeformtags,freefromtags,ao3categories,comments,kudos,hits,bookmarks,collections,series00,series01,series02,series03,series00Url,series01Url,series02Url,series03Url
|
||||
fandoms_label:Fandoms
|
||||
freeformtags_label:Freeform Tags
|
||||
freefromtags_label:Freeform Tags
|
||||
@@ -495,7 +540,7 @@ bookmarks_label:Bookmarks
|
||||
include_in_freefromtags:freeformtags
|
||||
|
||||
## adds to titlepage_entries instead of replacing it.
|
||||
#extra_titlepage_entries: fandoms,freeformtags,ao3categories,comments,kudos,hits,bookmarks
|
||||
#extra_titlepage_entries: fandoms,freeformtags,ao3categories,comments,kudos,hits,bookmarks,series00,series01,series02,series03,series00Url,series01Url,series02Url,series03Url
|
||||
|
||||
## adds to include_subject_tags instead of replacing it.
|
||||
#extra_subject_tags:fandoms,freeformtags,ao3categories
|
||||
@@ -1329,6 +1374,11 @@ titlepage_entries: series,seriesUrl,category,genre,language,status,datePublished
|
||||
## Site dedicated to these categories/characters/ships
|
||||
extracategories:Lord of the Rings
|
||||
|
||||
## Some sites do not require a login, but do require the user to
|
||||
## confirm they are adult for adult content. In commandline version,
|
||||
## this should go in your personal.ini, not defaults.ini.
|
||||
#is_adult:true
|
||||
|
||||
[www.thepetulantpoetess.com]
|
||||
## Some sites require login (or login for some rated stories) The
|
||||
## program can prompt you, or you can save it in config. In
|
||||
@@ -1450,7 +1500,8 @@ extracategories:Stargate: Atlantis
|
||||
[teststory:defaults]
|
||||
valid_entries:title,author_list,authorId_list,authorUrl_list,storyUrl,
|
||||
datePublished,dateUpdated,numWords,status,language,series,seriesUrl,
|
||||
rating,category_list,genre_list,warnings_list,characters_list
|
||||
rating,category_list,genre_list,warnings_list,characters_list,ships_list,
|
||||
description,site,extratags
|
||||
|
||||
# {{storyId}} is a special case--it's the only one that works.
|
||||
title:Test Story Title {{storyId}}
|
||||
|
||||
+54
-15
@@ -105,6 +105,9 @@ def main(argv,
|
||||
parser.add_option("-n", "--normalize-list",
|
||||
action="store_true", dest="normalize",default=False,
|
||||
help="Get list of valid story URLs from page given, but normalized to standard forms.",)
|
||||
parser.add_option("-s", "--sites-list",
|
||||
action="store_true", dest="siteslist",default=False,
|
||||
help="Get list of valid story URLs examples.",)
|
||||
parser.add_option("-d", "--debug",
|
||||
action="store_true", dest="debug",
|
||||
help="Show debug output while downloading.",)
|
||||
@@ -115,21 +118,45 @@ def main(argv,
|
||||
logger = logging.getLogger("fanficdownloader")
|
||||
logger.setLevel(logging.INFO)
|
||||
|
||||
if len(args) != 1:
|
||||
if not options.siteslist and len(args) != 1:
|
||||
parser.error("incorrect number of arguments")
|
||||
|
||||
if options.siteslist:
|
||||
for (site,examples) in adapters.getSiteExamples():
|
||||
print("\n====%s====\n\nExample URLs:"%site)
|
||||
for u in examples:
|
||||
print(" * %s"%u)
|
||||
return
|
||||
|
||||
if options.update and options.format != 'epub':
|
||||
parser.error("-u/--update-epub only works with epub")
|
||||
|
||||
## Attempt to update an existing epub.
|
||||
chaptercount = None
|
||||
output_filename = None
|
||||
if options.update:
|
||||
(url,chaptercount) = get_dcsource_chaptercount(args[0])
|
||||
print "Updating %s, URL: %s" % (args[0],url)
|
||||
output_filename = args[0]
|
||||
try:
|
||||
(url,chaptercount) = get_dcsource_chaptercount(args[0])
|
||||
if not url:
|
||||
print "No story URL found in epub to update."
|
||||
return
|
||||
print "Updating %s, URL: %s" % (args[0],url)
|
||||
output_filename = args[0]
|
||||
except:
|
||||
# if there's an error reading the update file, maybe it's a URL?
|
||||
# we'll look for an existing outputfile down below.
|
||||
url = args[0]
|
||||
else:
|
||||
url = args[0]
|
||||
|
||||
configuration = Configuration(adapters.getConfigSectionFor(url),options.format)
|
||||
|
||||
try:
|
||||
configuration = Configuration(adapters.getConfigSectionFor(url),options.format)
|
||||
except exceptions.UnknownSite, e:
|
||||
if options.list or options.normalize:
|
||||
# list for page doesn't have to be a supported site.
|
||||
configuration = Configuration("test1.com",options.format)
|
||||
else:
|
||||
raise e
|
||||
|
||||
conflist = []
|
||||
homepath = join(expanduser("~"),".fanficdownloader")
|
||||
@@ -164,8 +191,8 @@ def main(argv,
|
||||
if options.force:
|
||||
configuration.set("overrides","always_overwrite","true")
|
||||
|
||||
if options.update:
|
||||
configuration.set("overrides","output_filename",args[0])
|
||||
if options.update and chaptercount:
|
||||
configuration.set("overrides","output_filename",output_filename)
|
||||
|
||||
if options.update and not options.updatecover:
|
||||
configuration.set("overrides","never_make_cover","true")
|
||||
@@ -182,14 +209,24 @@ def main(argv,
|
||||
|
||||
if options.list or options.normalize:
|
||||
retlist = get_urls_from_page(args[0], configuration, normalize=options.normalize)
|
||||
print "\n".join(retlist)
|
||||
|
||||
print "\n".join(retlist)
|
||||
return
|
||||
|
||||
try:
|
||||
adapter = adapters.getAdapter(configuration,url)
|
||||
adapter.setChaptersRange(options.begin,options.end)
|
||||
|
||||
|
||||
# check for updating from URL (vs from file)
|
||||
if options.update and not chaptercount:
|
||||
try:
|
||||
writer = writers.getWriter("epub",configuration,adapter)
|
||||
output_filename=writer.getOutputFileName()
|
||||
(noturl,chaptercount) = get_dcsource_chaptercount(output_filename)
|
||||
print "Updating %s, URL: %s" % (output_filename,url)
|
||||
except:
|
||||
options.update = False
|
||||
pass
|
||||
|
||||
## Check for include_images and absence of PIL, give warning.
|
||||
if adapter.getConfig('include_images'):
|
||||
try:
|
||||
@@ -225,11 +262,13 @@ def main(argv,
|
||||
|
||||
if options.update and not options.force:
|
||||
urlchaptercount = int(adapter.getStoryMetadataOnly().getMetadata('numChapters'))
|
||||
|
||||
|
||||
if chaptercount == urlchaptercount and not options.metaonly:
|
||||
print "%s already contains %d chapters." % (args[0],chaptercount)
|
||||
print "%s already contains %d chapters." % (output_filename,chaptercount)
|
||||
elif chaptercount > urlchaptercount:
|
||||
print "%s contains %d chapters, more than source: %d." % (args[0],chaptercount,urlchaptercount)
|
||||
print "%s contains %d chapters, more than source: %d." % (output_filename,chaptercount,urlchaptercount)
|
||||
elif chaptercount == 0:
|
||||
print "%s doesn't contain any recognizable chapters, probably from a different source. Not updating." % (output_filename)
|
||||
else:
|
||||
print "Do update - epub(%d) vs url(%d)" % (chaptercount, urlchaptercount)
|
||||
if not options.metaonly:
|
||||
@@ -243,7 +282,7 @@ def main(argv,
|
||||
adapter.oldimgs,
|
||||
adapter.oldcover,
|
||||
adapter.calibrebookmark,
|
||||
adapter.logfile) = get_update_data(args[0])
|
||||
adapter.logfile) = get_update_data(output_filename)
|
||||
|
||||
writeStory(configuration,adapter,"epub")
|
||||
|
||||
|
||||
@@ -126,6 +126,7 @@ import adapter_scarheadnet
|
||||
|
||||
## List of registered site adapters.
|
||||
__class_list = []
|
||||
__domain_map = {}
|
||||
|
||||
def imports():
|
||||
for name, val in globals().items():
|
||||
@@ -135,7 +136,10 @@ def imports():
|
||||
for x in imports():
|
||||
if "fanficdownloader.adapters.adapter_" in x:
|
||||
#print x
|
||||
__class_list.append(sys.modules[x].getClass())
|
||||
cls = sys.modules[x].getClass()
|
||||
__class_list.append(cls)
|
||||
for site in cls.getAcceptDomains():
|
||||
__domain_map[site]=cls
|
||||
|
||||
def getNormalStoryURL(url):
|
||||
if not getNormalStoryURL.__dummyconfig:
|
||||
@@ -153,12 +157,14 @@ def getNormalStoryURL(url):
|
||||
# kludgey function static/singleton
|
||||
getNormalStoryURL.__dummyconfig = None
|
||||
|
||||
def getAdapter(config,url):
|
||||
def getAdapter(config,url,anyurl=False):
|
||||
|
||||
#logger.debug("trying url:"+url)
|
||||
(cls,fixedurl) = getClassFor(url)
|
||||
#logger.debug("fixedurl:"+fixedurl)
|
||||
if cls:
|
||||
if anyurl:
|
||||
fixedurl = cls.getSiteExampleURLs().split()[0]
|
||||
adapter = cls(config,fixedurl) # raises InvalidStoryURL
|
||||
return adapter
|
||||
# No adapter found.
|
||||
@@ -167,6 +173,12 @@ def getAdapter(config,url):
|
||||
def getConfigSections():
|
||||
return [cls.getConfigSection() for cls in __class_list]
|
||||
|
||||
def getSiteExamples():
|
||||
l=[]
|
||||
for cls in sorted(__class_list, key=lambda x : x.getConfigSection()):
|
||||
l.append((cls.getConfigSection(),cls.getSiteExampleURLs().split()))
|
||||
return l
|
||||
|
||||
def getConfigSectionFor(url):
|
||||
(cls,fixedurl) = getClassFor(url)
|
||||
if cls:
|
||||
@@ -198,12 +210,14 @@ def getClassFor(url):
|
||||
#logger.debug("trying site:www."+domain)
|
||||
cls = getClassFromList("www."+domain)
|
||||
fixedurl = fixedurl.replace("http://","http://www.")
|
||||
|
||||
fixedurl = cls.stripURLParameters(fixedurl)
|
||||
|
||||
if cls:
|
||||
fixedurl = cls.stripURLParameters(fixedurl)
|
||||
|
||||
return (cls,fixedurl)
|
||||
|
||||
def getClassFromList(domain):
|
||||
for cls in __class_list:
|
||||
if cls.matchesSite(domain):
|
||||
return cls
|
||||
try:
|
||||
return __domain_map[domain]
|
||||
except KeyError:
|
||||
pass # return none.
|
||||
|
||||
@@ -42,7 +42,7 @@ class AdAstraFanficComSiteAdapter(BaseSiteAdapter):
|
||||
|
||||
# get storyId from url--url validation guarantees query is only sid=1234
|
||||
self.story.setMetadata('storyId',self.parsedUrl.query.split('=',)[1])
|
||||
logger.debug("storyId: (%s)"%self.story.getMetadata('storyId'))
|
||||
|
||||
|
||||
# normalized story URL.
|
||||
self._setURL('http://' + self.getSiteDomain() + '/viewstory.php?sid='+self.story.getMetadata('storyId'))
|
||||
@@ -52,6 +52,7 @@ class AdAstraFanficComSiteAdapter(BaseSiteAdapter):
|
||||
def getSiteDomain():
|
||||
return 'www.adastrafanfic.com'
|
||||
|
||||
@classmethod
|
||||
def getSiteExampleURLs(self):
|
||||
return "http://"+self.getSiteDomain()+"/viewstory.php?sid=1234"
|
||||
|
||||
@@ -89,7 +90,7 @@ class AdAstraFanficComSiteAdapter(BaseSiteAdapter):
|
||||
|
||||
## Title
|
||||
a = soup.find('a', href=re.compile(r'viewstory.php\?sid='+self.story.getMetadata('storyId')+"$"))
|
||||
self.story.setMetadata('title',a.string)
|
||||
self.story.setMetadata('title',stripHTML(a))
|
||||
|
||||
# Find authorid and URL from... author url.
|
||||
a = soup.find('a', href=re.compile(r"viewuser.php"))
|
||||
|
||||
@@ -51,13 +51,13 @@ class ArchiveOfOurOwnOrgAdapter(BaseSiteAdapter):
|
||||
|
||||
# get storyId from url--url validation guarantees query is only sid=1234
|
||||
self.story.setMetadata('storyId',self.parsedUrl.path.split('/',)[2])
|
||||
logger.debug("storyId: (%s)"%self.story.getMetadata('storyId'))
|
||||
|
||||
|
||||
# get storyId from url--url validation guarantees query correct
|
||||
m = re.match(self.getSiteURLPattern(),url)
|
||||
if m:
|
||||
self.story.setMetadata('storyId',m.group('id'))
|
||||
logger.debug("storyId: (%s)"%self.story.getMetadata('storyId'))
|
||||
|
||||
# normalized story URL.
|
||||
self._setURL('http://' + self.getSiteDomain() + '/works/'+self.story.getMetadata('storyId'))
|
||||
else:
|
||||
@@ -77,8 +77,9 @@ class ArchiveOfOurOwnOrgAdapter(BaseSiteAdapter):
|
||||
# The site domain. Does have www here, if it uses it.
|
||||
return 'archiveofourown.org'
|
||||
|
||||
@classmethod
|
||||
def getSiteExampleURLs(self):
|
||||
return "http://"+self.getSiteDomain()+"/works/123456 http://"+self.getSiteDomain()+"/collections/Some_Archive/works/123456"
|
||||
return "http://"+self.getSiteDomain()+"/works/123456 http://"+self.getSiteDomain()+"/collections/Some_Archive/works/123456 http://"+self.getSiteDomain()+"/works/123456/chapters/78901"
|
||||
|
||||
def getSiteURLPattern(self):
|
||||
# http://archiveofourown.org/collections/Smallville_Slash_Archive/works/159770
|
||||
@@ -162,7 +163,7 @@ class ArchiveOfOurOwnOrgAdapter(BaseSiteAdapter):
|
||||
|
||||
## Title
|
||||
a = soup.find('a', href=re.compile(r"^/works/\d+$"))
|
||||
self.story.setMetadata('title',a.string)
|
||||
self.story.setMetadata('title',stripHTML(a))
|
||||
|
||||
# Find authorid and URL from... author url.
|
||||
alist = soup.findAll('a', href=re.compile(r"^/users/\w+/pseuds/\w+"))
|
||||
@@ -209,10 +210,7 @@ class ArchiveOfOurOwnOrgAdapter(BaseSiteAdapter):
|
||||
if a != None:
|
||||
warnings = a.findAll('a',{'class':"tag"})
|
||||
for warning in warnings:
|
||||
if warning.string == "Author Chose Not To Use Archive Warnings":
|
||||
warning.string = "No Archive Warnings Apply"
|
||||
if warning.string != "No Archive Warnings Apply":
|
||||
self.story.addToList('warnings',warning.string)
|
||||
self.story.addToList('warnings',warning.string)
|
||||
|
||||
a = metasoup.find('dd',{'class':"freeform tags"})
|
||||
if a != None:
|
||||
@@ -287,19 +285,19 @@ class ArchiveOfOurOwnOrgAdapter(BaseSiteAdapter):
|
||||
self.story.setMetadata('dateUpdated', makeDate(stripHTML(value), self.dateformat))
|
||||
|
||||
|
||||
try:
|
||||
# Find Series name from series URL.
|
||||
a = metasoup.find('dd',{'class':"series"})
|
||||
b = a.find('a', href=re.compile(r"/series/\d+"))
|
||||
series_name = b.string
|
||||
series_url = 'http://'+self.host+b['href']
|
||||
series_index = int(a.text.split(' ')[1])
|
||||
self.setSeries(series_name, series_index)
|
||||
self.story.setMetadata('seriesUrl',series_url)
|
||||
|
||||
except:
|
||||
# I find it hard to care if the series parsing fails
|
||||
pass
|
||||
# Find Series name from series URL.
|
||||
ddseries = metasoup.find('dd',{'class':"series"})
|
||||
|
||||
if ddseries:
|
||||
for i, a in enumerate(ddseries.findAll('a', href=re.compile(r"/series/\d+"))):
|
||||
series_name = stripHTML(a)
|
||||
series_url = 'http://'+self.host+a['href']
|
||||
series_index = int(stripHTML(a.previousSibling).replace(', ','').split(' ')[1]) # "Part # of" or ", Part #"
|
||||
self.story.setMetadata('series%02d'%i,"%s [%s]"%(series_name,series_index))
|
||||
self.story.setMetadata('series%02dUrl'%i,series_url)
|
||||
if i == 0:
|
||||
self.setSeries(series_name, series_index)
|
||||
self.story.setMetadata('seriesUrl',series_url)
|
||||
|
||||
# grab the text for an individual chapter.
|
||||
def getChapterText(self, url):
|
||||
|
||||
@@ -49,7 +49,7 @@ class ArchiveSkyeHawkeComAdapter(BaseSiteAdapter):
|
||||
|
||||
# get storyId from url--url validation guarantees query is only sid=1234
|
||||
self.story.setMetadata('storyId',self.parsedUrl.query.split('=',)[1])
|
||||
logger.debug("storyId: (%s)"%self.story.getMetadata('storyId'))
|
||||
|
||||
|
||||
# normalized story URL.
|
||||
self._setURL('http://' + self.getSiteDomain() + '/story.php?no='+self.story.getMetadata('storyId'))
|
||||
@@ -70,6 +70,7 @@ class ArchiveSkyeHawkeComAdapter(BaseSiteAdapter):
|
||||
def getAcceptDomains(cls):
|
||||
return ['archive.skyehawke.com','www.skyehawke.com']
|
||||
|
||||
@classmethod
|
||||
def getSiteExampleURLs(self):
|
||||
return "http://archive.skyehawke.com/story.php?no=1234 http://www.skyehawke.com/archive/story.php?no=1234 http://skyehawke.com/archive/story.php?no=1234"
|
||||
|
||||
@@ -100,7 +101,7 @@ class ArchiveSkyeHawkeComAdapter(BaseSiteAdapter):
|
||||
|
||||
## Title
|
||||
a = soup.find('div', {'class':"story border"}).find('span',{'class':'left'})
|
||||
title=a.text.split('"')[1]
|
||||
title=stripHTML(a).split('"')[1]
|
||||
self.story.setMetadata('title',title)
|
||||
|
||||
# Find authorid and URL from... author url.
|
||||
|
||||
@@ -48,7 +48,7 @@ class AshwinderSycophantHexComAdapter(BaseSiteAdapter):
|
||||
|
||||
# get storyId from url--url validation guarantees query is only sid=1234
|
||||
self.story.setMetadata('storyId',self.parsedUrl.query.split('=',)[1])
|
||||
logger.debug("storyId: (%s)"%self.story.getMetadata('storyId'))
|
||||
|
||||
|
||||
|
||||
# normalized story URL.
|
||||
@@ -66,6 +66,7 @@ class AshwinderSycophantHexComAdapter(BaseSiteAdapter):
|
||||
# The site domain. Does have www here, if it uses it.
|
||||
return 'ashwinder.sycophanthex.com'
|
||||
|
||||
@classmethod
|
||||
def getSiteExampleURLs(self):
|
||||
return "http://"+self.getSiteDomain()+"/viewstory.php?sid=1234"
|
||||
|
||||
@@ -156,7 +157,7 @@ class AshwinderSycophantHexComAdapter(BaseSiteAdapter):
|
||||
for info in asoup.findAll('table', {'width' : '100%', 'bordercolor' : re.compile(r'#')}):
|
||||
a = info.find('a', href=re.compile(r'viewstory.php\?sid='+self.story.getMetadata('storyId')+"$"))
|
||||
if a != None:
|
||||
self.story.setMetadata('title',a.string)
|
||||
self.story.setMetadata('title',stripHTML(a))
|
||||
break
|
||||
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ class Asr3SlashzoneOrgAdapter(BaseSiteAdapter):
|
||||
|
||||
# get storyId from url--url validation guarantees query is only sid=1234
|
||||
self.story.setMetadata('storyId',self.parsedUrl.query.split('=',)[1])
|
||||
logger.debug("storyId: (%s)"%self.story.getMetadata('storyId'))
|
||||
|
||||
|
||||
# normalized story URL.
|
||||
self._setURL('http://' + self.getSiteDomain() + '/archive/viewstory.php?sid='+self.story.getMetadata('storyId'))
|
||||
@@ -63,6 +63,7 @@ class Asr3SlashzoneOrgAdapter(BaseSiteAdapter):
|
||||
# The site domain. Does have www here, if it uses it.
|
||||
return 'asr3.slashzone.org'
|
||||
|
||||
@classmethod
|
||||
def getSiteExampleURLs(self):
|
||||
return "http://"+self.getSiteDomain()+"/archive/viewstory.php?sid=1234"
|
||||
|
||||
@@ -127,7 +128,7 @@ class Asr3SlashzoneOrgAdapter(BaseSiteAdapter):
|
||||
|
||||
## Title
|
||||
a = soup.find('a', href=re.compile(r'viewstory.php\?sid='+self.story.getMetadata('storyId')+"$"))
|
||||
self.story.setMetadata('title',a.string)
|
||||
self.story.setMetadata('title',stripHTML(a))
|
||||
|
||||
# Find authorid and URL from... author url.
|
||||
a = soup.find('a', href=re.compile(r"viewuser.php\?uid=\d+"))
|
||||
|
||||
@@ -70,7 +70,7 @@ class BloodTiesFansComAdapter(BaseSiteAdapter): # XXX
|
||||
|
||||
# get storyId from url--url validation guarantees query is only sid=1234
|
||||
self.story.setMetadata('storyId',self.parsedUrl.query.split('=',)[1])
|
||||
logger.debug("storyId: (%s)"%self.story.getMetadata('storyId'))
|
||||
|
||||
|
||||
# normalized story URL.
|
||||
# XXX Most sites don't have the /fanfic part. Replace all to remove it usually.
|
||||
@@ -88,6 +88,7 @@ class BloodTiesFansComAdapter(BaseSiteAdapter): # XXX
|
||||
# The site domain. Does have www here, if it uses it.
|
||||
return 'bloodties-fans.com' # XXX
|
||||
|
||||
@classmethod
|
||||
def getSiteExampleURLs(self):
|
||||
return "http://"+self.getSiteDomain()+"/fiction/viewstory.php?sid=1234"
|
||||
|
||||
@@ -206,7 +207,7 @@ class BloodTiesFansComAdapter(BaseSiteAdapter): # XXX
|
||||
|
||||
## Title
|
||||
a = soup.find('a', href=re.compile(r'viewstory.php\?sid='+self.story.getMetadata('storyId')+"$"))
|
||||
self.story.setMetadata('title',a.string)
|
||||
self.story.setMetadata('title',stripHTML(a))
|
||||
|
||||
# Find authorid and URL from... author url.
|
||||
a = soup.find('a', href=re.compile(r"viewuser.php\?uid=\d+"))
|
||||
|
||||
@@ -58,7 +58,7 @@ class BuffyNFaithNetAdapter(BaseSiteAdapter):
|
||||
m = re.match(self.getSiteURLPattern(),url)
|
||||
if m:
|
||||
self.story.setMetadata('storyId',m.group('id'))
|
||||
logger.debug("storyId: (%s)"%self.story.getMetadata('storyId'))
|
||||
|
||||
# normalized story URL. gets rid of chapter if there, left with ch 1 URL on this site
|
||||
nurl = "http://"+self.getSiteDomain()+"/fanfictions/index.php?act=vie&id="+self.story.getMetadata('storyId')
|
||||
self._setURL(nurl)
|
||||
@@ -69,7 +69,7 @@ class BuffyNFaithNetAdapter(BaseSiteAdapter):
|
||||
raise exceptions.InvalidStoryURL(url,
|
||||
self.getSiteDomain(),
|
||||
self.getSiteExampleURLs())
|
||||
logger.debug("storyId: (%s)"%self.story.getMetadata('storyId'))
|
||||
|
||||
|
||||
# Each adapter needs to have a unique site abbreviation.
|
||||
self.story.setMetadata('siteabbrev','bnfnet')
|
||||
@@ -89,8 +89,9 @@ class BuffyNFaithNetAdapter(BaseSiteAdapter):
|
||||
"buffynfaith.net wants a Referer for images. Used both above and below(after cookieproc added)"
|
||||
self.opener.addheaders = [('Referer', 'http://'+self.getSiteDomain()+'/')]
|
||||
|
||||
@classmethod
|
||||
def getSiteExampleURLs(self):
|
||||
return "http://buffynfaith.net/fanfictions/index.php?act=vie&id=963 http://buffynfaith.net/fanfictions/index.php?act=vie&id=949 http://buffynfaith.net/fanfictions/index.php?act=vie&id=949&ch=2"
|
||||
return "http://"+self.getSiteDomain()+"/fanfictions/index.php?act=vie&id=1234 http://buffynfaith.net/fanfictions/index.php?act=ovr&id=1234 http://buffynfaith.net/fanfictions/index.php?act=vie&id=1234&ch=2"
|
||||
|
||||
def getSiteURLPattern(self):
|
||||
#http://buffynfaith.net/fanfictions/index.php?act=vie&id=963
|
||||
|
||||
@@ -72,7 +72,7 @@ class CastleFansOrgAdapter(BaseSiteAdapter): # XXX
|
||||
|
||||
# get storyId from url--url validation guarantees query is only sid=1234
|
||||
self.story.setMetadata('storyId',self.parsedUrl.query.split('=',)[1])
|
||||
logger.debug("storyId: (%s)"%self.story.getMetadata('storyId'))
|
||||
|
||||
|
||||
# normalized story URL.
|
||||
# XXX Most sites don't have the /fanfic part. Replace all to remove it usually.
|
||||
@@ -90,6 +90,7 @@ class CastleFansOrgAdapter(BaseSiteAdapter): # XXX
|
||||
# The site domain. Does have www here, if it uses it.
|
||||
return 'castlefans.org' # XXX
|
||||
|
||||
@classmethod
|
||||
def getSiteExampleURLs(self):
|
||||
return "http://"+self.getSiteDomain()+"/fanfic/viewstory.php?sid=1234"
|
||||
|
||||
@@ -179,7 +180,7 @@ class CastleFansOrgAdapter(BaseSiteAdapter): # XXX
|
||||
pagetitle = soup.find('div',{'id':'pagetitle'})
|
||||
## Title
|
||||
a = pagetitle.find('a', href=re.compile(r'viewstory.php\?sid='+self.story.getMetadata('storyId')+"$"))
|
||||
self.story.setMetadata('title',a.string)
|
||||
self.story.setMetadata('title',stripHTML(a))
|
||||
|
||||
# Find authorid and URL from... author url.
|
||||
a = pagetitle.find('a', href=re.compile(r"viewuser.php\?uid=\d+"))
|
||||
|
||||
@@ -48,7 +48,7 @@ class ChaosSycophantHexComAdapter(BaseSiteAdapter):
|
||||
|
||||
# get storyId from url--url validation guarantees query is only sid=1234
|
||||
self.story.setMetadata('storyId',self.parsedUrl.query.split('=',)[1])
|
||||
logger.debug("storyId: (%s)"%self.story.getMetadata('storyId'))
|
||||
|
||||
|
||||
|
||||
# normalized story URL.
|
||||
@@ -66,6 +66,7 @@ class ChaosSycophantHexComAdapter(BaseSiteAdapter):
|
||||
# The site domain. Does have www here, if it uses it.
|
||||
return 'chaos.sycophanthex.com'
|
||||
|
||||
@classmethod
|
||||
def getSiteExampleURLs(self):
|
||||
return "http://"+self.getSiteDomain()+"/viewstory.php?sid=1234"
|
||||
|
||||
@@ -115,7 +116,7 @@ class ChaosSycophantHexComAdapter(BaseSiteAdapter):
|
||||
## Title
|
||||
pt = soup.find('div', {'id' : 'pagetitle'})
|
||||
a = pt.find('a', href=re.compile(r'viewstory.php\?sid='+self.story.getMetadata('storyId')+"$"))
|
||||
self.story.setMetadata('title',a.text)
|
||||
self.story.setMetadata('title',stripHTML(a))
|
||||
|
||||
# Find authorid and URL from... author url.
|
||||
a = pt.find('a', href=re.compile(r"viewuser.php\?uid=\d+"))
|
||||
|
||||
@@ -48,7 +48,7 @@ class CheckmatedComAdapter(BaseSiteAdapter):
|
||||
|
||||
# get storyId from url--url validation guarantees query is only sid=1234
|
||||
self.story.setMetadata('storyId',self.parsedUrl.query.split('=',)[1])
|
||||
logger.debug("storyId: (%s)"%self.story.getMetadata('storyId'))
|
||||
|
||||
|
||||
self._setURL('http://' + self.getSiteDomain() + '/story.php?story='+self.story.getMetadata('storyId'))
|
||||
|
||||
@@ -64,6 +64,7 @@ class CheckmatedComAdapter(BaseSiteAdapter):
|
||||
# The site domain. Does have www here, if it uses it.
|
||||
return 'www.checkmated.com'
|
||||
|
||||
@classmethod
|
||||
def getSiteExampleURLs(self):
|
||||
return "http://"+self.getSiteDomain()+"/story.php?story=1234"
|
||||
|
||||
@@ -142,11 +143,11 @@ class CheckmatedComAdapter(BaseSiteAdapter):
|
||||
# Now go hunting for all the meta data and the chapter list.
|
||||
|
||||
## Title
|
||||
a = soup.findAll('span', {'class' : 'storytitle'})
|
||||
self.story.setMetadata('title',a[0].string)
|
||||
a = soup.find('span', {'class' : 'storytitle'})
|
||||
self.story.setMetadata('title',stripHTML(a))
|
||||
|
||||
# Find authorid and URL from... author url.
|
||||
a = a[1].find('a', href=re.compile(r"authors.php\?name\=\w+"))
|
||||
a = a.parent.find('a', href=re.compile(r"authors.php\?name\=\w+"))
|
||||
self.story.setMetadata('authorId',a['href'].split('=')[1])
|
||||
self.story.setMetadata('authorUrl','http://'+self.host+'/'+a['href'])
|
||||
self.story.setMetadata('author',a.string)
|
||||
|
||||
@@ -48,7 +48,7 @@ class DarkSolaceOrgAdapter(BaseSiteAdapter):
|
||||
|
||||
# get storyId from url--url validation guarantees query is only sid=1234
|
||||
self.story.setMetadata('storyId',self.parsedUrl.query.split('=',)[1])
|
||||
logger.debug("storyId: (%s)"%self.story.getMetadata('storyId'))
|
||||
|
||||
|
||||
# normalized story URL.
|
||||
self._setURL('http://' + self.getSiteDomain() + '/elysian/viewstory.php?sid='+self.story.getMetadata('storyId'))
|
||||
@@ -69,6 +69,7 @@ class DarkSolaceOrgAdapter(BaseSiteAdapter):
|
||||
def getAcceptDomains(cls):
|
||||
return ['www.dark-solace.org','dark-solace.org']
|
||||
|
||||
@classmethod
|
||||
def getSiteExampleURLs(self):
|
||||
return "http://"+self.getSiteDomain()+"/elysian/viewstory.php?sid=1234"
|
||||
|
||||
@@ -183,31 +184,31 @@ class DarkSolaceOrgAdapter(BaseSiteAdapter):
|
||||
# first a tag in pagetitle is title
|
||||
self.story.setMetadata('title',stripHTML(div.find('a')))
|
||||
|
||||
# Find the chapters:
|
||||
# chapters=soup.find('select', {'name' : 'chapter'})
|
||||
# if chapters != None:
|
||||
# for chapter in chapters.findAll('option'):
|
||||
# self.chapterUrls.append((stripHTML(chapter),'http://'+self.host+'/elysian/viewstory.php?sid='+self.story.getMetadata('storyId')+'&chapter='+chapter['value']))
|
||||
# else:
|
||||
# self.chapterUrls.append((self.story.getMetadata('title'),url+"&chapter=1"))
|
||||
|
||||
for chapa in soup.findAll('a', href=re.compile(r'viewstory.php\?sid='+
|
||||
self.story.getMetadata('storyId')+'&chapter=\d+')):
|
||||
self.chapterUrls.append((stripHTML(chapa),'http://'+self.host+'/elysian/'+chapa['href']))
|
||||
|
||||
self.story.setMetadata('numChapters',len(self.chapterUrls))
|
||||
|
||||
|
||||
asoup = bs.BeautifulSoup(self._fetchUrl(self.story.getMetadata('authorUrl')))
|
||||
storylink = asoup.find('a', href=re.compile(r'viewstory.php\?sid='+
|
||||
self.story.getMetadata('storyId')+'($|[^\d])'))
|
||||
# author's story list is paginated if there's a pagelinks div.
|
||||
# Only need to look in it if the story wasn't on the first page.
|
||||
pagelinks = asoup.find('div',{'id':'pagelinks'})
|
||||
if pagelinks and storylink==None:
|
||||
authpageslist = pagelinks.findAll('a',href=re.compile(r'action=storiesby'))
|
||||
for page in authpageslist[1:]: # skip first, already checked above.
|
||||
asoup = bs.BeautifulSoup(self._fetchUrl('http://'+self.host+'/elysian/'+page['href']))
|
||||
storylink = asoup.find('a', href=re.compile(r'viewstory.php\?sid='+
|
||||
self.story.getMetadata('storyId')+'($|[^\d])'))
|
||||
if storylink:
|
||||
break
|
||||
|
||||
if not storylink:
|
||||
raise exceptions.FailedToDownload("Unable to find story metadata on author's page(s)")
|
||||
|
||||
# for metalist in asoup.findAll('div', {'class' : re.compile('listbox\s+')}):
|
||||
# a = metalist.find('a', href=re.compile(r'viewstory.php\?sid='))
|
||||
# if a != None:
|
||||
# if 'viewstory.php?sid='+self.story.getMetadata('storyId') in a['href']:
|
||||
# break
|
||||
|
||||
metalist = asoup.find('a', href=re.compile(r'viewstory.php\?sid='+
|
||||
self.story.getMetadata('storyId')+'($|[^\d])')).parent.parent
|
||||
|
||||
metalist = storylink.parent.parent
|
||||
# eFiction sites don't help us out a lot with their meta data
|
||||
# formating, so it's a little ugly.
|
||||
|
||||
@@ -228,7 +229,7 @@ class DarkSolaceOrgAdapter(BaseSiteAdapter):
|
||||
if 'Summary' in label:
|
||||
## Everything until the next span class='label'
|
||||
svalue = ""
|
||||
while not (defaultGetattr(value,'class') == 'label' or "Chapters: " in stripHTML(value)):
|
||||
while value and not (defaultGetattr(value,'class') == 'label' or "Chapters: " in stripHTML(value)):
|
||||
svalue += str(value)
|
||||
value = value.nextSibling
|
||||
self.setDescription(url,svalue)
|
||||
@@ -283,20 +284,40 @@ class DarkSolaceOrgAdapter(BaseSiteAdapter):
|
||||
# use BeautifulSoup HTML parser to make everything easier to find.
|
||||
seriessoup = bs.BeautifulSoup(self._fetchUrl(series_url))
|
||||
# can't use ^viewstory...$ in case of higher rated stories with javascript href.
|
||||
storyas = seriessoup.findAll('a', href=re.compile(r'viewstory.php\?sid=\d+'))
|
||||
i=1
|
||||
for a in storyas:
|
||||
# skip 'report this' and 'TOC' links
|
||||
if 'contact.php' not in a['href'] and 'index' not in a['href']:
|
||||
if ('viewstory.php?sid='+self.story.getMetadata('storyId')) in a['href']:
|
||||
self.setSeries(series_name, i)
|
||||
self.story.setMetadata('seriesUrl',series_url)
|
||||
storylink = seriessoup.find('a', href=re.compile(r'viewstory.php\?sid='+
|
||||
self.story.getMetadata('storyId')+'($|[^\d])'))
|
||||
if storylink and storylink.parent and storylink.parent['class'] != 'title': # in case of links inside story summaries.
|
||||
storylink = None
|
||||
|
||||
offset = 0
|
||||
# series story list is paginated if there's a pagelinks div.
|
||||
# Only need to look in it if the story wasn't on the first page.
|
||||
pagelinks = seriessoup.find('div',{'id':'pagelinks'})
|
||||
if pagelinks and storylink==None:
|
||||
authpageslist = pagelinks.findAll('a',href=re.compile(r'offset='))
|
||||
for page in authpageslist[1:]: # skip first, already checked above.
|
||||
seriessoup = bs.BeautifulSoup(self._fetchUrl('http://'+self.host+'/elysian/'+page['href']))
|
||||
storylink = seriessoup.find('a', href=re.compile(r'viewstory.php\?sid='+
|
||||
self.story.getMetadata('storyId')+'($|[^\d])'))
|
||||
if storylink and storylink.parent and storylink.parent['class'] != 'title': # in case of links inside story summaries.
|
||||
storylink = None
|
||||
if storylink:
|
||||
offset = int(page['href'].split('=')[-1]) # offset is last.
|
||||
break
|
||||
i+=1
|
||||
|
||||
# for reasons I don't understand, searching for story
|
||||
# links by regex wasn't working reliably. It was missing
|
||||
# the javascript links sometimes. This is cleaner anyway.
|
||||
for i, div in enumerate(seriessoup.findAll('div', {'class':'title'})):
|
||||
a = div.find('a') # first a is story link.
|
||||
# skip 'report this' and 'TOC' links
|
||||
if a == storylink:
|
||||
self.setSeries(series_name, 1+i+offset)
|
||||
self.story.setMetadata('seriesUrl',series_url)
|
||||
break
|
||||
|
||||
except:
|
||||
# I find it hard to care if the series parsing fails
|
||||
pass
|
||||
except Exception, e:
|
||||
print("Series parsing failed: %s"%e)
|
||||
|
||||
# grab the text for an individual chapter.
|
||||
def getChapterText(self, url):
|
||||
|
||||
@@ -48,7 +48,7 @@ class DestinysGatewayComAdapter(BaseSiteAdapter):
|
||||
|
||||
# get storyId from url--url validation guarantees query is only sid=1234
|
||||
self.story.setMetadata('storyId',self.parsedUrl.query.split('=',)[1])
|
||||
logger.debug("storyId: (%s)"%self.story.getMetadata('storyId'))
|
||||
|
||||
|
||||
# normalized story URL.
|
||||
self._setURL('http://' + self.getSiteDomain() + '/viewstory.php?sid='+self.story.getMetadata('storyId'))
|
||||
@@ -65,6 +65,7 @@ class DestinysGatewayComAdapter(BaseSiteAdapter):
|
||||
# The site domain. Does have www here, if it uses it.
|
||||
return 'www.destinysgateway.com'
|
||||
|
||||
@classmethod
|
||||
def getSiteExampleURLs(self):
|
||||
return "http://"+self.getSiteDomain()+"/viewstory.php?sid=1234"
|
||||
|
||||
@@ -130,7 +131,7 @@ class DestinysGatewayComAdapter(BaseSiteAdapter):
|
||||
|
||||
## Title
|
||||
a = soup.find('a', href=re.compile(r'viewstory.php\?sid='+self.story.getMetadata('storyId')+"$"))
|
||||
self.story.setMetadata('title',a.string)
|
||||
self.story.setMetadata('title',stripHTML(a))
|
||||
|
||||
# Find authorid and URL from... author url.
|
||||
a = soup.find('a', href=re.compile(r"viewuser.php\?uid=\d+"))
|
||||
|
||||
@@ -48,7 +48,7 @@ class DokugaComAdapter(BaseSiteAdapter):
|
||||
|
||||
# get storyId from url--url validation guarantees query is only sid=1234
|
||||
self.story.setMetadata('storyId',self.parsedUrl.path.split('/',)[3])
|
||||
logger.debug("storyId: (%s)"%self.story.getMetadata('storyId'))
|
||||
|
||||
|
||||
# www.dokuga.com has two 'sections', shown in URL as
|
||||
# 'fanfiction' and 'spark' that change how things should be
|
||||
@@ -75,6 +75,7 @@ class DokugaComAdapter(BaseSiteAdapter):
|
||||
# The site domain. Does have www here, if it uses it.
|
||||
return 'www.dokuga.com'
|
||||
|
||||
@classmethod
|
||||
def getSiteExampleURLs(self):
|
||||
return "http://"+self.getSiteDomain()+"/fanfiction/story/1234/1 http://"+self.getSiteDomain()+"/spark/story/1234/1"
|
||||
|
||||
@@ -163,7 +164,7 @@ class DokugaComAdapter(BaseSiteAdapter):
|
||||
aut.extract()
|
||||
|
||||
a = a.string[:(len(a.string)-4)]
|
||||
self.story.setMetadata('title',a)
|
||||
self.story.setMetadata('title',stripHTML(a))
|
||||
|
||||
# Find the chapters:
|
||||
chapters = soup.find('select').findAll('option')
|
||||
@@ -204,7 +205,6 @@ class DokugaComAdapter(BaseSiteAdapter):
|
||||
|
||||
a=div.text.split('Category: ')
|
||||
if len(a) == 2: self.story.addToList('category', a[1].split('&')[0])
|
||||
self.story.addToList('category', 'Fanfiction')
|
||||
|
||||
a=div.text.split('Created: ')
|
||||
if len(a) == 2: self.story.setMetadata('datePublished', makeDate(stripHTML(a[1].split('&')[0]), self.dateformat))
|
||||
|
||||
@@ -48,7 +48,7 @@ class DotMoonNetAdapter(BaseSiteAdapter):
|
||||
|
||||
# get storyId from url--url validation guarantees query is only sid=1234
|
||||
self.story.setMetadata('storyId',self.parsedUrl.query.split('=',)[1])
|
||||
logger.debug("storyId: (%s)"%self.story.getMetadata('storyId'))
|
||||
|
||||
|
||||
# normalized story URL. www.dotmoon.net/library_view.php?storyid=3
|
||||
self._setURL('http://' + self.getSiteDomain() + '/library_view.php?storyid='+self.story.getMetadata('storyId'))
|
||||
@@ -65,6 +65,7 @@ class DotMoonNetAdapter(BaseSiteAdapter):
|
||||
# The site domain. Does have www here, if it uses it.
|
||||
return 'www.dotmoon.net'
|
||||
|
||||
@classmethod
|
||||
def getSiteExampleURLs(self):
|
||||
return "http://"+self.getSiteDomain()+"/library_view.php?storyid=1234"
|
||||
|
||||
@@ -140,7 +141,7 @@ class DotMoonNetAdapter(BaseSiteAdapter):
|
||||
|
||||
## Title
|
||||
a = body.find('b')
|
||||
self.story.setMetadata('title',a.string)
|
||||
self.story.setMetadata('title',stripHTML(a))
|
||||
|
||||
# Find authorid and URL from... author url. http://www.dotmoon.net/board/index.php?action=profile;u=1'
|
||||
a = body.find('a', href=re.compile(r"index.php\?action=profile;u=\d+"))
|
||||
|
||||
@@ -48,7 +48,7 @@ class DracoAndGinnyComAdapter(BaseSiteAdapter):
|
||||
|
||||
# get storyId from url--url validation guarantees query is only sid=1234
|
||||
self.story.setMetadata('storyId',self.parsedUrl.query.split('=',)[1])
|
||||
logger.debug("storyId: (%s)"%self.story.getMetadata('storyId'))
|
||||
|
||||
|
||||
# normalized story URL.
|
||||
self._setURL('http://' + self.getSiteDomain() + '/viewstory.php?sid='+self.story.getMetadata('storyId'))
|
||||
@@ -65,6 +65,7 @@ class DracoAndGinnyComAdapter(BaseSiteAdapter):
|
||||
# The site domain. Does have www here, if it uses it.
|
||||
return 'www.dracoandginny.com'
|
||||
|
||||
@classmethod
|
||||
def getSiteExampleURLs(self):
|
||||
return "http://"+self.getSiteDomain()+"/viewstory.php?sid=1234"
|
||||
|
||||
@@ -169,7 +170,7 @@ class DracoAndGinnyComAdapter(BaseSiteAdapter):
|
||||
|
||||
## Title
|
||||
a = soup.find('a', href=re.compile(r'viewstory.php\?sid='+self.story.getMetadata('storyId')+"$"))
|
||||
self.story.setMetadata('title',a.string)
|
||||
self.story.setMetadata('title',stripHTML(a))
|
||||
|
||||
# Find authorid and URL from... author url.
|
||||
a = soup.find('a', href=re.compile(r"viewuser.php\?uid=\d+"))
|
||||
|
||||
@@ -48,7 +48,7 @@ class DramioneOrgAdapter(BaseSiteAdapter):
|
||||
|
||||
# get storyId from url--url validation guarantees query is only sid=1234
|
||||
self.story.setMetadata('storyId',self.parsedUrl.query.split('=',)[1])
|
||||
logger.debug("storyId: (%s)"%self.story.getMetadata('storyId'))
|
||||
|
||||
|
||||
# normalized story URL.
|
||||
self._setURL('http://' + self.getSiteDomain() + '/viewstory.php?sid='+self.story.getMetadata('storyId'))
|
||||
@@ -65,6 +65,7 @@ class DramioneOrgAdapter(BaseSiteAdapter):
|
||||
# The site domain. Does have www here, if it uses it.
|
||||
return 'dramione.org'
|
||||
|
||||
@classmethod
|
||||
def getSiteExampleURLs(self):
|
||||
return "http://"+self.getSiteDomain()+"/viewstory.php?sid=1234"
|
||||
|
||||
@@ -153,7 +154,7 @@ class DramioneOrgAdapter(BaseSiteAdapter):
|
||||
|
||||
## Title
|
||||
a = soup.find('a', href=re.compile(r'viewstory.php\?sid='+self.story.getMetadata('storyId')+"$"))
|
||||
self.story.setMetadata('title',a.string)
|
||||
self.story.setMetadata('title',stripHTML(a))
|
||||
|
||||
# Find authorid and URL from... author url.
|
||||
a = soup.find('a', href=re.compile(r"viewuser.php\?uid=\d+"))
|
||||
|
||||
@@ -48,7 +48,7 @@ class EfictionEstelielDeAdapter(BaseSiteAdapter):
|
||||
|
||||
# get storyId from url--url validation guarantees query is only sid=1234
|
||||
self.story.setMetadata('storyId',self.parsedUrl.query.split('=',)[1])
|
||||
logger.debug("storyId: (%s)"%self.story.getMetadata('storyId'))
|
||||
|
||||
|
||||
# normalized story URL.
|
||||
self._setURL('http://' + self.getSiteDomain() + '/viewstory.php?sid='+self.story.getMetadata('storyId'))
|
||||
@@ -65,6 +65,7 @@ class EfictionEstelielDeAdapter(BaseSiteAdapter):
|
||||
# The site domain. Does have www here, if it uses it.
|
||||
return 'efiction.esteliel.de'
|
||||
|
||||
@classmethod
|
||||
def getSiteExampleURLs(self):
|
||||
return "http://"+self.getSiteDomain()+"/viewstory.php?sid=1234"
|
||||
|
||||
@@ -103,7 +104,7 @@ class EfictionEstelielDeAdapter(BaseSiteAdapter):
|
||||
pagetitle = soup.find('div',{'id':'pagetitle'})
|
||||
## Title
|
||||
a = pagetitle.find('a', href=re.compile(r'viewstory.php\?sid='+self.story.getMetadata('storyId')+"$"))
|
||||
self.story.setMetadata('title',a.string)
|
||||
self.story.setMetadata('title',stripHTML(a))
|
||||
|
||||
# Find authorid and URL from... author url.
|
||||
a = pagetitle.find('a', href=re.compile(r"viewuser.php\?uid=\d+"))
|
||||
|
||||
@@ -48,7 +48,7 @@ class EFPFanFicNet(BaseSiteAdapter):
|
||||
|
||||
# get storyId from url--url validation guarantees query is only sid=1234
|
||||
self.story.setMetadata('storyId',self.parsedUrl.query.split('=',)[1])
|
||||
logger.debug("storyId: (%s)"%self.story.getMetadata('storyId'))
|
||||
|
||||
|
||||
# normalized story URL.
|
||||
self._setURL('http://' + self.getSiteDomain() + '/viewstory.php?sid='+self.story.getMetadata('storyId'))
|
||||
@@ -65,6 +65,7 @@ class EFPFanFicNet(BaseSiteAdapter):
|
||||
# The site domain. Does have www here, if it uses it.
|
||||
return 'www.efpfanfic.net'
|
||||
|
||||
@classmethod
|
||||
def getSiteExampleURLs(self):
|
||||
return "http://"+self.getSiteDomain()+"/viewstory.php?sid=1234"
|
||||
|
||||
@@ -165,7 +166,7 @@ class EFPFanFicNet(BaseSiteAdapter):
|
||||
logger.debug("Normalizing to URL: "+url)
|
||||
self._setURL(url)
|
||||
self.story.setMetadata('storyId',self.parsedUrl.query.split('=',)[1])
|
||||
logger.debug("storyId: (%s)"%self.story.getMetadata('storyId'))
|
||||
|
||||
|
||||
# eFiction sites don't help us out a lot with their meta data
|
||||
# formating, so it's a little ugly.
|
||||
|
||||
@@ -48,7 +48,7 @@ class ErosnSapphoSycophantHexComAdapter(BaseSiteAdapter):
|
||||
|
||||
# get storyId from url--url validation guarantees query is only sid=1234
|
||||
self.story.setMetadata('storyId',self.parsedUrl.query.split('=',)[1])
|
||||
logger.debug("storyId: (%s)"%self.story.getMetadata('storyId'))
|
||||
|
||||
|
||||
|
||||
# normalized story URL.
|
||||
@@ -66,6 +66,7 @@ class ErosnSapphoSycophantHexComAdapter(BaseSiteAdapter):
|
||||
# The site domain. Does have www here, if it uses it.
|
||||
return 'erosnsappho.sycophanthex.com'
|
||||
|
||||
@classmethod
|
||||
def getSiteExampleURLs(self):
|
||||
return "http://"+self.getSiteDomain()+"/viewstory.php?sid=1234"
|
||||
|
||||
@@ -131,7 +132,7 @@ class ErosnSapphoSycophantHexComAdapter(BaseSiteAdapter):
|
||||
## Title
|
||||
pt = soup.find('div', {'id' : 'pagetitle'})
|
||||
a = pt.find('a', href=re.compile(r'viewstory.php\?sid='+self.story.getMetadata('storyId')+"$"))
|
||||
self.story.setMetadata('title',a.text)
|
||||
self.story.setMetadata('title',stripHTML(a))
|
||||
|
||||
# Find authorid and URL from... author url.
|
||||
a = pt.find('a', href=re.compile(r"viewuser.php\?uid=\d+"))
|
||||
|
||||
@@ -64,8 +64,9 @@ class FanFictionNetSiteAdapter(BaseSiteAdapter):
|
||||
def getAcceptDomains(cls):
|
||||
return ['www.fanfiction.net','m.fanfiction.net']
|
||||
|
||||
@classmethod
|
||||
def getSiteExampleURLs(self):
|
||||
return "http://www.fanfiction.net/s/1234/1/ http://www.fanfiction.net/s/1234/12/ http://www.fanfiction.net/s/1234/1/Story_Title"
|
||||
return "http://www.fanfiction.net/s/1234/1/ http://www.fanfiction.net/s/1234/12/ http://www.fanfiction.net/s/1234/1/Story_Title http://m.fanfiction.net/s/1234/1/"
|
||||
|
||||
def getSiteURLPattern(self):
|
||||
return r"http://(www|m)?\.fanfiction\.net/s/\d+(/\d+)?(/|/[^/]+)?/?$"
|
||||
|
||||
@@ -50,7 +50,7 @@ class FanFiktionDeAdapter(BaseSiteAdapter):
|
||||
|
||||
# get storyId from url--url validation guarantees query is only sid=1234
|
||||
self.story.setMetadata('storyId',self.parsedUrl.path.split('/',)[2])
|
||||
logger.debug("storyId: (%s)"%self.story.getMetadata('storyId'))
|
||||
|
||||
|
||||
# normalized story URL.
|
||||
self._setURL('http://' + self.getSiteDomain() + '/s/'+self.story.getMetadata('storyId') + '/1')
|
||||
@@ -67,11 +67,12 @@ class FanFiktionDeAdapter(BaseSiteAdapter):
|
||||
# The site domain. Does have www here, if it uses it.
|
||||
return 'www.fanfiktion.de'
|
||||
|
||||
@classmethod
|
||||
def getSiteExampleURLs(self):
|
||||
return "http://"+self.getSiteDomain()+"/s/46ccbef30000616306614050"
|
||||
return "http://"+self.getSiteDomain()+"/s/46ccbef30000616306614050 http://"+self.getSiteDomain()+"/s/46ccbef30000616306614050/1 http://"+self.getSiteDomain()+"/s/46ccbef30000616306614050/1/story-name"
|
||||
|
||||
def getSiteURLPattern(self):
|
||||
return re.escape("http://"+self.getSiteDomain()+"/s/")+r"\w+(/\d+)?$"
|
||||
return re.escape("http://"+self.getSiteDomain()+"/s/")+r"\w+(/\d+)?"
|
||||
|
||||
## Login seems to be reasonably standard across eFiction sites.
|
||||
def needToLoginCheck(self, data):
|
||||
@@ -137,15 +138,15 @@ class FanFiktionDeAdapter(BaseSiteAdapter):
|
||||
# Now go hunting for all the meta data and the chapter list.
|
||||
|
||||
## Title
|
||||
a = soup.find('a', href=re.compile(r'/s/'+self.story.getMetadata('storyId')+"$"))
|
||||
self.story.setMetadata('title',a.string)
|
||||
a = soup.find('a', href=re.compile(r'/s/'+self.story.getMetadata('storyId')+"/"))
|
||||
self.story.setMetadata('title',stripHTML(a))
|
||||
|
||||
# Find authorid and URL from... author url.
|
||||
head = soup.find('div', {'class' : 'story-metadata-left-top'})
|
||||
a = head.find('a')
|
||||
self.story.setMetadata('authorId',a['href'].split('/')[2])
|
||||
self.story.setMetadata('authorUrl','http://'+self.host+'/'+a['href'])
|
||||
self.story.setMetadata('author',a.string)
|
||||
self.story.setMetadata('author',stripHTML(a))
|
||||
|
||||
# Find the chapters:
|
||||
for chapter in soup.find('select').findAll('option'):
|
||||
@@ -172,14 +173,14 @@ class FanFiktionDeAdapter(BaseSiteAdapter):
|
||||
tr=asoup.findAll('tr')
|
||||
for i in range(1,len(tr)):
|
||||
a = tr[i].find('a')
|
||||
if a['href'] == '/s/'+self.story.getMetadata('storyId'):
|
||||
if '/s/'+self.story.getMetadata('storyId')+'/1/' in a['href']:
|
||||
break
|
||||
self.setDescription(url,a['onmouseover'].split("', '")[1])
|
||||
|
||||
td = tr[i].findAll('td')
|
||||
self.story.addToList('category',stripHTML(td[1]))
|
||||
self.story.setMetadata('rating', td[4].string)
|
||||
self.story.setMetadata('numWords', td[5].string)
|
||||
self.story.setMetadata('rating', stripHTML(td[4]))
|
||||
self.story.setMetadata('numWords', stripHTML(td[5]))
|
||||
|
||||
|
||||
# grab the text for an individual chapter.
|
||||
|
||||
@@ -52,7 +52,7 @@ class FicBookNetAdapter(BaseSiteAdapter):
|
||||
|
||||
# get storyId from url--url validation guarantees query is only sid=1234
|
||||
self.story.setMetadata('storyId',self.parsedUrl.path.split('/',)[2])
|
||||
logger.debug("storyId: (%s)"%self.story.getMetadata('storyId'))
|
||||
|
||||
|
||||
# normalized story URL.
|
||||
self._setURL('http://' + self.getSiteDomain() + '/readfic/'+self.story.getMetadata('storyId'))
|
||||
@@ -69,8 +69,9 @@ class FicBookNetAdapter(BaseSiteAdapter):
|
||||
# The site domain. Does have www here, if it uses it.
|
||||
return 'www.ficbook.net'
|
||||
|
||||
@classmethod
|
||||
def getSiteExampleURLs(self):
|
||||
return "http://"+self.getSiteDomain()+"/readfic/12345"
|
||||
return "http://"+self.getSiteDomain()+"/readfic/12345 http://"+self.getSiteDomain()+"/readfic/93626/246417#part_content"
|
||||
|
||||
def getSiteURLPattern(self):
|
||||
return re.escape("http://"+self.getSiteDomain()+"/readfic/")+r"\d+"
|
||||
|
||||
@@ -45,7 +45,7 @@ class FictionAlleyOrgSiteAdapter(BaseSiteAdapter):
|
||||
if m:
|
||||
self.story.setMetadata('authorId',m.group('auth'))
|
||||
self.story.setMetadata('storyId',m.group('id'))
|
||||
logger.debug("storyId: (%s)"%self.story.getMetadata('storyId'))
|
||||
|
||||
# normalized story URL.
|
||||
self._setURL(url)
|
||||
else:
|
||||
@@ -57,6 +57,7 @@ class FictionAlleyOrgSiteAdapter(BaseSiteAdapter):
|
||||
def getSiteDomain():
|
||||
return 'www.fictionalley.org'
|
||||
|
||||
@classmethod
|
||||
def getSiteExampleURLs(self):
|
||||
return "http://"+self.getSiteDomain()+"/authors/drt/DA.html http://"+self.getSiteDomain()+"/authors/drt/JOTP01a.html"
|
||||
|
||||
@@ -110,7 +111,7 @@ class FictionAlleyOrgSiteAdapter(BaseSiteAdapter):
|
||||
url=self.url
|
||||
logger.debug("Normalizing to URL: "+url)
|
||||
## title's right there...
|
||||
self.story.setMetadata('title',storya.string)
|
||||
self.story.setMetadata('title',stripHTML(storya))
|
||||
data = self._fetchUrl(url)
|
||||
soup = bs.BeautifulSoup(data)
|
||||
chapterlinklist = soup.findAll('a',{'class':'chapterlink'})
|
||||
@@ -120,7 +121,7 @@ class FictionAlleyOrgSiteAdapter(BaseSiteAdapter):
|
||||
## same way.
|
||||
chapsoup = bs.BeautifulSoup(chapterdata)
|
||||
storya = chapsoup.find('div',{'class':'breadcrumbs'}).findAll('a')[1]
|
||||
self.story.setMetadata('title',storya.string)
|
||||
self.story.setMetadata('title',stripHTML(storya))
|
||||
del chapsoup
|
||||
|
||||
del chapterdata
|
||||
|
||||
@@ -39,8 +39,9 @@ class FictionPressComSiteAdapter(FanFictionNetSiteAdapter):
|
||||
def getAcceptDomains(cls):
|
||||
return ['www.fictionpress.com','m.fictionpress.com']
|
||||
|
||||
@classmethod
|
||||
def getSiteExampleURLs(self):
|
||||
return "http://www.fictionpress.com/s/1234/1/ http://www.fictionpress.com/s/1234/12/ http://www.fictionpress.com/s/1234/1/Story_Title"
|
||||
return "http://www.fictionpress.com/s/1234/1/ http://www.fictionpress.com/s/1234/12/ http://www.fictionpress.com/s/1234/1/Story_Title http://m.fictionpress.com/s/1234/1/"
|
||||
|
||||
def getSiteURLPattern(self):
|
||||
return r"http://(www|m)?\.fictionpress\.com/s/\d+(/\d+)?(/|/[a-zA-Z0-9_-]+)?/?$"
|
||||
|
||||
@@ -45,8 +45,9 @@ class FicwadComSiteAdapter(BaseSiteAdapter):
|
||||
def getSiteDomain():
|
||||
return 'ficwad.com'
|
||||
|
||||
@classmethod
|
||||
def getSiteExampleURLs(self):
|
||||
return "http://ficwad.com/story/137169"
|
||||
return "http://ficwad.com/story/1234"
|
||||
|
||||
def getSiteURLPattern(self):
|
||||
return re.escape(r"http://"+self.getSiteDomain())+"/story/\d+?$"
|
||||
@@ -115,7 +116,7 @@ class FicwadComSiteAdapter(BaseSiteAdapter):
|
||||
|
||||
# title - first h4 tag will be title.
|
||||
titleh4 = soup.find('h4')
|
||||
self.story.setMetadata('title', titleh4.a.string)
|
||||
self.story.setMetadata('title', stripHTML(titleh4.a))
|
||||
|
||||
# Find authorid and URL from... author url.
|
||||
a = soup.find('a', href=re.compile(r"^/author/\d+"))
|
||||
|
||||
@@ -51,6 +51,7 @@ class FimFictionNetSiteAdapter(BaseSiteAdapter):
|
||||
# mobile.fimifction.com isn't actually a valid domain, but we can still get the story id from URLs anyway
|
||||
return ['www.fimfiction.net','mobile.fimfiction.net', 'www.fimfiction.com', 'mobile.fimfiction.com']
|
||||
|
||||
@classmethod
|
||||
def getSiteExampleURLs(self):
|
||||
return "http://www.fimfiction.net/story/1234/story-title-here http://www.fimfiction.net/story/1234/ http://www.fimfiction.com/story/1234/1/ http://mobile.fimfiction.net/story/1234/1/story-title-here/chapter-title-here"
|
||||
|
||||
@@ -116,7 +117,7 @@ class FimFictionNetSiteAdapter(BaseSiteAdapter):
|
||||
|
||||
## Title
|
||||
a = soup.find('a', href=re.compile(r'^/story/'+self.story.getMetadata('storyId')))
|
||||
self.story.setMetadata('title',a.string)
|
||||
self.story.setMetadata('title',stripHTML(a))
|
||||
|
||||
# self.story.setMetadata("title", storyMetadata["title"])
|
||||
# if not storyMetadata["title"]:
|
||||
|
||||
@@ -50,7 +50,7 @@ class FineStoriesComAdapter(BaseSiteAdapter):
|
||||
self.story.setMetadata('storyId',self.parsedUrl.path.split('/',)[2].split(':')[0])
|
||||
if 'storyInfo' in self.story.getMetadata('storyId'):
|
||||
self.story.setMetadata('storyId',self.parsedUrl.query.split('=',)[1])
|
||||
logger.debug("storyId: (%s)"%self.story.getMetadata('storyId'))
|
||||
|
||||
|
||||
# normalized story URL.
|
||||
self._setURL('http://' + self.getSiteDomain() + '/s/storyInfo.php?id='+self.story.getMetadata('storyId'))
|
||||
@@ -67,8 +67,9 @@ class FineStoriesComAdapter(BaseSiteAdapter):
|
||||
# The site domain. Does have www here, if it uses it.
|
||||
return 'finestories.com'
|
||||
|
||||
@classmethod
|
||||
def getSiteExampleURLs(self):
|
||||
return "http://"+self.getSiteDomain()+"/s/10537 http://"+self.getSiteDomain()+"/s/10537:4010 http://"+self.getSiteDomain()+"/library/storyInfo.php?id=10537"
|
||||
return "http://"+self.getSiteDomain()+"/s/1234 http://"+self.getSiteDomain()+"/s/1234:4010 http://"+self.getSiteDomain()+"/library/storyInfo.php?id=1234"
|
||||
|
||||
def getSiteURLPattern(self):
|
||||
return re.escape("http://"+self.getSiteDomain())+r"/(s|library)?/(storyInfo.php\?id=)?\d+(:\d+)?(;\d+)?$"
|
||||
@@ -141,7 +142,7 @@ class FineStoriesComAdapter(BaseSiteAdapter):
|
||||
|
||||
## Title
|
||||
a = soup.find('a', href=re.compile(r'/s/'+self.story.getMetadata('storyId')+"$"))
|
||||
self.story.setMetadata('title',a.text)
|
||||
self.story.setMetadata('title',stripHTML(a))
|
||||
|
||||
# Find authorid and URL from... author url.
|
||||
a = soup.find('a', href=re.compile(r"/a/\w+"))
|
||||
|
||||
@@ -48,7 +48,7 @@ class GrangerEnchantedCom(BaseSiteAdapter):
|
||||
|
||||
# get storyId from url--url validation guarantees query is only sid=1234
|
||||
self.story.setMetadata('storyId',self.parsedUrl.query.split('=',)[1])
|
||||
logger.debug("storyId: (%s)"%self.story.getMetadata('storyId'))
|
||||
|
||||
self.section=self.parsedUrl.path.split('/',)[1]
|
||||
|
||||
# normalized story URL.
|
||||
@@ -74,6 +74,7 @@ class GrangerEnchantedCom(BaseSiteAdapter):
|
||||
def getAcceptDomains(cls):
|
||||
return ['grangerenchanted.com','malfoymanor.grangerenchanted.com']
|
||||
|
||||
@classmethod
|
||||
def getSiteExampleURLs(self):
|
||||
return "http://grangerenchanted.com/enchant/viewstory.php?sid=1234 http://malfoymanor.grangerenchanted.com/themanor/viewstory.php?sid=1234"
|
||||
|
||||
@@ -181,7 +182,7 @@ class GrangerEnchantedCom(BaseSiteAdapter):
|
||||
|
||||
## Title
|
||||
a = soup.find('a', href=re.compile(r'viewstory.php\?sid='+self.story.getMetadata('storyId')+"$"))
|
||||
self.story.setMetadata('title',a.string)
|
||||
self.story.setMetadata('title',stripHTML(a))
|
||||
|
||||
# Find authorid and URL from... author url.
|
||||
a = soup.find('a', href=re.compile(r"viewuser.php\?uid=\d+"))
|
||||
|
||||
@@ -42,7 +42,7 @@ class HarryPotterFanFictionComSiteAdapter(BaseSiteAdapter):
|
||||
|
||||
# get storyId from url--url validation guarantees query is only psid=1234
|
||||
self.story.setMetadata('storyId',self.parsedUrl.query.split('=',)[1])
|
||||
logger.debug("storyId: (%s)"%self.story.getMetadata('storyId'))
|
||||
|
||||
|
||||
# normalized story URL.
|
||||
self._setURL('http://' + self.getSiteDomain() + '/viewstory.php?psid='+self.story.getMetadata('storyId'))
|
||||
@@ -56,8 +56,9 @@ class HarryPotterFanFictionComSiteAdapter(BaseSiteAdapter):
|
||||
def getAcceptDomains(cls):
|
||||
return ['www.harrypotterfanfiction.com','harrypotterfanfiction.com']
|
||||
|
||||
@classmethod
|
||||
def getSiteExampleURLs(self):
|
||||
return "http://www.harrypotterfanfiction.com/viewstory.php?psid=1234 http://harrypotterfanfiction.com/viewstory.php?psid=5678"
|
||||
return "http://www.harrypotterfanfiction.com/viewstory.php?psid=1234"
|
||||
|
||||
def getSiteURLPattern(self):
|
||||
return re.escape("http://")+r"(www\.)?"+re.escape("harrypotterfanfiction.com/viewstory.php?psid=")+r"\d+$"
|
||||
@@ -91,7 +92,7 @@ class HarryPotterFanFictionComSiteAdapter(BaseSiteAdapter):
|
||||
|
||||
## Title
|
||||
a = soup.find('a', href=re.compile(r'\?psid='+self.story.getMetadata('storyId')))
|
||||
self.story.setMetadata('title',a.string)
|
||||
self.story.setMetadata('title',stripHTML(a))
|
||||
## javascript:if (confirm('Please note. This story may contain adult themes. By clicking here you are stating that you are over 17. Click cancel if you do not meet this requirement.')) location = '?psid=290995'
|
||||
if "This story may contain adult themes." in a['href'] and not (self.is_adult or self.getConfig("is_adult")):
|
||||
raise exceptions.AdultCheckRequired(self.url)
|
||||
@@ -130,55 +131,55 @@ class HarryPotterFanFictionComSiteAdapter(BaseSiteAdapter):
|
||||
|
||||
## Finding the metadata is a bit of a pain. Most of the meta
|
||||
## data is in a center.table without a bgcolor.
|
||||
for center in soup.findAll('center'):
|
||||
table = center.find('table',{'bgcolor':None})
|
||||
if table:
|
||||
metastr = stripHTML(str(table)).replace('\n',' ').replace('\t',' ')
|
||||
# Rating: 12+ Story Reviews: 3
|
||||
# Chapters: 3
|
||||
# Characters: Andromeda, Ted, Bellatrix, R. Lestrange, Lucius, Narcissa, OC
|
||||
# Genre(s): Fluff, Romance, Young Adult Era: OtherPairings: Other Pairing, Lucius/Narcissa
|
||||
# Status: Completed
|
||||
# First Published: 2010.09.02
|
||||
# Last Published Chapter: 2010.09.28
|
||||
# Last Updated: 2010.09.28
|
||||
# Favorite Story Of: 1 users
|
||||
# Warnings: Scenes of a Mild Sexual Nature
|
||||
#for center in soup.findAll('center'):
|
||||
table = soup.find('table',{'class':'storymaininfo'})
|
||||
if table:
|
||||
metastr = stripHTML(str(table)).replace('\n',' ').replace('\t',' ')
|
||||
# Rating: 12+ Story Reviews: 3
|
||||
# Chapters: 3
|
||||
# Characters: Andromeda, Ted, Bellatrix, R. Lestrange, Lucius, Narcissa, OC
|
||||
# Genre(s): Fluff, Romance, Young Adult Era: OtherPairings: Other Pairing, Lucius/Narcissa
|
||||
# Status: Completed
|
||||
# First Published: 2010.09.02
|
||||
# Last Published Chapter: 2010.09.28
|
||||
# Last Updated: 2010.09.28
|
||||
# Favorite Story Of: 1 users
|
||||
# Warnings: Scenes of a Mild Sexual Nature
|
||||
|
||||
m = re.match(r".*?Status: Completed.*?",metastr)
|
||||
if m:
|
||||
self.story.setMetadata('status','Completed')
|
||||
else:
|
||||
self.story.setMetadata('status','In-Progress')
|
||||
m = re.match(r".*?Status: Completed.*?",metastr)
|
||||
if m:
|
||||
self.story.setMetadata('status','Completed')
|
||||
else:
|
||||
self.story.setMetadata('status','In-Progress')
|
||||
|
||||
m = re.match(r".*?Rating: (.+?) Story Reviews.*?",metastr)
|
||||
if m:
|
||||
self.story.setMetadata('rating', m.group(1))
|
||||
m = re.match(r".*?Rating: (.+?) Story Reviews.*?",metastr)
|
||||
if m:
|
||||
self.story.setMetadata('rating', m.group(1))
|
||||
|
||||
m = re.match(r".*?Genre\(s\): (.+?) Era.*?",metastr)
|
||||
if m:
|
||||
for g in m.group(1).split(','):
|
||||
self.story.addToList('genre',g)
|
||||
|
||||
m = re.match(r".*?Characters: (.+?) Genre.*?",metastr)
|
||||
if m:
|
||||
for g in m.group(1).split(','):
|
||||
self.story.addToList('characters',g)
|
||||
|
||||
m = re.match(r".*?Warnings: (.+).*?",metastr)
|
||||
if m:
|
||||
for w in m.group(1).split(','):
|
||||
if w != 'Now Warnings':
|
||||
self.story.addToList('warnings',w)
|
||||
|
||||
m = re.match(r".*?First Published: ([0-9\.]+).*?",metastr)
|
||||
if m:
|
||||
self.story.setMetadata('datePublished',makeDate(m.group(1), "%Y.%m.%d"))
|
||||
m = re.match(r".*?Genre\(s\): (.+?) Era.*?",metastr)
|
||||
if m:
|
||||
for g in m.group(1).split(','):
|
||||
self.story.addToList('genre',g)
|
||||
|
||||
m = re.match(r".*?Characters: (.+?) Genre.*?",metastr)
|
||||
if m:
|
||||
for g in m.group(1).split(','):
|
||||
self.story.addToList('characters',g)
|
||||
|
||||
m = re.match(r".*?Warnings: (.+).*?",metastr)
|
||||
if m:
|
||||
for w in m.group(1).split(','):
|
||||
if w != 'Now Warnings':
|
||||
self.story.addToList('warnings',w)
|
||||
|
||||
m = re.match(r".*?First Published: ([0-9\.]+).*?",metastr)
|
||||
if m:
|
||||
self.story.setMetadata('datePublished',makeDate(m.group(1), "%Y.%m.%d"))
|
||||
|
||||
# Updated can have more than one space after it. <shrug>
|
||||
m = re.match(r".*?Last Updated: ([0-9\.]+).*?",metastr)
|
||||
if m:
|
||||
self.story.setMetadata('dateUpdated',makeDate(m.group(1), "%Y.%m.%d"))
|
||||
# Updated can have more than one space after it. <shrug>
|
||||
m = re.match(r".*?Last Updated: ([0-9\.]+).*?",metastr)
|
||||
if m:
|
||||
self.story.setMetadata('dateUpdated',makeDate(m.group(1), "%Y.%m.%d"))
|
||||
|
||||
def getChapterText(self, url):
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ class HennethAnnunNetAdapter(BaseSiteAdapter):
|
||||
|
||||
# get storyId from url--url validation guarantees query is only sid=1234
|
||||
self.story.setMetadata('storyId',self.parsedUrl.query.split('=',)[1])
|
||||
logger.debug("storyId: (%s)"%self.story.getMetadata('storyId'))
|
||||
|
||||
|
||||
# normalized story URL.
|
||||
self._setURL('http://' + self.getSiteDomain() + '/stories/chapter.cfm?stid='+self.story.getMetadata('storyId'))
|
||||
@@ -65,6 +65,7 @@ class HennethAnnunNetAdapter(BaseSiteAdapter):
|
||||
# The site domain. Does have www here, if it uses it.
|
||||
return 'www.henneth-annun.net'
|
||||
|
||||
@classmethod
|
||||
def getSiteExampleURLs(self):
|
||||
return "http://"+self.getSiteDomain()+"/stories/chapter.cfm?stid=1234"
|
||||
|
||||
@@ -100,7 +101,7 @@ class HennethAnnunNetAdapter(BaseSiteAdapter):
|
||||
|
||||
## Title
|
||||
a = soup.find('h2', {'id':'page_heading'})
|
||||
self.story.setMetadata('title',a.string)
|
||||
self.story.setMetadata('title',stripHTML(a))
|
||||
|
||||
# Find the chapters: chapter_view.cfm?stid=6663&spordinal=1"
|
||||
for chapter in soup.findAll('a', href=re.compile(r'chapter_view.cfm\?stid='+self.story.getMetadata('storyId')+"&spordinal=\d+$")):
|
||||
|
||||
@@ -48,7 +48,7 @@ class HLFictionNetAdapter(BaseSiteAdapter):
|
||||
|
||||
# get storyId from url--url validation guarantees query is only sid=1234
|
||||
self.story.setMetadata('storyId',self.parsedUrl.query.split('=',)[1])
|
||||
logger.debug("storyId: (%s)"%self.story.getMetadata('storyId'))
|
||||
|
||||
|
||||
# normalized story URL.
|
||||
self._setURL('http://' + self.getSiteDomain() + '/viewstory.php?sid='+self.story.getMetadata('storyId'))
|
||||
@@ -65,6 +65,7 @@ class HLFictionNetAdapter(BaseSiteAdapter):
|
||||
# The site domain. Does have www here, if it uses it.
|
||||
return 'hlfiction.net'
|
||||
|
||||
@classmethod
|
||||
def getSiteExampleURLs(self):
|
||||
return "http://"+self.getSiteDomain()+"/viewstory.php?sid=1234"
|
||||
|
||||
@@ -105,7 +106,7 @@ class HLFictionNetAdapter(BaseSiteAdapter):
|
||||
self.story.setMetadata('author',aut.string)
|
||||
aut.extract()
|
||||
|
||||
self.story.setMetadata('title',a.string[:(len(a.string)-3)])
|
||||
self.story.setMetadata('title',stripHTML(a)[:(len(a.string)-3)])
|
||||
|
||||
# Find the chapters:
|
||||
chapters=soup.find('select')
|
||||
|
||||
@@ -52,7 +52,7 @@ class HPFandomNetAdapterAdapter(BaseSiteAdapter): # XXX
|
||||
|
||||
# get storyId from url--url validation guarantees query is only sid=1234
|
||||
self.story.setMetadata('storyId',self.parsedUrl.query.split('=',)[1])
|
||||
logger.debug("storyId: (%s)"%self.story.getMetadata('storyId'))
|
||||
|
||||
|
||||
# normalized story URL.
|
||||
# XXX Most sites don't have the /eff part. Replace all to remove it usually.
|
||||
@@ -70,6 +70,7 @@ class HPFandomNetAdapterAdapter(BaseSiteAdapter): # XXX
|
||||
# The site domain. Does have www here, if it uses it.
|
||||
return 'www.hpfandom.net' # XXX
|
||||
|
||||
@classmethod
|
||||
def getSiteExampleURLs(self):
|
||||
return "http://"+self.getSiteDomain()+"/eff/viewstory.php?sid=1234"
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ class HPFanficArchiveComAdapter(BaseSiteAdapter):
|
||||
|
||||
# get storyId from url--url validation guarantees query is only sid=1234
|
||||
self.story.setMetadata('storyId',self.parsedUrl.query.split('=',)[1])
|
||||
logger.debug("storyId: (%s)"%self.story.getMetadata('storyId'))
|
||||
|
||||
|
||||
# normalized story URL.
|
||||
self._setURL('http://' + self.getSiteDomain() + '/stories/viewstory.php?sid='+self.story.getMetadata('storyId'))
|
||||
@@ -65,6 +65,7 @@ class HPFanficArchiveComAdapter(BaseSiteAdapter):
|
||||
# The site domain. Does have www here, if it uses it.
|
||||
return 'www.hpfanficarchive.com'
|
||||
|
||||
@classmethod
|
||||
def getSiteExampleURLs(self):
|
||||
return "http://"+self.getSiteDomain()+"/stories/viewstory.php?sid=1234"
|
||||
|
||||
@@ -99,7 +100,7 @@ class HPFanficArchiveComAdapter(BaseSiteAdapter):
|
||||
|
||||
## Title
|
||||
a = soup.find('a', href=re.compile(r'viewstory.php\?sid='+self.story.getMetadata('storyId')+"$"))
|
||||
self.story.setMetadata('title',a.string)
|
||||
self.story.setMetadata('title',stripHTML(a))
|
||||
|
||||
# Find authorid and URL from... author url.
|
||||
a = soup.find('a', href=re.compile(r"viewuser.php\?uid=\d+"))
|
||||
|
||||
@@ -48,7 +48,7 @@ class IkEternalNetAdapter(BaseSiteAdapter):
|
||||
|
||||
# get storyId from url--url validation guarantees query is only sid=1234
|
||||
self.story.setMetadata('storyId',self.parsedUrl.query.split('=',)[1])
|
||||
logger.debug("storyId: (%s)"%self.story.getMetadata('storyId'))
|
||||
|
||||
|
||||
# normalized story URL.
|
||||
self._setURL('http://' + self.getSiteDomain() + '/viewstory.php?sid='+self.story.getMetadata('storyId'))
|
||||
@@ -65,6 +65,7 @@ class IkEternalNetAdapter(BaseSiteAdapter):
|
||||
# The site domain. Does have www here, if it uses it.
|
||||
return 'www.ik-eternal.net'
|
||||
|
||||
@classmethod
|
||||
def getSiteExampleURLs(self):
|
||||
return "http://"+self.getSiteDomain()+"/viewstory.php?sid=1234"
|
||||
|
||||
@@ -182,7 +183,7 @@ class IkEternalNetAdapter(BaseSiteAdapter):
|
||||
|
||||
## Title
|
||||
a = soup.find('a', href=re.compile(r'viewstory.php\?sid='+self.story.getMetadata('storyId')+"$"))
|
||||
self.story.setMetadata('title',a.string)
|
||||
self.story.setMetadata('title',stripHTML(a))
|
||||
|
||||
# Find authorid and URL from... author url.
|
||||
a = soup.find('a', href=re.compile(r"viewuser.php\?uid=\d+"))
|
||||
|
||||
@@ -48,7 +48,7 @@ class ImagineEFicComAdapter(BaseSiteAdapter):
|
||||
|
||||
# get storyId from url--url validation guarantees query is only sid=1234
|
||||
self.story.setMetadata('storyId',self.parsedUrl.query.split('=',)[1])
|
||||
logger.debug("storyId: (%s)"%self.story.getMetadata('storyId'))
|
||||
|
||||
|
||||
# normalized story URL.
|
||||
self._setURL('http://' + self.getSiteDomain() + '/viewstory.php?sid='+self.story.getMetadata('storyId'))
|
||||
@@ -65,6 +65,7 @@ class ImagineEFicComAdapter(BaseSiteAdapter):
|
||||
# The site domain. Does have www here, if it uses it.
|
||||
return 'imagine.e-fic.com'
|
||||
|
||||
@classmethod
|
||||
def getSiteExampleURLs(self):
|
||||
return "http://"+self.getSiteDomain()+"/viewstory.php?sid=1234"
|
||||
|
||||
@@ -169,7 +170,7 @@ class ImagineEFicComAdapter(BaseSiteAdapter):
|
||||
|
||||
## Title
|
||||
a = soup.find('a', href=re.compile(r'viewstory.php\?sid='+self.story.getMetadata('storyId')+"$"))
|
||||
self.story.setMetadata('title',a.string)
|
||||
self.story.setMetadata('title',stripHTML(a))
|
||||
|
||||
# Find authorid and URL from... author url.
|
||||
a = soup.find('a', href=re.compile(r"viewuser.php\?uid=\d+"))
|
||||
|
||||
@@ -51,7 +51,7 @@ class InDeathNetAdapter(BaseSiteAdapter):
|
||||
m = re.match(self.getSiteURLPattern(),url)
|
||||
if m:
|
||||
self.story.setMetadata('storyId',m.group('id'))
|
||||
logger.debug("storyId: (%s)"%self.story.getMetadata('storyId'))
|
||||
|
||||
# normalized story URL.
|
||||
self._setURL('http://www.' + self.getSiteDomain() + '/blog/archive/'+self.story.getMetadata('storyId')+'-'+m.group('name')+'/')
|
||||
else:
|
||||
@@ -72,6 +72,7 @@ class InDeathNetAdapter(BaseSiteAdapter):
|
||||
return 'indeath.net'
|
||||
|
||||
|
||||
@classmethod
|
||||
def getSiteExampleURLs(self):
|
||||
return "http://"+self.getSiteDomain()+"/blog/archive/123-story-in-death/"
|
||||
|
||||
@@ -108,7 +109,7 @@ class InDeathNetAdapter(BaseSiteAdapter):
|
||||
## Title
|
||||
h = soup.find('a', id="blog_title")
|
||||
t = h.find('span')
|
||||
self.story.setMetadata('title',t.contents[0].string.strip())
|
||||
self.story.setMetadata('title',stripHTML(t.contents[0]).strip())
|
||||
|
||||
s = t.find('div')
|
||||
if s != None:
|
||||
@@ -121,9 +122,6 @@ class InDeathNetAdapter(BaseSiteAdapter):
|
||||
self.story.setMetadata('authorUrl',a['href'])
|
||||
self.story.setMetadata('author',m.group('name'))
|
||||
|
||||
|
||||
|
||||
|
||||
# Find the chapters:
|
||||
chapters=soup.findAll('a', title="View entry", href=re.compile(r'http://www.indeath.net/blog/'+self.story.getMetadata('storyId')+"/entry\-(\d+)\-([^/]*)/$"))
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ class KSArchiveComAdapter(BaseSiteAdapter): # XXX
|
||||
|
||||
# get storyId from url--url validation guarantees query is only sid=1234
|
||||
self.story.setMetadata('storyId',self.parsedUrl.query.split('=',)[1])
|
||||
logger.debug("storyId: (%s)"%self.story.getMetadata('storyId'))
|
||||
|
||||
|
||||
# normalized story URL.
|
||||
# XXX Most sites don't have the /fanfic part. Replace all to remove it usually.
|
||||
@@ -74,6 +74,7 @@ class KSArchiveComAdapter(BaseSiteAdapter): # XXX
|
||||
# The site domain. Does have www here, if it uses it.
|
||||
return 'ksarchive.com' # XXX
|
||||
|
||||
@classmethod
|
||||
def getSiteExampleURLs(self):
|
||||
return "http://"+self.getSiteDomain()+"/viewstory.php?sid=1234"
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ class LibraryOfMoriaComAdapter(BaseSiteAdapter):
|
||||
|
||||
# get storyId from url--url validation guarantees query is only sid=1234
|
||||
self.story.setMetadata('storyId',self.parsedUrl.query.split('=',)[1])
|
||||
logger.debug("storyId: (%s)"%self.story.getMetadata('storyId'))
|
||||
|
||||
|
||||
# normalized story URL.
|
||||
self._setURL('http://' + self.getSiteDomain() + '/a/viewstory.php?sid='+self.story.getMetadata('storyId'))
|
||||
@@ -66,6 +66,7 @@ class LibraryOfMoriaComAdapter(BaseSiteAdapter):
|
||||
# The site domain. Does have www here, if it uses it.
|
||||
return 'www.libraryofmoria.com'
|
||||
|
||||
@classmethod
|
||||
def getSiteExampleURLs(self):
|
||||
return "http://"+self.getSiteDomain()+"/a/viewstory.php?sid=1234"
|
||||
|
||||
@@ -128,7 +129,7 @@ class LibraryOfMoriaComAdapter(BaseSiteAdapter):
|
||||
|
||||
## Title
|
||||
a = soup.find('a', href=re.compile(r'viewstory.php\?sid='+self.story.getMetadata('storyId')+"$"))
|
||||
self.story.setMetadata('title',a.string)
|
||||
self.story.setMetadata('title',stripHTML(a))
|
||||
|
||||
# Find authorid and URL from... author url.
|
||||
a = soup.find('a', href=re.compile(r"viewuser.php\?uid=\d+"))
|
||||
|
||||
@@ -48,7 +48,7 @@ class LumosSycophantHexComAdapter(BaseSiteAdapter):
|
||||
|
||||
# get storyId from url--url validation guarantees query is only sid=1234
|
||||
self.story.setMetadata('storyId',self.parsedUrl.query.split('=',)[1])
|
||||
logger.debug("storyId: (%s)"%self.story.getMetadata('storyId'))
|
||||
|
||||
|
||||
|
||||
# normalized story URL.
|
||||
@@ -66,6 +66,7 @@ class LumosSycophantHexComAdapter(BaseSiteAdapter):
|
||||
# The site domain. Does have www here, if it uses it.
|
||||
return 'lumos.sycophanthex.com'
|
||||
|
||||
@classmethod
|
||||
def getSiteExampleURLs(self):
|
||||
return "http://"+self.getSiteDomain()+"/viewstory.php?sid=1234"
|
||||
|
||||
@@ -115,7 +116,7 @@ class LumosSycophantHexComAdapter(BaseSiteAdapter):
|
||||
## Title
|
||||
pt = soup.find('div', {'id' : 'pagetitle'})
|
||||
a = pt.find('a', href=re.compile(r'viewstory.php\?sid='+self.story.getMetadata('storyId')+"$"))
|
||||
self.story.setMetadata('title',a.text)
|
||||
self.story.setMetadata('title',stripHTML(a))
|
||||
|
||||
# Find authorid and URL from... author url.
|
||||
a = pt.find('a', href=re.compile(r"viewuser.php\?uid=\d+"))
|
||||
|
||||
@@ -43,7 +43,7 @@ class MediaMinerOrgSiteAdapter(BaseSiteAdapter):
|
||||
m = re.match(self.getSiteURLPattern(),url)
|
||||
if m:
|
||||
self.story.setMetadata('storyId',m.group('id'))
|
||||
logger.debug("storyId: (%s)"%self.story.getMetadata('storyId'))
|
||||
|
||||
# normalized story URL.
|
||||
self._setURL('http://' + self.getSiteDomain() + '/fanfic/view_st.php/'+self.story.getMetadata('storyId'))
|
||||
else:
|
||||
@@ -55,6 +55,7 @@ class MediaMinerOrgSiteAdapter(BaseSiteAdapter):
|
||||
def getSiteDomain():
|
||||
return 'www.mediaminer.org'
|
||||
|
||||
@classmethod
|
||||
def getSiteExampleURLs(self):
|
||||
return "http://"+self.getSiteDomain()+"/fanfic/view_st.php/123456 http://"+self.getSiteDomain()+"/fanfic/view_ch.php/1234123/123444#fic_c"
|
||||
|
||||
@@ -106,10 +107,10 @@ class MediaMinerOrgSiteAdapter(BaseSiteAdapter):
|
||||
for font in title.findAll('font'):
|
||||
font.extract() # removes 'font' tags from inside the td.
|
||||
if title.has_key('colspan'):
|
||||
titlet = title.text
|
||||
titlet = stripHTML(title)
|
||||
else:
|
||||
## No colspan, it's part chapter title--even if it's a one-shot.
|
||||
titlet = ':'.join(title.text.split(':')[:-1]) # strip trailing 'Chapter X' or chapter title
|
||||
titlet = ':'.join(stripHTML(title).split(':')[:-1]) # strip trailing 'Chapter X' or chapter title
|
||||
self.story.setMetadata('title',titlet)
|
||||
## The story title is difficult to reliably parse from the
|
||||
## story pages. Getting it from the author page is, but costs
|
||||
|
||||
@@ -48,7 +48,7 @@ class MerlinFicDtwinsCoUk(BaseSiteAdapter):
|
||||
|
||||
# get storyId from url--url validation guarantees query is only sid=1234
|
||||
self.story.setMetadata('storyId',self.parsedUrl.query.split('=',)[1])
|
||||
logger.debug("storyId: (%s)"%self.story.getMetadata('storyId'))
|
||||
|
||||
|
||||
# normalized story URL.
|
||||
self._setURL('http://' + self.getSiteDomain() + '/viewstory.php?sid='+self.story.getMetadata('storyId'))
|
||||
@@ -65,6 +65,7 @@ class MerlinFicDtwinsCoUk(BaseSiteAdapter):
|
||||
# The site domain. Does have www here, if it uses it.
|
||||
return 'merlinfic.dtwins.co.uk'
|
||||
|
||||
@classmethod
|
||||
def getSiteExampleURLs(self):
|
||||
return "http://"+self.getSiteDomain()+"/viewstory.php?sid=1234"
|
||||
|
||||
@@ -169,7 +170,7 @@ class MerlinFicDtwinsCoUk(BaseSiteAdapter):
|
||||
|
||||
## Title
|
||||
a = soup.find('a', href=re.compile(r'viewstory.php\?sid='+self.story.getMetadata('storyId')+"$"))
|
||||
self.story.setMetadata('title',a.string)
|
||||
self.story.setMetadata('title',stripHTML(a))
|
||||
|
||||
# Find authorid and URL from... author url.
|
||||
a = soup.find('a', href=re.compile(r"viewuser.php\?uid=\d+"))
|
||||
|
||||
@@ -52,7 +52,7 @@ class MidnightwhispersCaAdapter(BaseSiteAdapter): # XXX
|
||||
|
||||
# get storyId from url--url validation guarantees query is only sid=1234
|
||||
self.story.setMetadata('storyId',self.parsedUrl.query.split('=',)[1])
|
||||
logger.debug("storyId: (%s)"%self.story.getMetadata('storyId'))
|
||||
|
||||
|
||||
# normalized story URL.
|
||||
# XXX Most sites don't have the /fanfic part. Replace all to remove it usually.
|
||||
@@ -70,6 +70,7 @@ class MidnightwhispersCaAdapter(BaseSiteAdapter): # XXX
|
||||
# The site domain. Does have www here, if it uses it.
|
||||
return 'www.midnightwhispers.ca' # XXX
|
||||
|
||||
@classmethod
|
||||
def getSiteExampleURLs(self):
|
||||
return "http://"+self.getSiteDomain()+"/viewstory.php?sid=1234"
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ class MuggleNetComAdapter(BaseSiteAdapter): # XXX
|
||||
|
||||
# get storyId from url--url validation guarantees query is only sid=1234
|
||||
self.story.setMetadata('storyId',self.parsedUrl.query.split('=',)[1])
|
||||
logger.debug("storyId: (%s)"%self.story.getMetadata('storyId'))
|
||||
|
||||
|
||||
# normalized story URL.
|
||||
self._setURL('http://' + self.getSiteDomain() + '/viewstory.php?sid='+self.story.getMetadata('storyId'))
|
||||
@@ -73,6 +73,7 @@ class MuggleNetComAdapter(BaseSiteAdapter): # XXX
|
||||
def getAcceptDomains(cls):
|
||||
return ['fanfiction.mugglenet.com','fanfic.mugglenet.com']
|
||||
|
||||
@classmethod
|
||||
def getSiteExampleURLs(self):
|
||||
return "http://"+self.getSiteDomain()+"/viewstory.php?sid=1234"
|
||||
|
||||
@@ -192,7 +193,7 @@ class MuggleNetComAdapter(BaseSiteAdapter): # XXX
|
||||
|
||||
## Title
|
||||
a = soup.find('a', href=re.compile(r'viewstory.php\?sid='+self.story.getMetadata('storyId')+"$"))
|
||||
self.story.setMetadata('title',a.string)
|
||||
self.story.setMetadata('title',stripHTML(a))
|
||||
|
||||
# Find authorid and URL from... author url.
|
||||
a = soup.find('a', href=re.compile(r"viewuser.php\?uid=\d+"))
|
||||
|
||||
@@ -48,7 +48,7 @@ class NationalLibraryNetAdapter(BaseSiteAdapter):
|
||||
|
||||
# get storyId from url--url validation guarantees query is only storyid=1234
|
||||
self.story.setMetadata('storyId',self.parsedUrl.query.split('=',)[1])
|
||||
logger.debug("storyId: (%s)"%self.story.getMetadata('storyId'))
|
||||
|
||||
|
||||
# normalized story URL.
|
||||
self._setURL('http://' + self.getSiteDomain() + '/viewstory.php?storyid='+self.story.getMetadata('storyId'))
|
||||
@@ -68,8 +68,10 @@ class NationalLibraryNetAdapter(BaseSiteAdapter):
|
||||
def getAcceptDomains(cls):
|
||||
return ['www.national-library.net','national-library.net']
|
||||
|
||||
@classmethod
|
||||
def getSiteExampleURLs(self):
|
||||
return "ONLY the stories archived on or after June 17, 2006 and that are hosted on the website: http://"+self.getSiteDomain()+"/viewstory.php?storyid=1234"
|
||||
# ONLY the stories archived on or after June 17, 2006 and that are hosted on the website:
|
||||
return "http://"+self.getSiteDomain()+"/viewstory.php?storyid=1234"
|
||||
|
||||
def getSiteURLPattern(self):
|
||||
return re.escape("http://")+"(www\.)?"+re.escape(self.getSiteDomain()+"/viewstory.php?storyid=")+r"\d+$"
|
||||
@@ -102,7 +104,7 @@ class NationalLibraryNetAdapter(BaseSiteAdapter):
|
||||
|
||||
## Title
|
||||
a = soup.find('h1')
|
||||
self.story.setMetadata('title',a.string)
|
||||
self.story.setMetadata('title',stripHTML(a))
|
||||
|
||||
# Find authorid and URL from... author url.
|
||||
a = soup.find('a', href=re.compile(r"authorresults.php\?author=\d+"))
|
||||
|
||||
@@ -48,7 +48,7 @@ class NCISFicComAdapter(BaseSiteAdapter):
|
||||
|
||||
# get storyId from url--url validation guarantees query is only storyid=1234
|
||||
self.story.setMetadata('storyId',self.parsedUrl.query.split('=',)[1])
|
||||
logger.debug("storyId: (%s)"%self.story.getMetadata('storyId'))
|
||||
|
||||
|
||||
# normalized story URL.
|
||||
self._setURL('http://' + self.getSiteDomain() + '/viewstory.php?storyid='+self.story.getMetadata('storyId'))
|
||||
@@ -68,6 +68,7 @@ class NCISFicComAdapter(BaseSiteAdapter):
|
||||
def getAcceptDomains(cls):
|
||||
return ['www.ncisfic.com','ncisfic.com']
|
||||
|
||||
@classmethod
|
||||
def getSiteExampleURLs(self):
|
||||
return "http://"+self.getSiteDomain()+"/viewstory.php?storyid=1234"
|
||||
|
||||
@@ -102,7 +103,7 @@ class NCISFicComAdapter(BaseSiteAdapter):
|
||||
|
||||
## Title
|
||||
a = soup.find('h1')
|
||||
self.story.setMetadata('title',a.string)
|
||||
self.story.setMetadata('title',stripHTML(a))
|
||||
|
||||
# Find authorid and URL from... author url.
|
||||
a = soup.find('a', href=re.compile(r"authorresults.php\?author=\d+"))
|
||||
|
||||
@@ -37,11 +37,6 @@ class NCISFictionNetAdapter(BaseSiteAdapter):
|
||||
def __init__(self, config, url):
|
||||
BaseSiteAdapter.__init__(self, config, url)
|
||||
|
||||
# ncisfiction.net blocks IPs the default user-agent. However,
|
||||
# when asked, they said it was just general anti-spam, not
|
||||
# targeted at us. That lets me do this in good conscience:
|
||||
self.opener.addheaders = [('User-agent', 'FFDL/1.6')]
|
||||
|
||||
self.decode = ["iso-8859-1",
|
||||
"Windows-1252"] # 1252 is a superset of iso-8859-1.
|
||||
# Most sites that claim to be
|
||||
@@ -53,7 +48,7 @@ class NCISFictionNetAdapter(BaseSiteAdapter):
|
||||
|
||||
# get storyId from url--url validation guarantees query is only sid=1234
|
||||
self.story.setMetadata('storyId',self.parsedUrl.query.split('=',)[1])
|
||||
logger.debug("storyId: (%s)"%self.story.getMetadata('storyId'))
|
||||
|
||||
|
||||
# normalized story URL.
|
||||
self._setURL("http://"+self.getSiteDomain()\
|
||||
@@ -79,6 +74,7 @@ class NCISFictionNetAdapter(BaseSiteAdapter):
|
||||
def getAcceptDomains(cls):
|
||||
return ['www.ncisfiction.net','www.ncisfiction.com']
|
||||
|
||||
@classmethod
|
||||
def getSiteExampleURLs(self):
|
||||
return "http://"+self.getSiteDomain()+"/story.php?stid=01234 http://"+self.getSiteDomain()+"/chapters.php?stid=1234"
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ class NetRaptorOrgAdapter(BaseSiteAdapter):
|
||||
|
||||
# get storyId from url--url validation guarantees query is only sid=1234
|
||||
self.story.setMetadata('storyId',self.parsedUrl.query.split('=',)[1])
|
||||
logger.debug("storyId: (%s)"%self.story.getMetadata('storyId'))
|
||||
|
||||
|
||||
# normalized story URL.
|
||||
self._setURL('http://' + self.getSiteDomain() + '/fanfiction/viewstory.php?sid='+self.story.getMetadata('storyId'))
|
||||
@@ -63,6 +63,7 @@ class NetRaptorOrgAdapter(BaseSiteAdapter):
|
||||
# The site domain. Does have www here, if it uses it.
|
||||
return 'netraptor.org'
|
||||
|
||||
@classmethod
|
||||
def getSiteExampleURLs(self):
|
||||
return "http://"+self.getSiteDomain()+"/fanfiction/viewstory.php?sid=1234"
|
||||
|
||||
@@ -96,7 +97,7 @@ class NetRaptorOrgAdapter(BaseSiteAdapter):
|
||||
## Title
|
||||
pagetitle = soup.find('div',{'id':'pagetitle'})
|
||||
a = pagetitle.find('a', href=re.compile(r'viewstory.php\?sid='+self.story.getMetadata('storyId')+"$"))
|
||||
self.story.setMetadata('title',a.string)
|
||||
self.story.setMetadata('title',stripHTML(a))
|
||||
|
||||
# Find authorid and URL from... author url.
|
||||
a = pagetitle.find('a', href=re.compile(r"viewuser.php\?uid=\d+"))
|
||||
|
||||
@@ -52,7 +52,7 @@ class NfaCommunityComAdapter(BaseSiteAdapter): # XXX
|
||||
|
||||
# get storyId from url--url validation guarantees query is only sid=1234
|
||||
self.story.setMetadata('storyId',self.parsedUrl.query.split('=',)[1])
|
||||
logger.debug("storyId: (%s)"%self.story.getMetadata('storyId'))
|
||||
|
||||
|
||||
# normalized story URL.
|
||||
# XXX Most sites don't have the /fanfic part. Replace all to remove it usually.
|
||||
@@ -74,6 +74,7 @@ class NfaCommunityComAdapter(BaseSiteAdapter): # XXX
|
||||
# The site domain. Does have www here, if it uses it.
|
||||
return 'nfacommunity.com' # XXX
|
||||
|
||||
@classmethod
|
||||
def getSiteExampleURLs(self):
|
||||
return "http://"+self.getSiteDomain()+"/viewstory.php?sid=1234"
|
||||
|
||||
@@ -155,7 +156,7 @@ class NfaCommunityComAdapter(BaseSiteAdapter): # XXX
|
||||
|
||||
## Title
|
||||
a = soup.find('a', href=re.compile(r'viewstory.php\?sid='+self.story.getMetadata('storyId')+"$"))
|
||||
self.story.setMetadata('title',a.string)
|
||||
self.story.setMetadata('title',stripHTML(a))
|
||||
|
||||
# Find authorid and URL from... author url.
|
||||
a = soup.find('a', href=re.compile(r"viewuser.php\?uid=\d+"))
|
||||
|
||||
@@ -48,7 +48,7 @@ class NHAMagicalWorldsUsAdapter(BaseSiteAdapter):
|
||||
|
||||
# get storyId from url--url validation guarantees query is only sid=1234
|
||||
self.story.setMetadata('storyId',self.parsedUrl.query.split('=',)[1])
|
||||
logger.debug("storyId: (%s)"%self.story.getMetadata('storyId'))
|
||||
|
||||
|
||||
|
||||
# normalized story URL.
|
||||
@@ -66,6 +66,7 @@ class NHAMagicalWorldsUsAdapter(BaseSiteAdapter):
|
||||
# The site domain. Does have www here, if it uses it.
|
||||
return 'nha.magical-worlds.us'
|
||||
|
||||
@classmethod
|
||||
def getSiteExampleURLs(self):
|
||||
return "http://"+self.getSiteDomain()+"/viewstory.php?sid=1234"
|
||||
|
||||
@@ -114,7 +115,7 @@ class NHAMagicalWorldsUsAdapter(BaseSiteAdapter):
|
||||
a = info.find('a')
|
||||
if 'viewstory.php?sid='+self.story.getMetadata('storyId') == a['href'] or \
|
||||
('viewstory.php?sid='+self.story.getMetadata('storyId')+'&') in a['href']:
|
||||
self.story.setMetadata('title',a.string)
|
||||
self.story.setMetadata('title',stripHTML(a))
|
||||
break
|
||||
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ class NickAndGregNetAdapter(BaseSiteAdapter):
|
||||
|
||||
# get storyId from url--url validation guarantees query is only sid=1234
|
||||
self.story.setMetadata('storyId',self.parsedUrl.query.split('=',)[1])
|
||||
logger.debug("storyId: (%s)"%self.story.getMetadata('storyId'))
|
||||
|
||||
|
||||
# normalized story URL.
|
||||
# XXX Most sites don't have the /fanfic part. Replace all to remove it usually.
|
||||
@@ -66,6 +66,7 @@ class NickAndGregNetAdapter(BaseSiteAdapter):
|
||||
# The site domain. Does have www here, if it uses it.
|
||||
return 'www.nickandgreg.net'
|
||||
|
||||
@classmethod
|
||||
def getSiteExampleURLs(self):
|
||||
return "http://"+self.getSiteDomain()+"/desert_archive/viewstory.php?sid=1234"
|
||||
|
||||
@@ -100,7 +101,7 @@ class NickAndGregNetAdapter(BaseSiteAdapter):
|
||||
|
||||
## Title
|
||||
a = soup.find('a', href=re.compile(r'viewstory.php\?sid='+self.story.getMetadata('storyId')+"$"))
|
||||
self.story.setMetadata('title',a.string)
|
||||
self.story.setMetadata('title',stripHTML(a))
|
||||
|
||||
# Find authorid and URL from... author url.
|
||||
a = soup.find('a', href=re.compile(r"viewuser.php\?uid=\d+"))
|
||||
|
||||
@@ -48,7 +48,7 @@ class OcclumencySycophantHexComAdapter(BaseSiteAdapter):
|
||||
|
||||
# get storyId from url--url validation guarantees query is only sid=1234
|
||||
self.story.setMetadata('storyId',self.parsedUrl.query.split('=',)[1])
|
||||
logger.debug("storyId: (%s)"%self.story.getMetadata('storyId'))
|
||||
|
||||
|
||||
|
||||
# normalized story URL.
|
||||
@@ -66,6 +66,7 @@ class OcclumencySycophantHexComAdapter(BaseSiteAdapter):
|
||||
# The site domain. Does have www here, if it uses it.
|
||||
return 'occlumency.sycophanthex.com'
|
||||
|
||||
@classmethod
|
||||
def getSiteExampleURLs(self):
|
||||
return "http://"+self.getSiteDomain()+"/viewstory.php?sid=1234"
|
||||
|
||||
@@ -157,7 +158,7 @@ class OcclumencySycophantHexComAdapter(BaseSiteAdapter):
|
||||
for info in asoup.findAll('table', {'class' : 'border'}):
|
||||
a = info.find('a', href=re.compile(r'viewstory.php\?sid='+self.story.getMetadata('storyId')+"$"))
|
||||
if a != None:
|
||||
self.story.setMetadata('title',a.text)
|
||||
self.story.setMetadata('title',stripHTML(a))
|
||||
break
|
||||
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ class OneDirectionFanfictionComAdapter(BaseSiteAdapter):
|
||||
|
||||
# get storyId from url--url validation guarantees query is only sid=1234
|
||||
self.story.setMetadata('storyId',self.parsedUrl.query.split('=',)[1])
|
||||
logger.debug("storyId: (%s)"%self.story.getMetadata('storyId'))
|
||||
|
||||
|
||||
# normalized story URL.
|
||||
self._setURL('http://' + self.getSiteDomain() + '/viewstory.php?sid='+self.story.getMetadata('storyId'))
|
||||
@@ -70,6 +70,7 @@ class OneDirectionFanfictionComAdapter(BaseSiteAdapter):
|
||||
return ['www.onedirectionfanfiction.com','onedirectionfanfiction.com']
|
||||
|
||||
|
||||
@classmethod
|
||||
def getSiteExampleURLs(self):
|
||||
return "http://"+self.getSiteDomain()+"/viewstory.php?sid=1234"
|
||||
|
||||
@@ -157,7 +158,7 @@ class OneDirectionFanfictionComAdapter(BaseSiteAdapter):
|
||||
|
||||
## Title
|
||||
a = soup.find('a', href=re.compile(r'viewstory.php\?sid='+self.story.getMetadata('storyId')+"$"))
|
||||
self.story.setMetadata('title',a.string)
|
||||
self.story.setMetadata('title',stripHTML(a))
|
||||
|
||||
# Find authorid and URL from... author url.
|
||||
a = soup.find('a', href=re.compile(r"viewuser.php\?uid=\d+"))
|
||||
|
||||
@@ -48,7 +48,7 @@ class PhoenixSongNetAdapter(BaseSiteAdapter):
|
||||
|
||||
# get storyId from url--url validation guarantees query is only sid=1234
|
||||
self.story.setMetadata('storyId',self.parsedUrl.path.split('/',)[3])
|
||||
logger.debug("storyId: (%s)"%self.story.getMetadata('storyId'))
|
||||
|
||||
|
||||
# normalized story URL.
|
||||
self._setURL('http://' + self.getSiteDomain() + '/fanfiction/story/' +self.story.getMetadata('storyId')+'/')
|
||||
@@ -65,6 +65,7 @@ class PhoenixSongNetAdapter(BaseSiteAdapter):
|
||||
# The site domain. Does have www here, if it uses it.
|
||||
return 'www.phoenixsong.net'
|
||||
|
||||
@classmethod
|
||||
def getSiteExampleURLs(self):
|
||||
return "http://"+self.getSiteDomain()+"/fanfiction/story/1234/"
|
||||
|
||||
@@ -135,7 +136,7 @@ class PhoenixSongNetAdapter(BaseSiteAdapter):
|
||||
## Title
|
||||
b = soup.find('div', {'id' : 'nav25'})
|
||||
a = b.find('a', href=re.compile(r'fanfiction/story/'+self.story.getMetadata('storyId')+"/$"))
|
||||
self.story.setMetadata('title',a.string)
|
||||
self.story.setMetadata('title',stripHTML(a))
|
||||
|
||||
# Find authorid and URL from... author url. /fanfiction/stories.php?psid=125
|
||||
a = b.find('a', href=re.compile(r"/fanfiction/stories.php\?psid=\d+"))
|
||||
|
||||
@@ -48,7 +48,7 @@ class PommeDeSangComAdapter(BaseSiteAdapter):
|
||||
|
||||
# get storyId from url--url validation guarantees query is only sid=1234
|
||||
self.story.setMetadata('storyId',self.parsedUrl.query.split('=',)[1])
|
||||
logger.debug("storyId: (%s)"%self.story.getMetadata('storyId'))
|
||||
|
||||
|
||||
# pommedesang.com has two 'sections', shown in URL as
|
||||
# 'efiction' and 'sds' that change how things should be
|
||||
@@ -75,6 +75,7 @@ class PommeDeSangComAdapter(BaseSiteAdapter):
|
||||
# The site domain. Does have www here, if it uses it.
|
||||
return 'pommedesang.com'
|
||||
|
||||
@classmethod
|
||||
def getSiteExampleURLs(self):
|
||||
return "http://"+self.getSiteDomain()+"/efiction/viewstory.php?sid=1234 http://"+self.getSiteDomain()+"/sds/viewstory.php?sid=1234"
|
||||
|
||||
@@ -179,7 +180,7 @@ class PommeDeSangComAdapter(BaseSiteAdapter):
|
||||
|
||||
## Title
|
||||
a = soup.find('a', href=re.compile('viewstory.php\?sid=\d+'))
|
||||
self.story.setMetadata('title',a.string)
|
||||
self.story.setMetadata('title',stripHTML(a))
|
||||
|
||||
# Find authorid and URL from... author url.
|
||||
a = soup.find('a', href=re.compile(r"viewuser.php\?uid=\d+"))
|
||||
|
||||
@@ -48,8 +48,7 @@ class PonyFictionArchiveNetAdapter(BaseSiteAdapter):
|
||||
|
||||
# get storyId from url--url validation guarantees query is only sid=1234
|
||||
self.story.setMetadata('storyId',self.parsedUrl.query.split('=',)[1])
|
||||
logger.debug("storyId: (%s)"%self.story.getMetadata('storyId'))
|
||||
logger.info(self.parsedUrl.netloc)
|
||||
|
||||
# normalized story URL.
|
||||
if "explicit" in self.parsedUrl.netloc:
|
||||
self._setURL('http://explicit.' + self.getSiteDomain() + '/viewstory.php?sid='+self.story.getMetadata('storyId'))
|
||||
@@ -70,8 +69,9 @@ class PonyFictionArchiveNetAdapter(BaseSiteAdapter):
|
||||
def getAcceptDomains(cls):
|
||||
return ['www.ponyfictionarchive.net','ponyfictionarchive.net','explicit.ponyfictionarchive.net']
|
||||
|
||||
@classmethod
|
||||
def getSiteExampleURLs(self):
|
||||
return "http://"+self.getSiteDomain()+"/viewstory.php?sid=1234"
|
||||
return "http://"+self.getSiteDomain()+"/viewstory.php?sid=1234 http://explicit."+self.getSiteDomain()+"/viewstory.php?sid=1234"
|
||||
|
||||
def getSiteURLPattern(self):
|
||||
return re.escape("http://")+"(www\.|explicit\.)?"+re.escape(self.getSiteDomain()+"/viewstory.php?sid=")+r"\d+$"
|
||||
@@ -136,7 +136,7 @@ class PonyFictionArchiveNetAdapter(BaseSiteAdapter):
|
||||
|
||||
## Title
|
||||
a = soup.find('a', href=re.compile(r'viewstory.php\?sid='+self.story.getMetadata('storyId')+"$"))
|
||||
self.story.setMetadata('title',a.string)
|
||||
self.story.setMetadata('title',stripHTML(a))
|
||||
|
||||
# Find authorid and URL from... author url.
|
||||
a = soup.find('a', href=re.compile(r"viewuser.php\?uid=\d+"))
|
||||
|
||||
@@ -55,7 +55,7 @@ class PortkeyOrgAdapter(BaseSiteAdapter): # XXX
|
||||
|
||||
# get storyId from url--url validation guarantees query is only sid=1234
|
||||
self.story.setMetadata('storyId',self.parsedUrl.path.split('/',)[2])
|
||||
logger.debug("storyId: (%s)"%self.story.getMetadata('storyId'))
|
||||
|
||||
|
||||
# normalized story URL.
|
||||
self._setURL('http://' + self.getSiteDomain() + '/story/'+self.story.getMetadata('storyId'))
|
||||
@@ -72,6 +72,7 @@ class PortkeyOrgAdapter(BaseSiteAdapter): # XXX
|
||||
# The site domain. Does have www here, if it uses it.
|
||||
return 'fanfiction.portkey.org' # XXX
|
||||
|
||||
@classmethod
|
||||
def getSiteExampleURLs(self):
|
||||
return "http://"+self.getSiteDomain()+"/story/1234"
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ class PotionsAndSnitchesNetSiteAdapter(BaseSiteAdapter):
|
||||
|
||||
# get storyId from url--url validation guarantees query is only sid=1234
|
||||
self.story.setMetadata('storyId',self.parsedUrl.query.split('=',)[1])
|
||||
logger.debug("storyId: (%s)"%self.story.getMetadata('storyId'))
|
||||
|
||||
|
||||
# normalized story URL.
|
||||
self._setURL('http://' + self.getSiteDomain() + '/fanfiction/viewstory.php?sid='+self.story.getMetadata('storyId'))
|
||||
@@ -55,8 +55,9 @@ class PotionsAndSnitchesNetSiteAdapter(BaseSiteAdapter):
|
||||
def getAcceptDomains(cls):
|
||||
return ['www.potionsandsnitches.net','potionsandsnitches.net']
|
||||
|
||||
@classmethod
|
||||
def getSiteExampleURLs(self):
|
||||
return "http://www.potionsandsnitches.net/fanfiction/viewstory.php?sid=1234 http://potionsandsnitches.net/fanfiction/viewstory.php?sid=5678"
|
||||
return "http://www.potionsandsnitches.net/fanfiction/viewstory.php?sid=1234"
|
||||
|
||||
def getSiteURLPattern(self):
|
||||
return re.escape("http://")+r"(www\.)?"+re.escape("potionsandsnitches.net/fanfiction/viewstory.php?sid=")+r"\d+$"
|
||||
@@ -82,7 +83,7 @@ class PotionsAndSnitchesNetSiteAdapter(BaseSiteAdapter):
|
||||
|
||||
## Title
|
||||
a = soup.find('a', href=re.compile(r'viewstory.php\?sid='+self.story.getMetadata('storyId')+"$"))
|
||||
self.story.setMetadata('title',a.string)
|
||||
self.story.setMetadata('title',stripHTML(a))
|
||||
|
||||
# Find authorid and URL from... author url.
|
||||
a = soup.find('a', href=re.compile(r"viewuser.php\?uid=\d+"))
|
||||
|
||||
@@ -54,7 +54,7 @@ class PotterFicsComAdapter(BaseSiteAdapter):
|
||||
m = re.match(self.getSiteURLPattern(),url)
|
||||
if m:
|
||||
self.story.setMetadata('storyId',m.group('id'))
|
||||
logger.debug("storyId: (%s)"%self.story.getMetadata('storyId'))
|
||||
|
||||
# normalized story URL. gets rid of chapter if there, left with chapter index URL
|
||||
nurl = "http://"+self.getSiteDomain()+"/historias/"+self.story.getMetadata('storyId')
|
||||
self._setURL(nurl)
|
||||
@@ -62,7 +62,7 @@ class PotterFicsComAdapter(BaseSiteAdapter):
|
||||
raise exceptions.InvalidStoryURL(url,
|
||||
self.getSiteDomain(),
|
||||
self.getSiteExampleURLs())
|
||||
logger.debug("storyId: (%s)"%self.story.getMetadata('storyId'))
|
||||
|
||||
|
||||
# Each adapter needs to have a unique site abbreviation.
|
||||
self.story.setMetadata('siteabbrev','potficscom')
|
||||
@@ -72,13 +72,9 @@ class PotterFicsComAdapter(BaseSiteAdapter):
|
||||
# The site domain. Does have www here, if it uses it.
|
||||
return 'www.potterfics.com'
|
||||
|
||||
@classmethod
|
||||
def getSiteExampleURLs(self):
|
||||
return \
|
||||
"http://www.potterfics.com/historias/127583 "\
|
||||
"http://www.potterfics.com/historias/127583/capitulo-1 "\
|
||||
"http://www.potterfics.com/historias/127583/capitulo-4 "\
|
||||
"http://www.potterfics.com/historias/92810 "\
|
||||
"http://www.potterfics.com/historias/111194"
|
||||
return "http://www.potterfics.com/historias/12345 http://www.potterfics.com/historias/12345/capitulo-1 "
|
||||
|
||||
def getSiteURLPattern(self):
|
||||
#http://www.potterfics.com/historias/127583
|
||||
@@ -151,7 +147,7 @@ class PotterFicsComAdapter(BaseSiteAdapter):
|
||||
#find first metadata block
|
||||
mb = cell.div.findNextSibling('div')
|
||||
#Get meta...
|
||||
self.story.setMetadata('title', mb.b.string)
|
||||
self.story.setMetadata('title', stripHTML(mb.b))
|
||||
#strip out brackets on rating
|
||||
self.story.setMetadata('rating', mb.span.string[1:-1])
|
||||
#Completion status is denoted by the presence of this image:
|
||||
|
||||
@@ -48,7 +48,7 @@ class PotterHeadsAnonymousComAdapter(BaseSiteAdapter):
|
||||
|
||||
# get storyId from url--url validation guarantees query is only sid=1234
|
||||
self.story.setMetadata('storyId',self.parsedUrl.query.split('=',)[1])
|
||||
logger.debug("storyId: (%s)"%self.story.getMetadata('storyId'))
|
||||
|
||||
|
||||
# normalized story URL.
|
||||
self._setURL('http://' + self.getSiteDomain() + '/viewstory.php?sid='+self.story.getMetadata('storyId'))
|
||||
@@ -65,6 +65,7 @@ class PotterHeadsAnonymousComAdapter(BaseSiteAdapter):
|
||||
# The site domain. Does have www here, if it uses it.
|
||||
return 'fanfic.potterheadsanonymous.com'
|
||||
|
||||
@classmethod
|
||||
def getSiteExampleURLs(self):
|
||||
return "http://"+self.getSiteDomain()+"/viewstory.php?sid=1234"
|
||||
|
||||
@@ -180,7 +181,7 @@ class PotterHeadsAnonymousComAdapter(BaseSiteAdapter):
|
||||
|
||||
## Title
|
||||
a = pagetitle.find('a', href=re.compile(r'viewstory.php\?sid='+self.story.getMetadata('storyId')+"$"))
|
||||
self.story.setMetadata('title',a.string)
|
||||
self.story.setMetadata('title',stripHTML(a))
|
||||
|
||||
# Find authorid and URL from... author url.
|
||||
a = pagetitle.find('a', href=re.compile(r"viewuser.php\?uid=\d+"))
|
||||
|
||||
@@ -48,7 +48,7 @@ class PretenderCenterComAdapter(BaseSiteAdapter):
|
||||
|
||||
# get storyId from url--url validation guarantees query is only sid=1234
|
||||
self.story.setMetadata('storyId',self.parsedUrl.query.split('=',)[1])
|
||||
logger.debug("storyId: (%s)"%self.story.getMetadata('storyId'))
|
||||
|
||||
|
||||
# normalized story URL.
|
||||
self._setURL('http://' + self.getSiteDomain() + '/missingpieces/viewstory.php?sid='+self.story.getMetadata('storyId'))
|
||||
@@ -69,6 +69,7 @@ class PretenderCenterComAdapter(BaseSiteAdapter):
|
||||
def getAcceptDomains(cls):
|
||||
return ['www.pretendercentre.com','pretendercentre.com']
|
||||
|
||||
@classmethod
|
||||
def getSiteExampleURLs(self):
|
||||
return "http://"+self.getSiteDomain()+"/missingpieces/viewstory.php?sid=1234"
|
||||
|
||||
@@ -133,7 +134,7 @@ class PretenderCenterComAdapter(BaseSiteAdapter):
|
||||
|
||||
## Title
|
||||
a = soup.find('a', href=re.compile(r'viewstory.php\?sid='+self.story.getMetadata('storyId')+"$"))
|
||||
self.story.setMetadata('title',a.text)
|
||||
self.story.setMetadata('title',stripHTML(a))
|
||||
|
||||
# Find authorid and URL from... author url.
|
||||
a = soup.find('a', href=re.compile(r"viewuser.php\?uid=\d+"))
|
||||
|
||||
@@ -48,7 +48,7 @@ class PsychFicComAdapter(BaseSiteAdapter):
|
||||
|
||||
# get storyId from url--url validation guarantees query is only sid=1234
|
||||
self.story.setMetadata('storyId',self.parsedUrl.query.split('=',)[1])
|
||||
logger.debug("storyId: (%s)"%self.story.getMetadata('storyId'))
|
||||
|
||||
|
||||
# normalized story URL.
|
||||
self._setURL('http://' + self.getSiteDomain() + '/viewstory.php?sid='+self.story.getMetadata('storyId'))
|
||||
@@ -65,6 +65,7 @@ class PsychFicComAdapter(BaseSiteAdapter):
|
||||
# The site domain. Does have www here, if it uses it.
|
||||
return 'www.psychfic.com'
|
||||
|
||||
@classmethod
|
||||
def getSiteExampleURLs(self):
|
||||
return "http://"+self.getSiteDomain()+"/viewstory.php?sid=1234"
|
||||
|
||||
@@ -129,7 +130,7 @@ class PsychFicComAdapter(BaseSiteAdapter):
|
||||
|
||||
## Title
|
||||
a = soup.find('a', href=re.compile(r'viewstory.php\?sid='+self.story.getMetadata('storyId')+"$"))
|
||||
self.story.setMetadata('title',a.string)
|
||||
self.story.setMetadata('title',stripHTML(a))
|
||||
|
||||
# Find authorid and URL from... author url.
|
||||
a = soup.find('a', href=re.compile(r"viewuser.php\?uid=\d+"))
|
||||
|
||||
@@ -48,7 +48,7 @@ class QafFicComAdapter(BaseSiteAdapter):
|
||||
|
||||
# get storyId from url--url validation guarantees query is only sid=1234
|
||||
self.story.setMetadata('storyId',self.parsedUrl.query.split('=',)[1])
|
||||
logger.debug("storyId: (%s)"%self.story.getMetadata('storyId'))
|
||||
|
||||
|
||||
# normalized story URL.
|
||||
self._setURL('http://' + self.getSiteDomain() + '/atp/viewstory.php?sid='+self.story.getMetadata('storyId'))
|
||||
@@ -65,6 +65,7 @@ class QafFicComAdapter(BaseSiteAdapter):
|
||||
# The site domain. Does have www here, if it uses it.
|
||||
return 'www.qaf-fic.com'
|
||||
|
||||
@classmethod
|
||||
def getSiteExampleURLs(self):
|
||||
return "http://"+self.getSiteDomain()+"/atp/viewstory.php?sid=1234"
|
||||
|
||||
@@ -137,7 +138,7 @@ class QafFicComAdapter(BaseSiteAdapter):
|
||||
self.story.setMetadata('author',aut.string)
|
||||
aut.extract()
|
||||
|
||||
self.story.setMetadata('title',a.string[:(len(a.string)-3)])
|
||||
self.story.setMetadata('title',stripHTML(a)[:(len(a.string)-3)])
|
||||
|
||||
# Find the chapters:
|
||||
chapters=soup.find('select')
|
||||
|
||||
@@ -52,10 +52,9 @@ class RestrictedSectionOrgSiteAdapter(BaseSiteAdapter):
|
||||
m = re.match(self.getSiteURLPattern(),url)
|
||||
if m:
|
||||
self.story.setMetadata('storyId',m.group('id'))
|
||||
logger.debug("storyId: (%s)"%self.story.getMetadata('storyId'))
|
||||
|
||||
# normalized story URL.
|
||||
self._setURL('http://' + self.getSiteDomain() + '/' + m.group('filestory') + '.php?' + m.group('filestory') + '=' + self.story.getMetadata('storyId'))
|
||||
logger.debug("storyUrl: (%s)"%self.story.getMetadata('storyUrl'))
|
||||
else:
|
||||
raise exceptions.InvalidStoryURL(url,
|
||||
self.getSiteDomain(),
|
||||
@@ -70,6 +69,7 @@ class RestrictedSectionOrgSiteAdapter(BaseSiteAdapter):
|
||||
def getSiteDomain():
|
||||
return 'www.restrictedsection.org'
|
||||
|
||||
@classmethod
|
||||
def getSiteExampleURLs(self):
|
||||
return "http://"+self.getSiteDomain()+"/story.php?story=1234 http://"+self.getSiteDomain()+"/file.php?file=1234"
|
||||
|
||||
@@ -126,10 +126,12 @@ class RestrictedSectionOrgSiteAdapter(BaseSiteAdapter):
|
||||
|
||||
self.story.setMetadata('authorId',ahref.split('=')[1])
|
||||
self.story.setMetadata('authorUrl','http://'+self.host+'/'+ahref)
|
||||
self.story.setMetadata('author',a.string)
|
||||
self.story.setMetadata('author',stripHTML(a))
|
||||
|
||||
# title, remove byauthorname.
|
||||
self.story.setMetadata('title',h2.text[:h2.text.index("by"+a.string)])
|
||||
auth=stripHTML(a)
|
||||
title=stripHTML(h2)
|
||||
self.story.setMetadata('title',title[:title.index(" by "+auth)])
|
||||
|
||||
dates = soup.findAll('span', {'class':'date'})
|
||||
if dates: # only for multi-chapter
|
||||
|
||||
@@ -48,7 +48,7 @@ class SamDeanArchiveNuAdapter(BaseSiteAdapter):
|
||||
|
||||
# get storyId from url--url validation guarantees query is only sid=1234
|
||||
self.story.setMetadata('storyId',self.parsedUrl.query.split('=',)[1])
|
||||
logger.debug("storyId: (%s)"%self.story.getMetadata('storyId'))
|
||||
|
||||
|
||||
# normalized story URL.
|
||||
self._setURL('http://' + self.getSiteDomain() + '/viewstory.php?sid='+self.story.getMetadata('storyId'))
|
||||
@@ -69,6 +69,7 @@ class SamDeanArchiveNuAdapter(BaseSiteAdapter):
|
||||
def getAcceptDomains(cls):
|
||||
return ['www.samdean.archive.nu','samdean.archive.nu']
|
||||
|
||||
@classmethod
|
||||
def getSiteExampleURLs(self):
|
||||
return "http://"+self.getSiteDomain()+"/viewstory.php?sid=1234"
|
||||
|
||||
@@ -109,7 +110,7 @@ class SamDeanArchiveNuAdapter(BaseSiteAdapter):
|
||||
self.story.setMetadata('author',aut.string)
|
||||
aut.extract()
|
||||
|
||||
self.story.setMetadata('title',a.string[:(len(a.string)-3)])
|
||||
self.story.setMetadata('title',stripHTML(a)[:(len(stripHTML(a))-3)])
|
||||
|
||||
# Find the chapters:
|
||||
chapters=soup.find('select')
|
||||
|
||||
@@ -48,7 +48,7 @@ class ScarHeadNetAdapter(BaseSiteAdapter):
|
||||
|
||||
# get storyId from url--url validation guarantees query is only sid=1234
|
||||
self.story.setMetadata('storyId',self.parsedUrl.query.split('=',)[1])
|
||||
logger.debug("storyId: (%s)"%self.story.getMetadata('storyId'))
|
||||
|
||||
|
||||
# normalized story URL.
|
||||
self._setURL('http://' + self.getSiteDomain() + '/viewstory.php?sid='+self.story.getMetadata('storyId'))
|
||||
@@ -65,6 +65,7 @@ class ScarHeadNetAdapter(BaseSiteAdapter):
|
||||
# The site domain. Does have www here, if it uses it.
|
||||
return 'scarhead.net'
|
||||
|
||||
@classmethod
|
||||
def getSiteExampleURLs(self):
|
||||
return "http://"+self.getSiteDomain()+"/viewstory.php?sid=1234"
|
||||
|
||||
@@ -180,7 +181,7 @@ class ScarHeadNetAdapter(BaseSiteAdapter):
|
||||
|
||||
## Title
|
||||
a = pagetitle.find('a', href=re.compile(r'viewstory.php\?sid='+self.story.getMetadata('storyId')+"$"))
|
||||
self.story.setMetadata('title',a.string)
|
||||
self.story.setMetadata('title',stripHTML(a))
|
||||
|
||||
# Find authorid and URL from... author url.
|
||||
a = pagetitle.find('a', href=re.compile(r"viewuser.php\?uid=\d+"))
|
||||
|
||||
@@ -48,7 +48,7 @@ class ScarvesAndCoffeeNetAdapter(BaseSiteAdapter):
|
||||
|
||||
# get storyId from url--url validation guarantees query is only sid=1234
|
||||
self.story.setMetadata('storyId',self.parsedUrl.query.split('=',)[1])
|
||||
logger.debug("storyId: (%s)"%self.story.getMetadata('storyId'))
|
||||
|
||||
|
||||
# normalized story URL.
|
||||
self._setURL('http://' + self.getSiteDomain() + '/viewstory.php?sid='+self.story.getMetadata('storyId'))
|
||||
@@ -65,6 +65,7 @@ class ScarvesAndCoffeeNetAdapter(BaseSiteAdapter):
|
||||
# The site domain. Does have www here, if it uses it.
|
||||
return 'www.scarvesandcoffee.net'
|
||||
|
||||
@classmethod
|
||||
def getSiteExampleURLs(self):
|
||||
return "http://"+self.getSiteDomain()+"/viewstory.php?sid=1234"
|
||||
|
||||
@@ -138,7 +139,7 @@ class ScarvesAndCoffeeNetAdapter(BaseSiteAdapter):
|
||||
|
||||
## Title
|
||||
a = soup.find('a', href=re.compile(r'viewstory.php\?sid='+self.story.getMetadata('storyId')+"$"))
|
||||
self.story.setMetadata('title',a.string)
|
||||
self.story.setMetadata('title',stripHTML(a))
|
||||
|
||||
# Find authorid and URL from... author url.
|
||||
a = soup.find('div',{"id":"pagetitle"}).find('a', href=re.compile(r"viewuser.php\?uid=\d+"))
|
||||
|
||||
@@ -48,7 +48,7 @@ class SG1HeliopolisComAdapter(BaseSiteAdapter):
|
||||
|
||||
# get storyId from url--url validation guarantees query is only sid=1234
|
||||
self.story.setMetadata('storyId',self.parsedUrl.query.split('=',)[1])
|
||||
logger.debug("storyId: (%s)"%self.story.getMetadata('storyId'))
|
||||
|
||||
self.section=self.parsedUrl.path.split('/',)[1]
|
||||
|
||||
# normalized story URL.
|
||||
@@ -74,6 +74,7 @@ class SG1HeliopolisComAdapter(BaseSiteAdapter):
|
||||
# The site domain. Does have www here, if it uses it.
|
||||
return 'sg1-heliopolis.com'
|
||||
|
||||
@classmethod
|
||||
def getSiteExampleURLs(self):
|
||||
return "http://"+self.getSiteDomain()+"/archive/viewstory.php?sid=1234 http://"+self.getSiteDomain()+"/adult/viewstory.php?sid=1234 http://"+self.getSiteDomain()+"/atlantis/viewstory.php?sid=1234"
|
||||
|
||||
@@ -139,7 +140,7 @@ class SG1HeliopolisComAdapter(BaseSiteAdapter):
|
||||
|
||||
## Title
|
||||
a = soup.find('a', href=re.compile(r'viewstory.php\?sid='+self.story.getMetadata('storyId')+"$"))
|
||||
self.story.setMetadata('title',a.string)
|
||||
self.story.setMetadata('title',stripHTML(a))
|
||||
|
||||
# Find authorid and URL from... author url.
|
||||
a = soup.find('a', href=re.compile(r"viewuser.php\?uid=\d+"))
|
||||
|
||||
@@ -48,7 +48,7 @@ class SimplyUndeniableComAdapter(BaseSiteAdapter):
|
||||
|
||||
# get storyId from url--url validation guarantees query is only sid=1234
|
||||
self.story.setMetadata('storyId',self.parsedUrl.query.split('=',)[1])
|
||||
logger.debug("storyId: (%s)"%self.story.getMetadata('storyId'))
|
||||
|
||||
|
||||
# normalized story URL.
|
||||
self._setURL('http://' + self.getSiteDomain() + '/viewstory.php?sid='+self.story.getMetadata('storyId'))
|
||||
@@ -65,6 +65,7 @@ class SimplyUndeniableComAdapter(BaseSiteAdapter):
|
||||
# The site domain. Does have www here, if it uses it.
|
||||
return 'www.simplyundeniable.com'
|
||||
|
||||
@classmethod
|
||||
def getSiteExampleURLs(self):
|
||||
return "http://"+self.getSiteDomain()+"/viewstory.php?sid=1234"
|
||||
|
||||
@@ -142,7 +143,7 @@ class SimplyUndeniableComAdapter(BaseSiteAdapter):
|
||||
|
||||
## Title
|
||||
a = soup.find('h1')
|
||||
self.story.setMetadata('title',a.text)
|
||||
self.story.setMetadata('title',stripHTML(a))
|
||||
|
||||
# Find authorid and URL from... author url.
|
||||
a = soup.find('a', href=re.compile(r"viewuser.php\?uid=\d+"))
|
||||
@@ -154,7 +155,7 @@ class SimplyUndeniableComAdapter(BaseSiteAdapter):
|
||||
for info in asoup.findAll('table', {'cellpadding' : '5'}):
|
||||
a = info.find('a', href=re.compile(r'viewstory.php\?sid='+self.story.getMetadata('storyId')+"$"))
|
||||
if a != None:
|
||||
self.story.setMetadata('title',a.string)
|
||||
self.story.setMetadata('title',stripHTML(a))
|
||||
break
|
||||
|
||||
# Find the chapters:
|
||||
|
||||
@@ -48,7 +48,7 @@ class SinfulDesireOrgAdapter(BaseSiteAdapter):
|
||||
|
||||
# get storyId from url--url validation guarantees query is only sid=1234
|
||||
self.story.setMetadata('storyId',self.parsedUrl.query.split('=',)[1])
|
||||
logger.debug("storyId: (%s)"%self.story.getMetadata('storyId'))
|
||||
|
||||
|
||||
# normalized story URL.
|
||||
self._setURL('http://' + self.getSiteDomain() + '/archive/viewstory.php?sid='+self.story.getMetadata('storyId'))
|
||||
@@ -65,6 +65,7 @@ class SinfulDesireOrgAdapter(BaseSiteAdapter):
|
||||
# The site domain. Does have www here, if it uses it.
|
||||
return 'www.sinful-desire.org'
|
||||
|
||||
@classmethod
|
||||
def getSiteExampleURLs(self):
|
||||
return "http://"+self.getSiteDomain()+"/archive/viewstory.php?sid=1234"
|
||||
|
||||
@@ -129,7 +130,7 @@ class SinfulDesireOrgAdapter(BaseSiteAdapter):
|
||||
|
||||
## Title
|
||||
a = soup.find('a', href=re.compile(r'viewstory.php\?sid='+self.story.getMetadata('storyId')+"$"))
|
||||
self.story.setMetadata('title',a.string)
|
||||
self.story.setMetadata('title',stripHTML(a))
|
||||
|
||||
# Find authorid and URL from... author url.
|
||||
a = soup.find('a', href=re.compile(r"viewuser.php\?uid=\d+"))
|
||||
|
||||
@@ -49,7 +49,7 @@ class SiyeCoUkAdapter(BaseSiteAdapter): # XXX
|
||||
|
||||
# get storyId from url--url validation guarantees query is only sid=1234
|
||||
self.story.setMetadata('storyId',self.parsedUrl.query.split('=',)[1])
|
||||
logger.debug("storyId: (%s)"%self.story.getMetadata('storyId'))
|
||||
|
||||
|
||||
# normalized story URL.
|
||||
self._setURL('http://' + self.getSiteDomain() + '/siye/viewstory.php?sid='+self.story.getMetadata('storyId'))
|
||||
@@ -70,6 +70,7 @@ class SiyeCoUkAdapter(BaseSiteAdapter): # XXX
|
||||
def getAcceptDomains(cls):
|
||||
return ['www.siye.co.uk','siye.co.uk']
|
||||
|
||||
@classmethod
|
||||
def getSiteExampleURLs(self):
|
||||
return "http://"+self.getSiteDomain()+"/siye/viewstory.php?sid=1234"
|
||||
|
||||
|
||||
@@ -59,7 +59,7 @@ class SquidgeOrgPejaAdapter(BaseSiteAdapter):
|
||||
|
||||
# get storyId from url--url validation guarantees query is only sid=1234
|
||||
self.story.setMetadata('storyId',self.parsedUrl.query.split('=',)[1])
|
||||
logger.debug("storyId: (%s)"%self.story.getMetadata('storyId'))
|
||||
|
||||
|
||||
# normalized story URL.
|
||||
self._setURL('http://' + self.getSiteDomain() + '/peja/cgi-bin/viewstory.php?sid='+self.story.getMetadata('storyId'))
|
||||
@@ -81,6 +81,7 @@ class SquidgeOrgPejaAdapter(BaseSiteAdapter):
|
||||
# The config section name. Only override if != site domain.
|
||||
return cls.getSiteDomain()+'/peja'
|
||||
|
||||
@classmethod
|
||||
def getSiteExampleURLs(self):
|
||||
return "http://"+self.getSiteDomain()+"/peja/cgi-bin/viewstory.php?sid=1234"
|
||||
|
||||
@@ -121,7 +122,7 @@ class SquidgeOrgPejaAdapter(BaseSiteAdapter):
|
||||
# formating, so it's a little ugly.
|
||||
|
||||
title = authorSoup.find('a',{'href':'viewstory.php?sid='+self.story.getMetadata('storyId')})
|
||||
self.story.setMetadata('title',title.string)
|
||||
self.story.setMetadata('title',stripHTML(title))
|
||||
titleblock=title.parent.parent
|
||||
|
||||
chapterselect=soup.find('select',{'name':'chapter'})
|
||||
|
||||
@@ -48,7 +48,7 @@ class StargateAtlantisOrgAdapter(BaseSiteAdapter):
|
||||
|
||||
# get storyId from url--url validation guarantees query is only sid=1234
|
||||
self.story.setMetadata('storyId',self.parsedUrl.query.split('=',)[1])
|
||||
logger.debug("storyId: (%s)"%self.story.getMetadata('storyId'))
|
||||
|
||||
|
||||
# normalized story URL.
|
||||
self._setURL('http://' + self.getSiteDomain() + '/fanfics/viewstory.php?sid='+self.story.getMetadata('storyId'))
|
||||
@@ -65,6 +65,7 @@ class StargateAtlantisOrgAdapter(BaseSiteAdapter):
|
||||
# The site domain. Does have www here, if it uses it.
|
||||
return 'stargate-atlantis.org'
|
||||
|
||||
@classmethod
|
||||
def getSiteExampleURLs(self):
|
||||
return "http://"+self.getSiteDomain()+"/fanfics/viewstory.php?sid=1234"
|
||||
|
||||
@@ -105,7 +106,7 @@ class StargateAtlantisOrgAdapter(BaseSiteAdapter):
|
||||
self.story.setMetadata('author',aut.string)
|
||||
aut.extract()
|
||||
|
||||
self.story.setMetadata('title',a.string[:(len(a.string)-3)])
|
||||
self.story.setMetadata('title',stripHTML(a)[:(len(stripHTML(a))-3)])
|
||||
|
||||
# Find the chapters:
|
||||
chapters=soup.findAll('div', {'class' : 'content'})
|
||||
|
||||
@@ -48,7 +48,7 @@ class StoriesOfArdaComAdapter(BaseSiteAdapter):
|
||||
|
||||
# get storyId from url--url validation guarantees query is only sid=1234
|
||||
self.story.setMetadata('storyId',self.parsedUrl.query.split('=',)[1])
|
||||
logger.debug("storyId: (%s)"%self.story.getMetadata('storyId'))
|
||||
|
||||
|
||||
# normalized story URL.
|
||||
self._setURL('http://' + self.getSiteDomain() + '/chapterlistview.asp?SID='+self.story.getMetadata('storyId'))
|
||||
@@ -65,6 +65,7 @@ class StoriesOfArdaComAdapter(BaseSiteAdapter):
|
||||
# The site domain. Does have www here, if it uses it.
|
||||
return 'www.storiesofarda.com'
|
||||
|
||||
@classmethod
|
||||
def getSiteExampleURLs(self):
|
||||
return "http://"+self.getSiteDomain()+"/chapterlistview.asp?SID=1234"
|
||||
|
||||
@@ -103,7 +104,7 @@ class StoriesOfArdaComAdapter(BaseSiteAdapter):
|
||||
asoup = bs.BeautifulSoup(self._fetchUrl(self.story.getMetadata('authorUrl')))
|
||||
|
||||
a.find('em').extract()
|
||||
self.story.setMetadata('title',a.text)
|
||||
self.story.setMetadata('title',stripHTML(a))
|
||||
|
||||
# Find the chapters: chapterview.asp?sid=7000&cid=30919
|
||||
chapters=soup.findAll('a', href=re.compile(r'chapterview.asp\?sid='+self.story.getMetadata('storyId')+"&cid=\d+$"))
|
||||
@@ -136,8 +137,20 @@ class StoriesOfArdaComAdapter(BaseSiteAdapter):
|
||||
|
||||
logger.debug('Getting chapter text from: %s' % url)
|
||||
|
||||
soup = bs.BeautifulStoneSoup(self._fetchUrl(url),
|
||||
if self.getConfig('is_adult'):
|
||||
params = {'confirmAge':'1'}
|
||||
data = self._postUrl(url,params)
|
||||
else:
|
||||
data = self._fetchUrl(url)
|
||||
|
||||
data = data[data.index('<table width="90%" align="center">'):]
|
||||
data.replace("<body","<notbody").replace("<BODY","<NOTBODY")
|
||||
|
||||
soup = bs.BeautifulStoneSoup(data,
|
||||
selfClosingTags=('br','hr')) # otherwise soup eats the br/hr tags.
|
||||
|
||||
if "Please indicate that you are an adult by selecting the appropriate choice below" in data:
|
||||
raise exceptions.FailedToDownload("Chapter requires you be an adult. Set is_adult in personal.ini (chapter url:%s)" % url)
|
||||
|
||||
div = soup.find('table', {'width' : '90%'}).find('td')
|
||||
div.name='div'
|
||||
|
||||
@@ -44,7 +44,7 @@ class TenhawkPresentsComSiteAdapter(BaseSiteAdapter):
|
||||
|
||||
# get storyId from url--url validation guarantees query is only sid=1234
|
||||
self.story.setMetadata('storyId',self.parsedUrl.query.split('=',)[1])
|
||||
logger.debug("storyId: (%s)"%self.story.getMetadata('storyId'))
|
||||
|
||||
|
||||
# normalized story URL.
|
||||
self._setURL('http://' + self.getSiteDomain() + '/viewstory.php?sid='+self.story.getMetadata('storyId'))
|
||||
@@ -55,6 +55,7 @@ class TenhawkPresentsComSiteAdapter(BaseSiteAdapter):
|
||||
def getSiteDomain():
|
||||
return 'fanfiction.tenhawkpresents.com'
|
||||
|
||||
@classmethod
|
||||
def getSiteExampleURLs(self):
|
||||
return "http://"+self.getSiteDomain()+"/viewstory.php?sid=1234"
|
||||
|
||||
@@ -132,7 +133,7 @@ class TenhawkPresentsComSiteAdapter(BaseSiteAdapter):
|
||||
|
||||
## Title
|
||||
a = soup.find('a', href=re.compile(r'viewstory.php\?sid='+self.story.getMetadata('storyId')))
|
||||
self.story.setMetadata('title',a.string)
|
||||
self.story.setMetadata('title',stripHTML(a))
|
||||
|
||||
# Find authorid and URL from... author url.
|
||||
a = soup.find('a', href=re.compile(r"viewuser.php\?uid=\d+"))
|
||||
|
||||
@@ -40,6 +40,7 @@ class TestSiteAdapter(BaseSiteAdapter):
|
||||
def getSiteDomain():
|
||||
return 'test1.com'
|
||||
|
||||
@classmethod
|
||||
def getSiteExampleURLs(self):
|
||||
return "http://"+self.getSiteDomain()+"?sid=1234"
|
||||
|
||||
@@ -140,14 +141,66 @@ Some more longer description. "I suck at summaries!" "Better than it sounds!"
|
||||
self.story.setMetadata('rating','Tweenie')
|
||||
|
||||
if idstr == '673':
|
||||
self.story.addToList('author','Author From List')
|
||||
self.story.addToList('author','Author From List 1')
|
||||
self.story.addToList('author','Author From List 2')
|
||||
self.story.addToList('author','Author From List 3')
|
||||
self.story.addToList('author','Author From List 4')
|
||||
self.story.addToList('author','Author From List 5')
|
||||
self.story.addToList('author','Author From List 6')
|
||||
self.story.addToList('author','Author From List 7')
|
||||
self.story.addToList('author','Author From List 8')
|
||||
self.story.addToList('author','Author From List 9')
|
||||
self.story.addToList('author','Author From List 0')
|
||||
self.story.addToList('author','Author From List q')
|
||||
self.story.addToList('author','Author From List w')
|
||||
self.story.addToList('author','Author From List e')
|
||||
self.story.addToList('author','Author From List r')
|
||||
self.story.addToList('author','Author From List t')
|
||||
self.story.addToList('author','Author From List y')
|
||||
self.story.addToList('author','Author From List u')
|
||||
self.story.addToList('author','Author From List i')
|
||||
self.story.addToList('author','Author From List o')
|
||||
|
||||
self.story.addToList('authorId','98765')
|
||||
self.story.addToList('authorId','98765-1')
|
||||
self.story.addToList('authorId','98765-2')
|
||||
self.story.addToList('authorId','98765-3')
|
||||
self.story.addToList('authorId','98765-4')
|
||||
self.story.addToList('authorId','98765-5')
|
||||
self.story.addToList('authorId','98765-6')
|
||||
self.story.addToList('authorId','98765-7')
|
||||
self.story.addToList('authorId','98765-8')
|
||||
self.story.addToList('authorId','98765-9')
|
||||
self.story.addToList('authorId','98765-0')
|
||||
self.story.addToList('authorId','98765-q')
|
||||
self.story.addToList('authorId','98765-w')
|
||||
self.story.addToList('authorId','98765-e')
|
||||
self.story.addToList('authorId','98765-r')
|
||||
self.story.addToList('authorId','98765-t')
|
||||
self.story.addToList('authorId','98765-y')
|
||||
self.story.addToList('authorId','98765-u')
|
||||
self.story.addToList('authorId','98765-i')
|
||||
self.story.addToList('authorId','98765-o')
|
||||
|
||||
self.story.addToList('authorUrl','http://author/url')
|
||||
self.story.addToList('authorUrl','http://author/url-1')
|
||||
self.story.addToList('authorUrl','http://author/url-2')
|
||||
self.story.addToList('authorUrl','http://author/url-3')
|
||||
self.story.addToList('authorUrl','http://author/url-4')
|
||||
self.story.addToList('authorUrl','http://author/url-5')
|
||||
self.story.addToList('authorUrl','http://author/url-6')
|
||||
self.story.addToList('authorUrl','http://author/url-7')
|
||||
self.story.addToList('authorUrl','http://author/url-8')
|
||||
self.story.addToList('authorUrl','http://author/url-9')
|
||||
self.story.addToList('authorUrl','http://author/url-0')
|
||||
self.story.addToList('authorUrl','http://author/url-q')
|
||||
self.story.addToList('authorUrl','http://author/url-w')
|
||||
self.story.addToList('authorUrl','http://author/url-e')
|
||||
self.story.addToList('authorUrl','http://author/url-r')
|
||||
self.story.addToList('authorUrl','http://author/url-t')
|
||||
self.story.addToList('authorUrl','http://author/url-y')
|
||||
self.story.addToList('authorUrl','http://author/url-u')
|
||||
self.story.addToList('authorUrl','http://author/url-i')
|
||||
self.story.addToList('authorUrl','http://author/url-o')
|
||||
|
||||
self.story.addToList('category','Power Rangers')
|
||||
self.story.addToList('category','SG-1')
|
||||
self.story.addToList('genre','Porn')
|
||||
@@ -160,13 +213,13 @@ Some more longer description. "I suck at summaries!" "Better than it sounds!"
|
||||
self.story.addToList('warnings','Violence')
|
||||
|
||||
if idstr == '80':
|
||||
self.story.addToList('category',u'Rizzoli & Isles')
|
||||
self.story.addToList('category',u'Rizzoli & Isles')
|
||||
self.story.addToList('characters','J. Rizzoli')
|
||||
elif idstr == '81':
|
||||
self.story.addToList('category',u'Pitch Perfect')
|
||||
self.story.addToList('characters','Chloe B.')
|
||||
elif idstr == '83':
|
||||
self.story.addToList('category',u'Rizzoli & Isles')
|
||||
self.story.addToList('category',u'Rizzoli & Isles')
|
||||
self.story.addToList('characters','J. Rizzoli')
|
||||
self.story.addToList('category',u'Pitch Perfect')
|
||||
self.story.addToList('characters','Chloe B.')
|
||||
@@ -184,6 +237,9 @@ Some more longer description. "I suck at summaries!" "Better than it sounds!"
|
||||
self.story.addToList('characters','Bob Smith')
|
||||
self.story.addToList('characters','George Johnson')
|
||||
self.story.addToList('characters','Fred Smythe')
|
||||
self.story.addToList('ships','Harry Potter/Ginny Weasley')
|
||||
self.story.addToList('ships','Harry Potter/Ginny Weasley/Albus Dumbledore')
|
||||
self.story.addToList('ships','Harry Potter & Hermione Granger')
|
||||
|
||||
self.story.addToList('genre','Fantasy')
|
||||
self.story.addToList('genre','Comedy')
|
||||
@@ -294,7 +350,7 @@ Don't—e;ver—d;o—that—a;gain, 法 é
|
||||
<hr>
|
||||
horizontal rules
|
||||
<hr size=1 noshade>
|
||||
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
|
||||
<p>"Lorem ipsum dolor sit amet", consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore--et dolore magna aliqua. 'Ut enim ad minim veniam', quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
|
||||
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
|
||||
</div>
|
||||
'''
|
||||
|
||||
@@ -48,7 +48,7 @@ class TheAlphaGateComAdapter(BaseSiteAdapter):
|
||||
|
||||
# get storyId from url--url validation guarantees query is only sid=1234
|
||||
self.story.setMetadata('storyId',self.parsedUrl.query.split('=',)[1])
|
||||
logger.debug("storyId: (%s)"%self.story.getMetadata('storyId'))
|
||||
|
||||
|
||||
# normalized story URL.
|
||||
self._setURL('http://' + self.getSiteDomain() + '/viewstory.php?sid='+self.story.getMetadata('storyId'))
|
||||
@@ -65,6 +65,7 @@ class TheAlphaGateComAdapter(BaseSiteAdapter):
|
||||
# The site domain. Does have www here, if it uses it.
|
||||
return 'www.thealphagate.com'
|
||||
|
||||
@classmethod
|
||||
def getSiteExampleURLs(self):
|
||||
return "http://"+self.getSiteDomain()+"/viewstory.php?sid=1234"
|
||||
|
||||
@@ -98,7 +99,7 @@ class TheAlphaGateComAdapter(BaseSiteAdapter):
|
||||
|
||||
## Title
|
||||
a = soup.find('a', href=re.compile(r'viewstory.php\?sid='+self.story.getMetadata('storyId')+"$"))
|
||||
self.story.setMetadata('title',a.string)
|
||||
self.story.setMetadata('title',stripHTML(a))
|
||||
|
||||
# Find authorid and URL from... author url.
|
||||
a = soup.find('a', href=re.compile(r"viewuser.php\?uid=\d+"))
|
||||
|
||||
@@ -48,7 +48,7 @@ class TheHexFilesNetAdapter(BaseSiteAdapter):
|
||||
|
||||
# get storyId from url--url validation guarantees query is only sid=1234
|
||||
self.story.setMetadata('storyId',self.parsedUrl.query.split('=',)[1])
|
||||
logger.debug("storyId: (%s)"%self.story.getMetadata('storyId'))
|
||||
|
||||
|
||||
# normalized story URL.
|
||||
self._setURL('http://' + self.getSiteDomain() + '/viewstory.php?sid='+self.story.getMetadata('storyId'))
|
||||
@@ -69,6 +69,7 @@ class TheHexFilesNetAdapter(BaseSiteAdapter):
|
||||
def getAcceptDomains(cls):
|
||||
return ['www.thehexfiles.net','thehexfiles.net']
|
||||
|
||||
@classmethod
|
||||
def getSiteExampleURLs(self):
|
||||
return "http://"+self.getSiteDomain()+"/viewstory.php?sid=1234"
|
||||
|
||||
@@ -102,7 +103,7 @@ class TheHexFilesNetAdapter(BaseSiteAdapter):
|
||||
a = soup.find('a', href=re.compile(r"viewuser.php\?uid=\d+"))
|
||||
self.story.setMetadata('authorId',a['href'].split('=')[1])
|
||||
self.story.setMetadata('authorUrl','http://'+self.host+'/'+a['href'])
|
||||
self.story.setMetadata('author',a.string)
|
||||
self.story.setMetadata('author',stripHTML(a))
|
||||
asoup = bs.BeautifulSoup(self._fetchUrl(self.story.getMetadata('authorUrl')))
|
||||
|
||||
try:
|
||||
@@ -117,7 +118,7 @@ class TheHexFilesNetAdapter(BaseSiteAdapter):
|
||||
for info in asoup.findAll('table', {'cellspacing' : '4'}):
|
||||
a = info.find('a', href=re.compile(r'viewstory.php\?sid='+self.story.getMetadata('storyId')+"$"))
|
||||
if a != None:
|
||||
self.story.setMetadata('title',a.string)
|
||||
self.story.setMetadata('title',stripHTML(a))
|
||||
break
|
||||
|
||||
|
||||
|
||||
@@ -72,7 +72,7 @@ class TheHookupZoneNetAdapter(BaseSiteAdapter): # XXX
|
||||
|
||||
# get storyId from url--url validation guarantees query is only sid=1234
|
||||
self.story.setMetadata('storyId',self.parsedUrl.query.split('=',)[1])
|
||||
logger.debug("storyId: (%s)"%self.story.getMetadata('storyId'))
|
||||
|
||||
|
||||
# normalized story URL.
|
||||
# XXX Most sites don't have the /fanfic part. Replace all to remove it usually.
|
||||
@@ -90,6 +90,7 @@ class TheHookupZoneNetAdapter(BaseSiteAdapter): # XXX
|
||||
# The site domain. Does have www here, if it uses it.
|
||||
return 'thehookupzone.net' # XXX
|
||||
|
||||
@classmethod
|
||||
def getSiteExampleURLs(self):
|
||||
return "http://"+self.getSiteDomain()+"/CriminalMinds/viewstory.php?sid=1234"
|
||||
|
||||
@@ -178,7 +179,7 @@ class TheHookupZoneNetAdapter(BaseSiteAdapter): # XXX
|
||||
|
||||
## Title
|
||||
a = soup.find('a', href=re.compile(r'viewstory.php\?sid='+self.story.getMetadata('storyId')+"$"))
|
||||
self.story.setMetadata('title',a.string)
|
||||
self.story.setMetadata('title',stripHTML(a))
|
||||
|
||||
# Find authorid and URL from... author url.
|
||||
a = soup.find('a', href=re.compile(r"viewuser.php\?uid=\d+"))
|
||||
|
||||
@@ -48,7 +48,7 @@ class TheMasqueNetAdapter(BaseSiteAdapter):
|
||||
|
||||
# get storyId from url--url validation guarantees query is only sid=1234
|
||||
self.story.setMetadata('storyId',self.parsedUrl.query.split('=',)[1])
|
||||
logger.debug("storyId: (%s)"%self.story.getMetadata('storyId'))
|
||||
|
||||
|
||||
if self.parsedUrl.path.split('/',)[1] == 'wiktt':
|
||||
self.story.addToList("category","Harry Potter")
|
||||
@@ -72,6 +72,7 @@ class TheMasqueNetAdapter(BaseSiteAdapter):
|
||||
# The site domain. Does have www here, if it uses it.
|
||||
return 'themasque.net'
|
||||
|
||||
@classmethod
|
||||
def getSiteExampleURLs(self):
|
||||
return "http://themasque.net/wiktt/efiction/viewstory.php?sid=1234 http://themasque.net/efiction/viewstory.php?sid=1234"
|
||||
|
||||
@@ -176,7 +177,7 @@ class TheMasqueNetAdapter(BaseSiteAdapter):
|
||||
|
||||
## Title
|
||||
a = soup.find('a', href=re.compile(r'viewstory.php\?sid='+self.story.getMetadata('storyId')+"$"))
|
||||
self.story.setMetadata('title',a.string)
|
||||
self.story.setMetadata('title',stripHTML(a))
|
||||
|
||||
# Find authorid and URL from... author url.
|
||||
a = soup.find('a', href=re.compile(r"viewuser.php\?uid=\d+"))
|
||||
|
||||
@@ -48,7 +48,7 @@ class ThePetulantPoetessComAdapter(BaseSiteAdapter):
|
||||
|
||||
# get storyId from url--url validation guarantees query is only sid=1234
|
||||
self.story.setMetadata('storyId',self.parsedUrl.query.split('=',)[1])
|
||||
logger.debug("storyId: (%s)"%self.story.getMetadata('storyId'))
|
||||
|
||||
|
||||
# normalized story URL.
|
||||
self._setURL('http://' + self.getSiteDomain() + '/viewstory.php?sid='+self.story.getMetadata('storyId') +'&i=1')
|
||||
@@ -65,6 +65,7 @@ class ThePetulantPoetessComAdapter(BaseSiteAdapter):
|
||||
# The site domain. Does have www here, if it uses it.
|
||||
return 'www.thepetulantpoetess.com'
|
||||
|
||||
@classmethod
|
||||
def getSiteExampleURLs(self):
|
||||
return "http://"+self.getSiteDomain()+"/viewstory.php?sid=1234"
|
||||
|
||||
@@ -164,7 +165,7 @@ class ThePetulantPoetessComAdapter(BaseSiteAdapter):
|
||||
for info in asoup.findAll('td', {'class' : 'highlightcolor1'}):
|
||||
a = info.find('a', href=re.compile(r'viewstory.php\?sid='+self.story.getMetadata('storyId')+"$"))
|
||||
if a != None:
|
||||
self.story.setMetadata('title',a.text)
|
||||
self.story.setMetadata('title',stripHTML(a))
|
||||
found = 1
|
||||
break
|
||||
index=index+1
|
||||
|
||||
@@ -52,7 +52,7 @@ class TheQuidditchPitchOrgAdapter(BaseSiteAdapter): # XXX
|
||||
|
||||
# get storyId from url--url validation guarantees query is only sid=1234
|
||||
self.story.setMetadata('storyId',self.parsedUrl.query.split('=',)[1])
|
||||
logger.debug("storyId: (%s)"%self.story.getMetadata('storyId'))
|
||||
|
||||
|
||||
# normalized story URL.
|
||||
# XXX Most sites don't have the part. Replace all to remove it usually.
|
||||
@@ -74,6 +74,7 @@ class TheQuidditchPitchOrgAdapter(BaseSiteAdapter): # XXX
|
||||
def getAcceptDomains(cls):
|
||||
return ['www.thequidditchpitch.org','thequidditchpitch.org']
|
||||
|
||||
@classmethod
|
||||
def getSiteExampleURLs(self):
|
||||
return "http://"+self.getSiteDomain()+"/viewstory.php?sid=1234"
|
||||
|
||||
@@ -164,7 +165,7 @@ class TheQuidditchPitchOrgAdapter(BaseSiteAdapter): # XXX
|
||||
|
||||
## Title
|
||||
a = soup.find('a', href=re.compile(r'viewstory.php\?sid='+self.story.getMetadata('storyId')))
|
||||
self.story.setMetadata('title',a.string)
|
||||
self.story.setMetadata('title',stripHTML(a))
|
||||
|
||||
# Find authorid and URL from... author url.
|
||||
a = soup.find('a', href=re.compile(r"viewuser.php\?uid=\d+"))
|
||||
|
||||
@@ -44,7 +44,7 @@ class TheWritersCoffeeShopComSiteAdapter(BaseSiteAdapter):
|
||||
|
||||
# get storyId from url--url validation guarantees query is only sid=1234
|
||||
self.story.setMetadata('storyId',self.parsedUrl.query.split('=',)[1])
|
||||
logger.debug("storyId: (%s)"%self.story.getMetadata('storyId'))
|
||||
|
||||
|
||||
# normalized story URL.
|
||||
self._setURL('http://' + self.getSiteDomain() + '/library/viewstory.php?sid='+self.story.getMetadata('storyId'))
|
||||
@@ -55,6 +55,7 @@ class TheWritersCoffeeShopComSiteAdapter(BaseSiteAdapter):
|
||||
def getSiteDomain():
|
||||
return 'www.thewriterscoffeeshop.com'
|
||||
|
||||
@classmethod
|
||||
def getSiteExampleURLs(self):
|
||||
return "http://"+self.getSiteDomain()+"/library/viewstory.php?sid=1234"
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ class TokraFandomnetComAdapter(BaseSiteAdapter):
|
||||
|
||||
# get storyId from url--url validation guarantees query is only sid=1234
|
||||
self.story.setMetadata('storyId',self.parsedUrl.query.split('=',)[1])
|
||||
logger.debug("storyId: (%s)"%self.story.getMetadata('storyId'))
|
||||
|
||||
|
||||
# normalized story URL.
|
||||
self._setURL('http://' + self.getSiteDomain() + '/viewstory.php?sid='+self.story.getMetadata('storyId'))
|
||||
@@ -66,6 +66,7 @@ class TokraFandomnetComAdapter(BaseSiteAdapter):
|
||||
# doesn't matter too much anymore.
|
||||
return 'tokra.fandomnet.com'
|
||||
|
||||
@classmethod
|
||||
def getSiteExampleURLs(self):
|
||||
return "http://"+self.getSiteDomain()+"/viewstory.php?sid=1234"
|
||||
|
||||
@@ -130,7 +131,7 @@ class TokraFandomnetComAdapter(BaseSiteAdapter):
|
||||
|
||||
## Title
|
||||
a = soup.find('a', href=re.compile(r'viewstory.php\?sid='+self.story.getMetadata('storyId')+"$"))
|
||||
self.story.setMetadata('title',a.string)
|
||||
self.story.setMetadata('title',stripHTML(a))
|
||||
|
||||
# Find authorid and URL from... author url.
|
||||
a = soup.find('a', href=re.compile(r"viewuser.php\?uid=\d+"))
|
||||
|
||||
@@ -41,7 +41,7 @@ class TwistingTheHellmouthSiteAdapter(BaseSiteAdapter):
|
||||
m = re.match(self.getSiteURLPattern(),url)
|
||||
if m:
|
||||
self.story.setMetadata('storyId',m.group('id'))
|
||||
logger.debug("storyId: (%s)"%self.story.getMetadata('storyId'))
|
||||
|
||||
# normalized story URL.
|
||||
self._setURL("http://"+self.getSiteDomain()\
|
||||
+"/Story-"+self.story.getMetadata('storyId'))
|
||||
@@ -54,13 +54,14 @@ class TwistingTheHellmouthSiteAdapter(BaseSiteAdapter):
|
||||
def getSiteDomain():
|
||||
return 'www.tthfanfic.org'
|
||||
|
||||
@classmethod
|
||||
def getSiteExampleURLs(self):
|
||||
return "http://www.tthfanfic.org/Story-5583 http://www.tthfanfic.org/Story-5583/Greywizard+Marked+By+Kane.htm http://www.tthfanfic.org/T-526321777890480578489880055880/Story-26448-15/batzulger+Willow+Rosenberg+and+the+Mind+Riders.htm"
|
||||
return "http://www.tthfanfic.org/Story-1234 http://www.tthfanfic.org/Story-1234/Author+Story+Title.htm http://www.tthfanfic.org/T-99999999/Story-1234-1/Author+Story+Title.htm http://www.tthfanfic.org/story.php?no=12345"
|
||||
|
||||
# http://www.tthfanfic.org/T-526321777848988007890480555880/Story-26448-15/batzulger+Willow+Rosenberg+and+the+Mind+Riders.htm
|
||||
# http://www.tthfanfic.org/Story-5583
|
||||
# http://www.tthfanfic.org/Story-5583/Greywizard+Marked+By+Kane.htm
|
||||
# http://www.tthfanfic.org/story.php?no=26093
|
||||
# http://www.tthfanfic.org/T-999999999999/Story-12345-1/Author+Story+Title.htm
|
||||
# http://www.tthfanfic.org/Story-12345
|
||||
# http://www.tthfanfic.org/Story-12345/Author+Story+Title.htm
|
||||
# http://www.tthfanfic.org/story.php?no=12345
|
||||
def getSiteURLPattern(self):
|
||||
return r"http://www.tthfanfic.org(/(T-\d+/)?Story-|/story.php\?no=)(?P<id>\d+)(-\d+)?(/.*)?$"
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ class TwilightArchivesComAdapter(BaseSiteAdapter):
|
||||
|
||||
# get storyId from url--url validation guarantees query is only sid=1234
|
||||
self.story.setMetadata('storyId',self.parsedUrl.path.split('/',)[2])
|
||||
logger.debug("storyId: (%s)"%self.story.getMetadata('storyId'))
|
||||
|
||||
|
||||
# normalized story URL. http://www.twilightarchives.com/read/9353
|
||||
self._setURL('http://' + self.getSiteDomain() + '/read/'+self.story.getMetadata('storyId'))
|
||||
@@ -66,6 +66,7 @@ class TwilightArchivesComAdapter(BaseSiteAdapter):
|
||||
return 'www.twilightarchives.com'
|
||||
|
||||
|
||||
@classmethod
|
||||
def getSiteExampleURLs(self):
|
||||
return "http://"+self.getSiteDomain()+"/read/1234"
|
||||
|
||||
@@ -99,7 +100,7 @@ class TwilightArchivesComAdapter(BaseSiteAdapter):
|
||||
|
||||
## Title
|
||||
a = soup.find('h1')
|
||||
self.story.setMetadata('title',a.string)
|
||||
self.story.setMetadata('title',stripHTML(a))
|
||||
|
||||
# Find the chapters:
|
||||
chapters=soup.find('ol', {'class' : 'chapters'})
|
||||
|
||||
@@ -43,7 +43,7 @@ class TwilightedNetSiteAdapter(BaseSiteAdapter):
|
||||
|
||||
# get storyId from url--url validation guarantees query is only sid=1234
|
||||
self.story.setMetadata('storyId',self.parsedUrl.query.split('=',)[1])
|
||||
logger.debug("storyId: (%s)"%self.story.getMetadata('storyId'))
|
||||
|
||||
|
||||
# normalized story URL.
|
||||
self._setURL('http://' + self.getSiteDomain() + '/viewstory.php?sid='+self.story.getMetadata('storyId'))
|
||||
@@ -57,8 +57,9 @@ class TwilightedNetSiteAdapter(BaseSiteAdapter):
|
||||
def getAcceptDomains(cls):
|
||||
return ['www.twilighted.net','twilighted.net']
|
||||
|
||||
@classmethod
|
||||
def getSiteExampleURLs(self):
|
||||
return "http://www.twilighted.net/viewstory.php?sid=1234 http://twilighted.net/viewstory.php?sid=5678"
|
||||
return "http://www.twilighted.net/viewstory.php?sid=1234"
|
||||
|
||||
def getSiteURLPattern(self):
|
||||
return re.escape("http://")+r"(www\.)?"+re.escape("twilighted.net/viewstory.php?sid=")+r"\d+$"
|
||||
@@ -129,7 +130,7 @@ class TwilightedNetSiteAdapter(BaseSiteAdapter):
|
||||
|
||||
## Title
|
||||
a = soup.find('a', href=re.compile(r'viewstory.php\?sid='+self.story.getMetadata('storyId')+"$"))
|
||||
self.story.setMetadata('title',a.string)
|
||||
self.story.setMetadata('title',stripHTML(a))
|
||||
|
||||
# Find authorid and URL from... author url.
|
||||
a = soup.find('a', href=re.compile(r"viewuser.php"))
|
||||
|
||||
@@ -44,7 +44,7 @@ class TwiwriteNetSiteAdapter(BaseSiteAdapter):
|
||||
|
||||
# get storyId from url--url validation guarantees query is only sid=1234
|
||||
self.story.setMetadata('storyId',self.parsedUrl.query.split('=',)[1])
|
||||
logger.debug("storyId: (%s)"%self.story.getMetadata('storyId'))
|
||||
|
||||
|
||||
# normalized story URL.
|
||||
self._setURL('http://' + self.getSiteDomain() + '/viewstory.php?sid='+self.story.getMetadata('storyId'))
|
||||
@@ -58,8 +58,9 @@ class TwiwriteNetSiteAdapter(BaseSiteAdapter):
|
||||
def getAcceptDomains(cls):
|
||||
return ['www.twiwrite.net','twiwrite.net']
|
||||
|
||||
@classmethod
|
||||
def getSiteExampleURLs(self):
|
||||
return "http://www.twiwrite.net/viewstory.php?sid=1234 http://twiwrite.net/viewstory.php?sid=5678"
|
||||
return "http://www.twiwrite.net/viewstory.php?sid=1234"
|
||||
|
||||
def getSiteURLPattern(self):
|
||||
return re.escape("http://")+r"(www\.)?"+re.escape("twiwrite.net/viewstory.php?sid=")+r"\d+$"
|
||||
@@ -143,7 +144,7 @@ class TwiwriteNetSiteAdapter(BaseSiteAdapter):
|
||||
|
||||
## Title
|
||||
a = pagetitlediv.find('a', href=re.compile(r'viewstory.php\?sid='+self.story.getMetadata('storyId')+"$"))
|
||||
self.story.setMetadata('title',a.string)
|
||||
self.story.setMetadata('title',stripHTML(a))
|
||||
|
||||
# Find authorid and URL from... author url.
|
||||
a = pagetitlediv.find('a', href=re.compile(r"viewuser.php\?uid=\d+"))
|
||||
|
||||
@@ -46,7 +46,7 @@ class WalkingThePlankOrgAdapter(BaseSiteAdapter):
|
||||
|
||||
# get storyId from url--url validation guarantees query is only sid=1234
|
||||
self.story.setMetadata('storyId',self.parsedUrl.query.split('=',)[1])
|
||||
logger.debug("storyId: (%s)"%self.story.getMetadata('storyId'))
|
||||
|
||||
|
||||
# normalized story URL.
|
||||
self._setURL('http://' + self.getSiteDomain() + '/archive/viewstory.php?sid='+self.story.getMetadata('storyId'))
|
||||
@@ -63,6 +63,7 @@ class WalkingThePlankOrgAdapter(BaseSiteAdapter):
|
||||
# The site domain. Does have www here, if it uses it.
|
||||
return 'www.walkingtheplank.org'
|
||||
|
||||
@classmethod
|
||||
def getSiteExampleURLs(self):
|
||||
return "http://"+self.getSiteDomain()+"/archive/viewstory.php?sid=1234"
|
||||
|
||||
@@ -114,7 +115,7 @@ class WalkingThePlankOrgAdapter(BaseSiteAdapter):
|
||||
|
||||
## Title
|
||||
a = soup.find('a', href=re.compile(r'viewstory.php\?sid='+self.story.getMetadata('storyId')+"$"))
|
||||
self.story.setMetadata('title',a.string)
|
||||
self.story.setMetadata('title',stripHTML(a))
|
||||
|
||||
# Find authorid and URL from... author url.
|
||||
a = soup.find('a', href=re.compile(r"viewuser.php\?uid=\d+"))
|
||||
|
||||
@@ -41,6 +41,7 @@ class WhoficComSiteAdapter(BaseSiteAdapter):
|
||||
def getSiteDomain():
|
||||
return 'www.whofic.com'
|
||||
|
||||
@classmethod
|
||||
def getSiteExampleURLs(self):
|
||||
return "http://"+self.getSiteDomain()+"/viewstory.php?sid=1234"
|
||||
|
||||
@@ -69,7 +70,7 @@ class WhoficComSiteAdapter(BaseSiteAdapter):
|
||||
raise e
|
||||
|
||||
# pull title(title) and author from the HTML title.
|
||||
title = soup.find('title').string
|
||||
title = stripHTML(soup.find('title'))
|
||||
logger.debug('Title: %s' % title)
|
||||
title = title.split('::')[1].strip()
|
||||
self.story.setMetadata('title',title.split(' by ')[0].strip())
|
||||
|
||||
@@ -48,7 +48,7 @@ class WizardTalesNetAdapter(BaseSiteAdapter):
|
||||
|
||||
# get storyId from url--url validation guarantees query is only sid=1234
|
||||
self.story.setMetadata('storyId',self.parsedUrl.query.split('=',)[1])
|
||||
logger.debug("storyId: (%s)"%self.story.getMetadata('storyId'))
|
||||
|
||||
|
||||
# normalized story URL.
|
||||
self._setURL('http://' + self.getSiteDomain() + '/viewstory.php?sid='+self.story.getMetadata('storyId'))
|
||||
@@ -65,6 +65,7 @@ class WizardTalesNetAdapter(BaseSiteAdapter):
|
||||
# The site domain. Does have www here, if it uses it.
|
||||
return 'www.wizardtales.net'
|
||||
|
||||
@classmethod
|
||||
def getSiteExampleURLs(self):
|
||||
return "http://"+self.getSiteDomain()+"/viewstory.php?sid=1234"
|
||||
|
||||
@@ -170,7 +171,7 @@ class WizardTalesNetAdapter(BaseSiteAdapter):
|
||||
## Title
|
||||
pt = soup.find('div', {'id' : 'pagetitle'})
|
||||
a = pt.find('a', href=re.compile(r'viewstory.php\?sid='+self.story.getMetadata('storyId')+"$"))
|
||||
self.story.setMetadata('title',a.text)
|
||||
self.story.setMetadata('title',stripHTML(a))
|
||||
|
||||
# Find authorid and URL from... author url.
|
||||
a = pt.find('a', href=re.compile(r"viewuser.php\?uid=\d+"))
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user