Want more features on Pastebin? Sign Up, it's FREE!
Guest

Explain XKCD Comic Bot

By: a guest on Aug 4th, 2012  |  syntax: Python  |  size: 6.80 KB  |  views: 29  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. #!/usr/bin/python
  2. #coding: utf-8
  3. """
  4. This bot reads data from xkcd.com and creates the appropriate pages.
  5. This bot is designed specifically for explainxkcd.com.
  6. No changes are made if the pages already exist.
  7.  
  8. Specific arguments:
  9. -test           Don't actually make any changes
  10. -latest         Create pages for the latest comic
  11. -all            Create pages for all comics
  12. -start:xxx      Specify the comic number to start at (inclusive).
  13.                This requires -all. Defaults to 1.
  14. -end:xxx        Specify the comic number to end at (inclusive).
  15.                This requires -all. Defaults to 99999.
  16.                                
  17. Example usage:
  18. # Make sure everthing is set up properly, but don't actually do anything
  19. python xkcd.py -latest -test
  20. # Add pages for the latest comic (if they don't exist yet)
  21. python xkcd.py -latest
  22. # Add pages for all comics (if they don't exist yet)
  23. python xkcd.py -all
  24. # Add pages for comics 50-100 (if they don't exist yet)
  25. python xkcd.py -all -start:50 -end:100
  26. """
  27. #
  28. # Distributed under the terms of the MIT license.
  29. #
  30. #
  31. # This script is based on pagefromfile.py, which has the following license:
  32. #
  33. ## (C) Andre Engels, 2004
  34. ## (C) Pywikipedia bot team, 2005-2010
  35. ##
  36. ## Distributed under the terms of the MIT license.
  37. #
  38. __version__='$Id$'
  39. #
  40.  
  41. import re
  42. import wikipedia as pywikibot
  43. import urllib
  44. import json
  45. import datetime
  46. import upload
  47.  
  48. def formatComicPage(data, imageFilename):
  49.     # Parse the date
  50.     date = datetime.date(int(data['year']), int(data['month']), int(data['day']))
  51.     # Format as "August 01, 2012", then replace "01" with "1"
  52.     dateText = re.sub(r"\b0([0-9])\b", r"\1", date.strftime("%B %d, %Y"))
  53.     # Return the contents of the comic page
  54.     return """{{ComicHeader|%d|%s}}
  55.  
  56. [[File:%s|%s]]
  57.  
  58. == Image Text ==
  59. %s
  60.  
  61. == Description ==
  62. This comic doesn't have a description yet. Why don't you add one?
  63. """ % (data['num'], dateText, imageFilename, data['alt'], data['alt'])
  64.  
  65. class XKCDRobot:
  66.    
  67.     def __init__(self, test, createAll, createLatest, start, end):
  68.         self.test = test
  69.         self.createAll = createAll
  70.         self.createLatest = createLatest
  71.         self.start = start
  72.         self.end = end
  73.  
  74.     def run(self):
  75.         pywikibot.output(u"")
  76.         if self.test:
  77.             pywikibot.output(u"TESTING - Nothing will actually be done.")
  78.         if self.createLatest:
  79.             self.addLatestComic()
  80.         if self.createAll:
  81.             self.addAllComics()
  82.    
  83.     def addAllComics(self):
  84.         pywikibot.output(u"Adding all comics from %d to %d..." % (self.start, self.end))
  85.         num = self.start
  86.         while num <= self.end:
  87.             try:
  88.                 pywikibot.output(u"Reading comic data for %d..." % num)
  89.                 data = self.getComicData(num)
  90.                 pywikibot.output(u"Read comic data (%s: '%s')." % (data['num'], data['safe_title']))
  91.             except ValueError:
  92.                 # Likely a 404, which means we're done
  93.                 break
  94.             self.addComic(data)
  95.             num += 1
  96.    
  97.     def addLatestComic(self):
  98.         pywikibot.output(u"Reading latest comic data...")
  99.         data = self.getComicData()
  100.         pywikibot.output(u"Read latest comic data (%s: %s)." % (data['num'], data['safe_title']))
  101.         self.addComic(data)
  102.    
  103.     def getComicData(self, num = None):
  104.         if num == None:
  105.             # Latest
  106.             url = "http://xkcd.com/info.0.json"
  107.         else:
  108.             url = "http://xkcd.com/%d/info.0.json" % num
  109.         return json.load(urllib.urlopen(url))
  110.    
  111.     def addComic(self, data):
  112.         self.createRedirectPage(data)
  113.         self.createComicPage(data)
  114.    
  115.     def createRedirectPage(self, data):
  116.         page = self.getPage(str(data['num']))
  117.         if not page.exists():
  118.             pywikibot.output(u"Creating redirect page for %s..." % data['num'])
  119.             contents = "#REDIRECT [[%s]]" % data['safe_title']
  120.             self.writePage(page, contents, "Created page with redirect to '%s'." % data['safe_title'])
  121.             pywikibot.output(u"Created redirect page." % data['num'])
  122.         else:
  123.             pywikibot.output(u"Redirect page already exists for %s." % data['num'])
  124.  
  125.     def createComicPage(self, data):
  126.         page = self.getPage(data['safe_title'])
  127.         if not page.exists():
  128.             # Upload image first
  129.             imageFilename = data['safe_title'].replace(" ", "_") + ".png"
  130.             pywikibot.output(u"Uploading image '%s' for %s..." % (imageFilename, data['num']))
  131.             if not self.test:
  132.                 uploadBot = upload.UploadRobot(data['img'], \
  133.                                                description="Image for comic '%s'" % data['safe_title'], \
  134.                                                useFilename = imageFilename, \
  135.                                                verifyDescription = False, \
  136.                                                targetSite = pywikibot.getSite(), \
  137.                                                uploadByUrl=True)
  138.             pywikibot.output(u"Uploaded image.")
  139.             pywikibot.output(u"Creating comic page '%s' for %s..." % (data['safe_title'], data['num']))
  140.             contents = formatComicPage(data, imageFilename)
  141.             self.writePage(page, contents, "Created comic stub")
  142.             pywikibot.output(u"Created comic page.")
  143.         else:
  144.             pywikibot.output(u"Comic page already exists for %s." % data['num'])
  145.  
  146.     def getPage(self, name):
  147.         mysite = pywikibot.getSite()
  148.         page = pywikibot.Page(mysite, name)
  149.         return page
  150.    
  151.     def writePage(self, page, contents, comment):
  152.         try:
  153.             if not self.test:
  154.                 page.put(contents, comment = comment)
  155.         except pywikibot.LockedPage:
  156.             pywikibot.output(u"Page is locked; skipping.")
  157.         except pywikibot.EditConflict:
  158.             pywikibot.output(u'Skipping because of edit conflict')
  159.         except pywikibot.SpamfilterError, error:
  160.             pywikibot.output(
  161.                 u'Cannot change because of spam blacklist entry %s'
  162.                 % (error.url))
  163.  
  164. def main():
  165.     createAll = False
  166.     createLatest = False
  167.     test = False
  168.     start = 1
  169.     end = 99999
  170.  
  171.     for arg in pywikibot.handleArgs():
  172.         if arg.startswith("-start:"):
  173.             start = int(arg[7:])
  174.         elif arg.startswith("-end:"):
  175.             end = int(arg[5:])
  176.         elif arg == "-latest":
  177.             createLatest = True
  178.         elif arg == "-all":
  179.             createAll = True
  180.         elif arg == "-test":
  181.             test = True
  182.         else:
  183.             pywikibot.output(u"Disregarding unknown argument %s." % arg)
  184.  
  185.     bot = XKCDRobot(test, createAll, createLatest, start, end)
  186.     bot.run()
  187.  
  188. if __name__ == "__main__":
  189.     try:
  190.         main()
  191.     finally:
  192.         pywikibot.stopme()
clone this paste RAW Paste Data