home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2011 January / maximum-cd-2011-01.iso / DiscContents / calibre-0.7.26.msi / file_957 (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2010-10-31  |  6.9 KB  |  195 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.6)
  3.  
  4. __license__ = 'GPL v3'
  5. __copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
  6. import sys
  7. import socket
  8. import os
  9. import re
  10. from lxml import html
  11. import mechanize
  12. from calibre import browser, prints
  13. from calibre.utils.config import OptionParser
  14. from calibre.ebooks.BeautifulSoup import BeautifulSoup
  15. from calibre.ebooks.chardet import strip_encoding_declarations
  16. OPENLIBRARY = 'http://covers.openlibrary.org/b/isbn/%s-L.jpg?default=false'
  17.  
  18. class HeadRequest(mechanize.Request):
  19.     
  20.     def get_method(self):
  21.         return 'HEAD'
  22.  
  23.  
  24.  
  25. def check_for_cover(isbn, timeout = 5):
  26.     br = browser()
  27.     br.set_handle_redirect(False)
  28.     
  29.     try:
  30.         br.open_novisit(HeadRequest(OPENLIBRARY % isbn), timeout = timeout)
  31.         return True
  32.     except Exception:
  33.         e = None
  34.         if callable(getattr(e, 'getcode', None)) and e.getcode() == 302:
  35.             return True
  36.     except:
  37.         e.getcode() == 302
  38.  
  39.     return False
  40.  
  41.  
  42. class LibraryThingError(Exception):
  43.     pass
  44.  
  45.  
  46. class ISBNNotFound(LibraryThingError):
  47.     pass
  48.  
  49.  
  50. class ServerBusy(LibraryThingError):
  51.     pass
  52.  
  53.  
  54. def login(br, username, password, force = True):
  55.     br.open('http://www.librarything.com')
  56.     br.select_form('signup')
  57.     br['formusername'] = username
  58.     br['formpassword'] = password
  59.     br.submit()
  60.  
  61.  
  62. def cover_from_isbn(isbn, timeout = 5, username = None, password = None):
  63.     src = None
  64.     br = browser()
  65.     
  66.     try:
  67.         return (br.open(OPENLIBRARY % isbn, timeout = timeout).read(), 'jpg')
  68.     except:
  69.         pass
  70.  
  71.     if username and password:
  72.         
  73.         try:
  74.             login(br, username, password, force = False)
  75.  
  76.     
  77.     
  78.     try:
  79.         src = br.open_novisit('http://www.librarything.com/isbn/' + isbn, timeout = timeout).read().decode('utf-8', 'replace')
  80.     except Exception:
  81.         err = None
  82.         if isinstance(getattr(err, 'args', [
  83.             None])[0], socket.timeout):
  84.             err = LibraryThingError(_('LibraryThing.com timed out. Try again later.'))
  85.         
  86.         raise err
  87.  
  88.     s = BeautifulSoup(src)
  89.     url = s.find('td', attrs = {
  90.         'class': 'left' })
  91.     if url is None:
  92.         if s.find('div', attrs = {
  93.             'class': 'highloadwarning' }) is not None:
  94.             raise ServerBusy(_('Could not fetch cover as server is experiencing high load. Please try again later.'))
  95.         s.find('div', attrs = {
  96.             'class': 'highloadwarning' }) is not None
  97.         raise ISBNNotFound('ISBN: ' + isbn + _(' not found.'))
  98.     url is None
  99.     url = url.find('img')
  100.     if url is None:
  101.         raise LibraryThingError(_('LibraryThing.com server error. Try again later.'))
  102.     url is None
  103.     url = re.sub('_S[XY]\\d+', '', url['src'])
  104.     cover_data = br.open_novisit(url).read()
  105.     return (cover_data, url.rpartition('.')[-1])
  106.  
  107.  
  108. def option_parser():
  109.     parser = OptionParser(usage = _('\n%prog [options] ISBN\n\nFetch a cover image/social metadata for the book identified by ISBN from LibraryThing.com\n'))
  110.     parser.add_option('-u', '--username', default = None, help = 'Username for LibraryThing.com')
  111.     parser.add_option('-p', '--password', default = None, help = 'Password for LibraryThing.com')
  112.     return parser
  113.  
  114.  
  115. def get_social_metadata(title, authors, publisher, isbn, username = None, password = None):
  116.     MetaInformation = MetaInformation
  117.     import calibre.ebooks.metadata
  118.     mi = MetaInformation(title, authors)
  119.     if isbn:
  120.         br = browser()
  121.         if username and password:
  122.             
  123.             try:
  124.                 login(br, username, password, force = False)
  125.  
  126.         
  127.         raw = br.open_novisit('http://www.librarything.com/isbn/' + isbn).read()
  128.         if not raw:
  129.             return mi
  130.         raw = raw.decode('utf-8', 'replace')
  131.         raw = strip_encoding_declarations(raw)
  132.         root = html.fromstring(raw)
  133.         h1 = root.xpath('//div[@class="headsummary"]/h1')
  134.         if h1 and not (mi.title):
  135.             mi.title = html.tostring(h1[0], method = 'text', encoding = unicode)
  136.         
  137.         h2 = root.xpath('//div[@class="headsummary"]/h2/a')
  138.         h3 = root.xpath('//div[@class="headsummary"]/h3/a')
  139.         if h3:
  140.             match = None
  141.             for h in h3:
  142.                 series = html.tostring(h, method = 'text', encoding = unicode)
  143.                 match = re.search('(.+) \\((.+)\\)', series)
  144.                 if match is not None:
  145.                     break
  146.                     continue
  147.                 None if h2 and not (mi.authors) else []
  148.             
  149.             if match is not None:
  150.                 mi.series = match.group(1).strip()
  151.                 match = re.search('[0-9.]+', match.group(2))
  152.                 si = 1
  153.                 if match is not None:
  154.                     si = float(match.group())
  155.                 
  156.                 mi.series_index = si
  157.             
  158.         
  159.         span = root.xpath('//table[@class="wsltable"]/tr[@class="wslcontent"]/td[4]//span')
  160.         if span:
  161.             raw = html.tostring(span[0], method = 'text', encoding = unicode)
  162.             match = re.search('([0-9.]+)', raw)
  163.             if match is not None:
  164.                 rating = float(match.group())
  165.                 if rating > 0 and rating <= 5:
  166.                     mi.rating = rating
  167.                 
  168.             
  169.         
  170.     
  171.     return mi
  172.  
  173.  
  174. def main(args = sys.argv):
  175.     parser = option_parser()
  176.     (opts, args) = parser.parse_args(args)
  177.     if len(args) != 2:
  178.         parser.print_help()
  179.         return 1
  180.     isbn = args[1]
  181.     mi = get_social_metadata('', [], '', isbn)
  182.     prints(mi)
  183.     (cover_data, ext) = cover_from_isbn(isbn, username = opts.username, password = opts.password)
  184.     if not ext:
  185.         ext = 'jpg'
  186.     
  187.     oname = os.path.abspath(isbn + '.' + ext)
  188.     open(oname, 'w').write(cover_data)
  189.     print 'Cover saved to file', oname
  190.     return 0
  191.  
  192. if __name__ == '__main__':
  193.     sys.exit(main())
  194.  
  195.