Разбор шаблона Wikitext Wikipedia С именем Parameters для извлечения данных из Taxobox
Используя Python, я пытаюсь извлечь данные из нескольких "полей" Таксобокса Википедии (инфобокс, который обычно отображается для каждой страницы видов животных или растений, см., например, здесь: https://en.wikipedia.org/wiki/Okapi).
Решение, представленное здесь (Как использовать Wikipedia API, чтобы получить раздел боковой панели?) интересен, но не полезен в моем случае, так как меня интересуют данные из более низкой таксономической категории (видов).
Чего я хочу, так это способ (максимально питонский) получить доступ к каждому полю в Таксобоксе, а затем получить данные (возможно, в виде словаря), представляющие интерес.
Заранее Благодарю за любую помощь.
EDIT : здесь (https://github.com/siznax/wptools ) - это еще одно хорошее решение, которое должно быть тем, что мне нужно, но, к сожалению, это набор инструментов командной строки (помимо зависимых от других инструментов командной строки, доступных только в Linux), а не библиотека Python.
EDIT2 : wptools теперь это библиотека (python 2,3).
2 ответа:
@maurobio, @jimhark
wptools
- это библиотека python (2+3). Оно будет дайте вам любой инфобокс с "коробкой" в названии в виде pythondict
, но возможно, вы захотите использовать Викиданные (например, okapi https://www.wikidata.org/wiki/Q82037 ) потому что инфобоксены грязны (чтобы мягко говоря). Если вы сосредоточитесь на Викиданных , то все выиграют, иwptools
может получить Викиданные для вас тоже. Мы недавно обновили wptools, так что он получает все Викиданные по умолчанию.Вы можете получите данные infobox в примере ниже на некоторых языках, но, как указывает @biojl, wikitext имеет различную структуру на разных языках!
>>> page = wptools.page('Okapi') >>> page.get_parse() en.wikipedia.org (parse) Okapi en.wikipedia.org (imageinfo) File:Okapi2.jpg Okapi (en) data { image: <list(1)> {'kind': 'parse-image', u'descriptionshorturl':... infobox: <dict(9)> status, status_ref, name, image, taxon, autho... iwlinks: <list(4)> https://commons.wikimedia.org/wiki/Okapia_joh... pageid: 22709 parsetree: <str(39115)> <root><template><title>about</title><par... requests: <list(2)> parse, imageinfo title: Okapi wikibase: Q82037 wikidata_url: https://www.wikidata.org/wiki/Q82037 wikitext: <str(29930)> {{about|the animal}}{{good article}}{{use... } >>> page.data['infobox'] {'authority': '([[P.L. Sclater]], 1901)', 'image': 'Okapi2.jpg', 'image_caption': "An okapi at [[Disney's Animal Kingdom]] in [[Florida]].", 'name': 'Okapi', 'parent_authority': '[[Ray Lankester|Lankester]], 1901', 'status': 'EN', 'status_ref': '<ext><name>ref</name><attr> name=iucn</attr><inner>{{IUCN2008|assessor=IUCN SSC Antelope Specialist Group|year=2008|id=15188|title=Okapia johnstoni|downloaded=26 November 2013}} Database entry includes a brief justification of why this species is endangered.</inner><close></ref></close></ext>', 'status_system': 'IUCN3.1', 'taxon': 'Okapia johnstoni'}
Однако, поскольку он структурирован, вы можете получить Викиданные на многих языках, например
Не забывайте, что вы можете редактировать Викиданные на своем родном языке. Существуют инструменты , позволяющие редактировать большое количество страниц Викиданных.>>> page = wptools.page('Okapi', lang='fr') >>> page.get_wikidata() www.wikidata.org (wikidata) Okapi www.wikidata.org (labels) P646|P349|P373|P685|P627|Q16521|Q7432|Q... fr.wikipedia.org (imageinfo) File:Okapia johnstoni -Marwell Wildl... Okapi (fr) data { aliases: <list(2)> Mondonga, Okapia johnstoni claims: <dict(26)> P646, P181, P935, P815, P373, P1417, P685, P1... description: espèce de mammifères image: <list(2)> {'kind': 'wikidata-image', u'descriptionshortur... label: Okapi labels: <dict(31)> P646, P373, P685, P627, Q16521, Q7432, Q20415... modified: <dict(1)> wikidata pageid: 84481 requests: <list(3)> wikidata, labels, imageinfo title: Okapi what: taxon wikibase: Q82037 wikidata: <dict(26)> identifiant BioLib (P838), taxon supérieur ... wikidata_url: https://www.wikidata.org/wiki/Q82037 } >>> page.data['wikidata'] {u'carte de r\xe9partition (P181)': u'Okapi distribution.PNG', u'cat\xe9gorie Commons (P373)': u'Okapia johnstoni', u'dur\xe9e de gestation (P3063)': {u'amount': u'+14.5', u'lowerBound': u'+14.0', u'unit': u'http://www.wikidata.org/entity/Q5151', u'upperBound': u'+15.0'}, u'd\xe9crit par (P1343)': u'encyclop\xe9die Otto (Q2041543)', u'galerie Commons (P935)': u'Okapia johnstoni', u'identifiant ARKive (P2833)': u'okapi/okapia-johnstoni', u'identifiant Animal Diversity Web (P4024)': u'Okapia_johnstoni', u'identifiant Biblioth\xe8que nationale de la Di\xe8te (P349)': u'01092792', u'identifiant BioLib (P838)': u'33523', u'identifiant Encyclopedia of Life (P830)': u'308387', u'identifiant Encyclop\xe6dia Britannica en ligne (P1417)': u'animal/okapi', u'identifiant Fossilworks (P842)': u'149380', u'identifiant Freebase (P646)': u'/m/05pf4', u'identifiant GBIF (P846)': u'2441207', u'identifiant ITIS (P815)': u'625037', u'identifiant Mammal Species of the World (P959)': u'14200484', u'identifiant NCBI (P685)': u'86973', u'identifiant UICN (P627)': u'15188', u'identifiant de la Grande Encyclop\xe9die russe en ligne (P2924)': u'2290412', u'image (P18)': [u'Okapia johnstoni -Marwell Wildlife, Hampshire, England-8a.jpg', u'Okapia johnstoni1.jpg'], u"nature de l'\xe9l\xe9ment (P31)": u'taxon (Q16521)', u'nom scientifique du taxon (P225)': u'Okapia johnstoni', u'nom vernaculaire (P1843)': [u'Okapi', u'Okapi'], u'rang taxinomique (P105)': u'esp\xe8ce (Q7432)', u'statut de conservation UICN (P141)': u'esp\xe8ce en danger (Q11394)', u'taxon sup\xe9rieur (P171)': u'Okapia (Q1872039)'}
EDIT : мы добавили более общий синтаксический анализатор, который должен работать (в некоторой степени) с любым синтаксисом infobox, например
Надеюсь, это поможет.>>> page = wptools.page('Okapi', lang='fr') >>> page.get_parse() fr.wikipedia.org (parse) Okapi Okapi (fr) data { infobox: <dict(2)> count, boxes ... } >>> page.data['infobox']['count'] 13 >>> page.data['infobox']['boxes'] [{u'Taxobox d\xe9but': [[{'index': '1'}, 'animal'], [{'index': '2'}, "''Okapia johnstoni''"], [{'index': '3'}, 'Okapi2.jpg'], [{'index': '4'}, 'Okapi']]}, {'Taxobox': [[{'index': '1'}, 'embranchement'], [{'index': '2'}, 'Chordata']]}, {'Taxobox': [[{'index': '1'}, 'classe'], [{'index': '2'}, 'Mammalia']]}, {'Taxobox': [[{'index': '1'}, 'sous-classe'], [{'index': '2'}, 'Theria']]}, {'Taxobox': [[{'index': '1'}, 'ordre'], [{'index': '2'}, 'Artiodactyla']]}, {'Taxobox': [[{'index': '1'}, 'famille'], [{'index': '2'}, 'Giraffidae']]}, {'Taxobox taxon': [[{'index': '1'}, 'animal'], [{'index': '2'}, 'genre'], [{'index': '3'}, 'Okapia'], [{'index': '4'}, '[[Edwin Ray Lankester|Lankester]], [[1901]]']]}, {'Taxobox taxon': [[{'index': '1'}, 'animal'], [{'index': '2'}, u'esp\xe8ce'], [{'index': '3'}, 'Okapia johnstoni'], [{'index': '4'}, '([[Philip Lutley Sclater|Sclater]], [[1901]])']]}, {'Taxobox synonymes': [[{'index': '1'}, "* ''Equus johnstoni'' <small>P.L. Sclater, 1901</small>"]]}, {'Taxobox UICN': [[{'index': '1'}, 'EN'], [{'index': '2'}, 'A2abcd+4abcd']]}, {u'Taxobox r\xe9partition': [[{'index': '1'}, 'Okapi map.jpg']]}, {u'Taxobox r\xe9partition': [[{'index': '1'}, 'Okapi distribution.PNG']]}, {'Taxobox fin': []}]
{@siznax опубликовал лучший ответ. Я оставляю свой ответ здесь только в качестве примера использования API wiki и анализа результатов. Это будет иметь практическую пользу только в том случае, если библиотека, подобная wptools, по какой-то причине не сможет удовлетворить ваши потребности.}
Это значительное переписывание, которое включает в себя (более) правильный синтаксический анализатор, чтобы соответствовать закрывающим двойным скобкам шаблона '}}'. Кроме того, упрощает запрос различных имен шаблонов и включает в себя main (), чтобы разрешить тестирование из оболочки / команды линия.
import sys import re import requests import json wikiApiRoot = 'https://en.wikipedia.org/w/api.php' # returns the position past the requested token or end of string if not found def FindToken(text, token, start=0): pos = text.find(token, start) if -1 == pos: nextTokenPos = len(text) else: nextTokenPos = pos return nextTokenPos + len(token) # Get the contents of the template as text def GetTemplateText(wikitext, templateName): templateTag = '{{' + templateName startPos = FindToken(wikitext, templateTag) if (len(wikitext) <= startPos): # Template not found return None openCount = 1 curPos = startPos nextOpenPos = FindToken(wikitext, '{{', curPos) nextClosePos = FindToken(wikitext, '}}', curPos) # scan for template's matching close braces while 0 < openCount: if nextOpenPos < nextClosePos: openCount += 1 curPos = nextOpenPos nextOpenPos = FindToken(wikitext, '{{', curPos) else: openCount -= 1 curPos = nextClosePos nextClosePos = FindToken(wikitext, '}}', curPos) templateText = wikitext[startPos:curPos-2] return templateText def GetTemplateDict(title, templateName='Taxobox'): templateDict = None # Get data from Wikipedia: resp = requests.get(wikiApiRoot + '?action=query&prop=revisions&' + 'rvprop=content&rvsection=0&format=json&redirects&titles=' + title) # Get the response text into a JSON object: rjson = json.loads(resp.text) # Pull out the text for the revision: wikitext = rjson['query']['pages'].values()[0]['revisions'][0]['*'] # Parse the text for the template templateText = GetTemplateText(wikitext, templateName) if templateText: # Parse templateText to get named properties templateItemIter = re.finditer( r'\|\s*(\w*)\s*=\s*([^\n]*)\n', templateText, re.M) templateList = [item.groups([0,1]) for item in templateItemIter] templateDict = dict(templateList) return templateDict def main(): import argparse import pprint parser = argparse.ArgumentParser() parser.add_argument('title', nargs='?', default='Okapia_johnstoni', help='title of the desired article') parser.add_argument('template', nargs='?', default='Taxobox', help='name of the desired template') args = parser.parse_args() templateDict = GetTemplateDict(args.title, args.template) pprint.pprint(templateDict) if __name__ == "__main__": main()
GetTemplateDict возвращает словарь записей таксобокса страницы. Для страницы Okapi это включает:
- биномиальный
- binomial_authority
- classis
- familia
- род
- genus_authority
- изображение
- image_caption
- ОРДО
- филум
- regnum
- виды
- статус
- status_ref
- status_system
- тренд
Я ожидаю фактического элементы для разных страниц.
Значения словаря-это оформленный текст Википедии:
>>> taxoDict['familia'] '[[Giraffidae]]'
Поэтому может потребоваться дополнительный синтаксический анализ или фильтрация.