wikipedia.py 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. """
  2. Wikipedia (Web)
  3. @website https://{language}.wikipedia.org
  4. @provide-api yes
  5. @using-api yes
  6. @results JSON
  7. @stable yes
  8. @parse url, infobox
  9. """
  10. from json import loads
  11. from urllib import urlencode, quote
  12. supported_languages = ["en", "sv", "ceb", "de", "nl", "fr", "ru", "it", "es", "war",
  13. "pl", "vi", "ja", "pt", "zh", "uk", "ca", "fa", "no", "sh",
  14. "ar", "fi", "hu", "id", "ro", "cs", "ko", "sr", "ms", "tr",
  15. "eu", "eo", "min", "bg", "da", "kk", "sk", "hy", "he", "zh-min-nan",
  16. "lt", "hr", "sl", "et", "ce", "gl", "nn", "uz", "la", "vo",
  17. "el", "simple", "be", "az", "th", "ur", "ka", "hi", "oc", "ta",
  18. "mk", "mg", "new", "lv", "cy", "bs", "tt", "tl", "te", "pms",
  19. "be-tarask", "br", "sq", "ky", "ht", "jv", "tg", "ast", "zh-yue", "lb",
  20. "mr", "ml", "bn", "pnb", "is", "af", "sco", "ga", "ba", "fy",
  21. "cv", "lmo", "sw", "my", "an", "yo", "ne", "io", "gu", "nds",
  22. "scn", "bpy", "pa", "ku", "als", "kn", "bar", "ia", "qu", "su",
  23. "ckb", "bat-smg", "mn", "arz", "nap", "wa", "bug", "gd", "yi", "map-bms",
  24. "am", "mzn", "fo", "si", "nah", "li", "sah", "vec", "hsb", "or",
  25. "os", "mrj", "sa", "hif", "mhr", "roa-tara", "azb", "pam", "ilo",
  26. "sd", "ps", "se", "mi", "bh", "eml", "bcl", "xmf", "diq", "hak",
  27. "gan", "glk", "vls", "nds-nl", "rue", "bo", "fiu-vro", "co", "sc",
  28. "tk", "csb", "lrc", "vep", "wuu", "km", "szl", "gv", "crh", "kv",
  29. "zh-classical", "frr", "zea", "as", "so", "kw", "nso", "ay", "stq",
  30. "udm", "cdo", "nrm", "ie", "koi", "rm", "pcd", "myv", "mt", "fur",
  31. "ace", "lad", "gn", "lij", "dsb", "dv", "cbk-zam", "ext", "gom",
  32. "kab", "ksh", "ang", "mai", "mwl", "lez", "gag", "ln", "ug", "pi",
  33. "pag", "frp", "sn", "nv", "av", "pfl", "haw", "xal", "krc", "kaa",
  34. "rw", "bxr", "pdc", "to", "kl", "nov", "arc", "kbd", "lo", "bjn",
  35. "pap", "ha", "tet", "ki", "tyv", "tpi", "na", "lbe", "ig", "jbo",
  36. "roa-rup", "ty", "jam", "za", "kg", "mdf", "lg", "wo", "srn", "ab",
  37. "ltg", "zu", "sm", "chr", "om", "tn", "chy", "rmy", "cu", "tw", "tum",
  38. "xh", "bi", "rn", "pih", "got", "ss", "pnt", "bm", "ch", "mo", "ts",
  39. "ady", "iu", "st", "ee", "ny", "fj", "ks", "ak", "ik", "sg", "ve",
  40. "dz", "ff", "ti", "cr", "ng", "cho", "kj", "mh", "ho", "ii", "aa", "mus", "hz", "kr"]
  41. # search-url
  42. base_url = 'https://{language}.wikipedia.org/'
  43. search_postfix = 'w/api.php?'\
  44. 'action=query'\
  45. '&format=json'\
  46. '&{query}'\
  47. '&prop=extracts|pageimages'\
  48. '&exintro'\
  49. '&explaintext'\
  50. '&pithumbsize=300'\
  51. '&redirects'
  52. # set language in base_url
  53. def url_lang(lang):
  54. lang = lang.split('-')[0]
  55. if lang == 'all' or lang not in supported_languages:
  56. language = 'en'
  57. else:
  58. language = lang
  59. return base_url.format(language=language)
  60. # do search-request
  61. def request(query, params):
  62. if query.islower():
  63. query += '|' + query.title()
  64. params['url'] = url_lang(params['language']) \
  65. + search_postfix.format(query=urlencode({'titles': query}))
  66. return params
  67. # get first meaningful paragraph
  68. # this should filter out disambiguation pages and notes above first paragraph
  69. # "magic numbers" were obtained by fine tuning
  70. def extract_first_paragraph(content, title, image):
  71. first_paragraph = None
  72. failed_attempts = 0
  73. for paragraph in content.split('\n'):
  74. starts_with_title = paragraph.lower().find(title.lower(), 0, len(title) + 35)
  75. length = len(paragraph)
  76. if length >= 200 or (starts_with_title >= 0 and (image or length >= 150)):
  77. first_paragraph = paragraph
  78. break
  79. failed_attempts += 1
  80. if failed_attempts > 3:
  81. return None
  82. return first_paragraph
  83. # get response from search-request
  84. def response(resp):
  85. results = []
  86. search_result = loads(resp.content)
  87. # wikipedia article's unique id
  88. # first valid id is assumed to be the requested article
  89. for article_id in search_result['query']['pages']:
  90. page = search_result['query']['pages'][article_id]
  91. if int(article_id) > 0:
  92. break
  93. if int(article_id) < 0:
  94. return []
  95. title = page.get('title')
  96. image = page.get('thumbnail')
  97. if image:
  98. image = image.get('source')
  99. extract = page.get('extract')
  100. summary = extract_first_paragraph(extract, title, image)
  101. if not summary:
  102. return []
  103. # link to wikipedia article
  104. wikipedia_link = url_lang(resp.search_params['language']) \
  105. + 'wiki/' + quote(title.replace(' ', '_').encode('utf8'))
  106. results.append({'url': wikipedia_link, 'title': title})
  107. results.append({'infobox': title,
  108. 'id': wikipedia_link,
  109. 'content': summary,
  110. 'img_src': image,
  111. 'urls': [{'title': 'Wikipedia', 'url': wikipedia_link}]})
  112. return results