2012-09-03 83 views
8

我想写一个python程序,可以搜索维基百科的人的出生和死亡日期。例如,阿尔伯特爱因斯坦1879年3月14日出生;死亡:4月18日1955年解析维基百科的出生和死亡日期?

我开始与Fetch a Wikipedia article with Python

import urllib2 
opener = urllib2.build_opener() 
opener.addheaders = [('User-agent', 'Mozilla/5.0')] 
infile = opener.open('http://en.wikipedia.org/w/api.php?action=query&prop=revisions&rvprop=content&rvsection=0&titles=Albert_Einstein&format=xml') 
page2 = infile.read() 

这工作尽可能去。 page2是来自Albert Einstein维基百科页面的部分的xml表示形式。

我看了这个教程,现在我有了xml格式的页面... http://www.travisglines.com/web-coding/python-xml-parser-tutorial,但我不明白如何从xml中获取我想要的信息(出生和死亡日期)。我觉得我一定要接近,然而,我不知道如何从这里出发。

编辑

经过几次的反应,我已经安装了BeautifulSoup。我现在的阶段,我可以打印:

import BeautifulSoup as BS 
soup = BS.BeautifulSoup(page2) 
print soup.getText() 
{{Infobox scientist 
| name  = Albert Einstein 
| image  = Einstein 1921 portrait2.jpg 
| caption  = Albert Einstein in 1921 
| birth_date = {{Birth date|df=yes|1879|3|14}} 
| birth_place = [[Ulm]], [[Kingdom of Württemberg]], [[German Empire]] 
| death_date = {{Death date and age|df=yes|1955|4|18|1879|3|14}} 
| death_place = [[Princeton, New Jersey|Princeton]], New Jersey, United States 
| spouse  = [[Mileva Marić]] (1903–1919)<br>{{nowrap|[[Elsa Löwenthal]] (1919–1936)}} 
| residence = Germany, Italy, Switzerland, Austria, Belgium, United Kingdom, United States 
| citizenship = {{Plainlist| 
* [[Kingdom of Württemberg|Württemberg/Germany]] (1879–1896) 
* [[Statelessness|Stateless]] (1896–1901) 
* [[Switzerland]] (1901–1955) 
* [[Austria–Hungary|Austria]] (1911–1912) 
* [[German Empire|Germany]] (1914–1933) 
* United States (1940–1955) 
}} 

所以,更接近,但我仍然不知道如何在这种格式返回death_date。除非我开始用re解析东西?我可以做到这一点,但我觉得我会为这项工作使用错误的工具。

+0

XML解析器不会帮你进一步。阅读JBernardo所说的内容:以json格式获取数据并使用专用的MW分析器。 – georg

+0

我附上了完整的代码,并且都使用/不使用're'来解析它。 –

+0

请不要试图通过您的用户代理模拟浏览器。根据[维基媒体用户代理政策](http://meta.wikimedia.org/wiki/User-Agent_policy),您应该使用“带有联系信息的信息性用户代理字符串”。 – svick

回答

7

您可以考虑使用库如BeautifulSouplxml解析响应html/xml。

您可能还想看看Requests,它有更简洁的API来提出请求。


下面是使用RequestsBeautifulSoupre,可以说不是最好的解决这里的工作代码,但它是非常灵活的,可扩展为类似的问题:

import re 
import requests 
from bs4 import BeautifulSoup 

url = 'http://en.wikipedia.org/w/api.php?action=query&prop=revisions&rvprop=content&rvsection=0&titles=Albert_Einstein&format=xml' 

res = requests.get(url) 
soup = BeautifulSoup(res.text, "xml") 

birth_re = re.search(r'(Birth date(.*?)}})', soup.revisions.getText()) 
birth_data = birth_re.group(0).split('|') 
birth_year = birth_data[2] 
birth_month = birth_data[3] 
birth_day = birth_data[4] 

death_re = re.search(r'(Death date(.*?)}})', soup.revisions.getText()) 
death_data = death_re.group(0).split('|') 
death_year = death_data[2] 
death_month = death_data[3] 
death_day = death_data[4] 

每@ JBernardo的建议使用JSON数据和mwparserfromhell,这个特定用例的更好的答案:

import requests 
import mwparserfromhell 

url = 'http://en.wikipedia.org/w/api.php?action=query&prop=revisions&rvprop=content&rvsection=0&titles=Albert_Einstein&format=json' 

res = requests.get(url) 
text = res.json["query"]["pages"].values()[0]["revisions"][0]["*"] 
wiki = mwparserfromhell.parse(text) 

birth_data = wiki.filter_templates(matches="Birth date")[0] 
birth_year = birth_data.get(1).value 
birth_month = birth_data.get(2).value 
birth_day = birth_data.get(3).value 

death_data = wiki.filter_templates(matches="Death date")[0] 
death_year = death_data.get(1).value 
death_month = death_data.get(2).value 
death_day = death_data.get(3).value 
+1

+1为BeautifulSoup。这是OP需要的。 –

+1

您是否检查过数据以查看HTML/XML解析器是否有帮助?提示:它不会 – JBernardo

+0

@JBernardo你是对的,内容是在同一个XML标签。虽然看起来像JSON格式有同样的问题。我认为你建议的解析器之一会解析标签内的数据? –

5

第一张:维基百科API允许使用JSON而不是XML,这将使事情变得更容易。

:根本不需要使用HTML/XML解析器(内容不是HTML,也不需要容器)。你需要解析的是这个Wiki格式在JSON的“revisions”标签里面。

检查一些维基解析器here


什么似乎是这里混淆的是,API可以让你请求一个特定的格式(XML或JSON),但是这仅仅是在现实一些文本的容器格式要解析:

这一个:{{Birth date|df=yes|1879|3|14}}

有了上面的链接提供的解析器之一,你将能够做到这一点。

+0

好的,所以我可以把它看作JSON:'infile = opener.open('http://en.wikipedia.org/w/api.php?action=query&prop=revisions&rvprop=content&rvsection=0&titles=Albert_Einstein&format=json' )' 看看你链接到的Wiki解析器,我看到很多XML/HTML,但没有列出JSON。你有推荐的吗? – JBWhitmore

+0

@JBWhitmore'json'模块附带了Python。它仅仅是一个你想分析真实数据的容器。这些数据不是XML或HTML或JSON。它是一些特定的Wiki格式 – JBernardo

+0

@JBWhitmore你想解析这种数据:'{{Birth date | df = yes | 1879 | 3 | 14}}',链接中的一个模块将帮助你。 – JBernardo

4

首先,使用pywikipedia。它允许您通过高级抽象接口查询文章文本,模板参数等。其次,我会去与Persondata模板(看文章的结尾)。另外,从长远来看,您可能对Wikidata感兴趣,这需要几个月的时间才能推出,但它会使维基百科文章中的大部分元数据易于查询。

1

persondata模板现在已被弃用,您应该改为访问Wikidata。请参阅Wikidata:Data access。我从2012年开始回答如下:

你应该做的是解析在大多数自传文章中找到的{{persondata}}模板。有existing tools for easily extracting such data programmatically,与您现有的知识和其他有用的答案我相信你可以做到这一点。

+0

对于它的价值来说,如果它稍后保存其他人的话, Persondata似乎现在已被弃用。该链接指出,“...现在已经被删除,从现在开始,这些数据应该被添加到Wikidata,而不是引用。” –

+0

确实。我会编辑我的答案。 –