Advertisement
murfel

harvest_microformat.py

Dec 30th, 2014
265
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 6.74 KB | None | 0 0
  1. #!/usr/bin/python
  2. # -*- coding: utf-8 -*-
  3. """
  4. Harvesting microformats from HTML to Wikibase script.
  5.  
  6. Usage:
  7.  
  8. python pwb.py scripts/harvest_html.py -transcludes:"..."
  9.  
  10. These command line parameters can be used to specify which pages to work on:
  11.  
  12. &params;
  13.  
  14. """
  15. #
  16. # (C) Pywikibot team, 2013-2015
  17. #
  18. # Distributed under the terms of MIT License.
  19. #
  20. __version__ = '$Id$'
  21. #
  22.  
  23. import re
  24. import pywikibot
  25. from pywikibot import pagegenerators as pg, WikidataBot
  26. from mf2py.parser import Parser
  27.  
  28. docuReplacements = {'&params;': pywikibot.pagegenerators.parameterHelp}
  29.  
  30.  
  31. class HarvestHTMLRobot(WikidataBot):
  32.  
  33.     """A bot to parse microformats and add Wikidata claims."""
  34.  
  35.     def __init__(self, generator):
  36.         """
  37.        Constructor.
  38.  
  39.        @param generator: A generator that yields Page objects
  40.  
  41.        """
  42.         super(HarvestHTMLRobot, self).__init__()
  43.         self.generator = pg.PreloadingGenerator(generator)
  44.         self.cacheSources()
  45.  
  46.     # I left this method signature in case its analogue
  47.     # may be somehow useful once implemented for pages
  48.     def getTemplateSynonyms(self, title):
  49.         """Fetch redirects of the title, so we can check against them."""
  50.         pass
  51.  
  52.     def _page_link_target(self, item, link_text):
  53.         linked_page = None
  54.  
  55.         link = pywikibot.Link(link_text)
  56.         linked_page = pywikibot.Page(link)
  57.  
  58.         if not linked_page.exists():
  59.             pywikibot.output(u'%s doesn\'t exist so it can\'t be linked. Skipping' % (linked_page))
  60.             return
  61.  
  62.         if linked_page.isRedirectPage():
  63.             linked_page = linked_page.getRedirectTarget()
  64.  
  65.         try:
  66.             linked_item = pywikibot.ItemPage.fromPage(linked_page)
  67.         except pywikibot.NoPage:
  68.             linked_item = None
  69.  
  70.         if not linked_item or not linked_item.exists():
  71.             pywikibot.output(u'%s doesn\'t have a wikidata item to link with. Skipping' % (linked_page))
  72.             return
  73.  
  74.         if linked_item.title() == item.title():
  75.             pywikibot.output(u'%s links to itself. Skipping' % (linked_page))
  76.             return
  77.  
  78.         return linked_item
  79.  
  80.     def treat(self, page, item):
  81.         """Process a single page/item."""
  82.         self.current_page = page
  83.         item.get()
  84.  
  85.         page_url = (self.current_page.site.protocol() + "://" +
  86.                     self.current_page.site.hostname() +
  87.                     self.current_page.site.nice_get_address(self.current_page.title(asUrl=True)))
  88.         parser = Parser(url=page_url)
  89.         parsed_props = parser.to_dict()
  90.  
  91.         #print parsed_props["items"][0]["properties"]
  92.         #print parsed_props
  93.         # interchange parsed_props with parsed_props["items"][0]["properties"]
  94.         for field in parsed_props:
  95.             field = field.strip()
  96.             parsed_props[field] = parsed_props[field].strip()
  97.  
  98.         for field in parsed_props:
  99.             # Check if the property isn't already set
  100.             value = parsed_props[field]
  101.             claim = pywikibot.Claim(self.repo, value)
  102.             if claim.getID() in item.get().get('claims'):
  103.                 pywikibot.output(u'A claim for %s already exists. Skipping'
  104.                                  % claim.getID())
  105.                 # TODO: Implement smarter approach to merging
  106.                 # harvested values with existing claims esp.
  107.                 # without overwriting humans unintentionally.
  108.             else:
  109.                 if claim.type == 'wikibase-item':
  110.                     # Try to extract a valid page
  111.                     match = re.search(pywikibot.link_regex, value)
  112.                     if not match:
  113.                         pywikibot.output(u'%s field %s value %s isn\'t a wikilink. Skipping'
  114.                                          % (claim.getID(), field, value))
  115.                         continue
  116.  
  117.                     link_text = match.group(1)
  118.                     linked_item = self._page_link_target(item, link_text)
  119.                     if not linked_item:
  120.                         continue
  121.  
  122.                     claim.setTarget(linked_item)
  123.                 elif claim.type == 'string':
  124.                     claim.setTarget(value.strip())
  125.                 elif claim.type == 'commonsMedia':
  126.                     commonssite = pywikibot.Site("commons", "commons")
  127.                     imagelink = pywikibot.Link(value, source=commonssite, defaultNamespace=6)
  128.                     image = pywikibot.FilePage(imagelink)
  129.                     if image.isRedirectPage():
  130.                         image = pywikibot.FilePage(image.getRedirectTarget())
  131.                     if not image.exists():
  132.                         pywikibot.output('[[%s]] doesn\'t exist so I can\'t link to it'
  133.                                          % (image.title(),))
  134.                         continue
  135.                     claim.setTarget(image)
  136.                 #elif claim.type == 'globe-coordinate':
  137.                 #elif claim.type == 'url':
  138.                 elif claim.type == 'time':
  139.                     # value is expected to have "1706-01-17" format
  140.                     WbTime_value = pywikibot.WbTime(year=value[:4],
  141.                                                     month=value[5:7],
  142.                                                     day=value[8:])
  143.                     claim = pywikibot.Claim(self.repo, WbTime_value)
  144.                     claim.setTarget(WbTime_value)
  145.                 #elif claim.type == 'quantity':
  146.                 else:
  147.                     pywikibot.output("%s is not a supported datatype." % claim.type)
  148.                     continue
  149.  
  150.                 pywikibot.output('Adding %s --> %s' % (claim.getID(), claim.getTarget()))
  151.                 item.addClaim(claim)
  152.                 # A generator might yield pages from multiple sites
  153.                 source = self.getSource(page.site)
  154.                 if source:
  155.                     claim.addSource(source, bot=True)
  156.  
  157.  
  158. def main(*args):
  159.     """
  160.    Process command line arguments and invoke bot.
  161.  
  162.    If args is an empty list, sys.argv is used.
  163.  
  164.    @param args: command line arguments
  165.    @type args: list of unicode
  166.    """
  167.     commandline_arguments = list()
  168.     page_title = u''
  169.  
  170.     # Process global args and prepare generator args parser
  171.     local_args = pywikibot.handle_args(args)
  172.     gen = pg.GeneratorFactory()
  173.  
  174.     for arg in local_args:
  175.         if gen.handleArg(arg):
  176.             if arg.startswith(u'-transcludes:'):
  177.                 page_title = arg[13:]
  178.         else:
  179.             commandline_arguments.append(arg)
  180.  
  181.     generator = gen.getCombinedGenerator()
  182.     if not generator:
  183.         gen.handleArg(u'-transcludes:' + page_title)
  184.         generator = gen.getCombinedGenerator()
  185.  
  186.     bot = HarvestHTMLRobot(generator)
  187.     bot.run()
  188.  
  189. if __name__ == "__main__":
  190.     main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement