2012-09-03 18 views
8

Sto provando a scrivere un programma python in grado di cercare wikipedia per le date di nascita e morte per le persone.Parse date di nascita e morte da Wikipedia?

Ad esempio, Albert Einstein nacque: 14 marzo 1879; è morto: 18 aprile 1955.

Ho iniziato con 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() 

Questo funziona per quanto va. page2 è la rappresentazione xml della sezione dalla pagina wikipedia di Albert Einstein.

E ho guardato questo tutorial, ora che ho la pagina in formato xml ... http://www.travisglines.com/web-coding/python-xml-parser-tutorial, ma non capisco come ottenere le informazioni che voglio (date di nascita e morte) dal xml. Mi sento come se dovessi essere vicino, eppure, non ho idea di come procedere da qui.

EDIT

Dopo alcune risposte, ho installato BeautifulSoup. Ora sono nella fase in cui posso stampare:

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) 
}} 

Quindi, molto più vicino, ma io ancora non so come restituire il death_date in questo formato. A meno che non inizi a analizzare le cose con re? Posso farlo, ma sento che utilizzerei lo strumento sbagliato per questo lavoro.

+0

Un parser XML non ti aiuterà ulteriormente. Leggi cosa dice JBernardo: recupera i dati in formato json e usa un parser dedicato MW. – georg

+0

Ho allegato il codice completo sia con che senza 're' per analizzarlo. –

+0

Per favore, non provare a imitare un browser dal tuo User-Agent. Secondo [la politica di utente-agente di Wikimedia] (http://meta.wikimedia.org/wiki/User-Agent_policy), è necessario utilizzare "una stringa di User-Agent informativo con le informazioni di contatto". – svick

risposta

7

È possibile considerare l'utilizzo di una libreria come BeautifulSoup o lxml per analizzare la risposta html/xml.

Si potrebbe anche voler dare un'occhiata a Requests, che ha un'API molto più pulita per fare richieste.


Ecco il codice di lavoro utilizzando Requests, BeautifulSoup e re, probabilmente non è la soluzione migliore qui, ma è abbastanza flessibile e può essere esteso per problemi simili:

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] 

Per @ Suggerimento di JBernardo utilizzando i dati JSON e mwparserfromhell, una risposta migliore per questo particolare caso d'uso:

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 per BeautifulSoup. Questo è ciò di cui OP ha bisogno. –

+1

Hai persino controllato i dati per vedere se un parser HTML/XML può essere d'aiuto? suggerimento: non sarà – JBernardo

+0

@JBernardo Hai ragione, i contenuti sono nello stesso tag XML. Anche se sembra che il formato JSON abbia lo stesso problema. Penso che uno dei parser che hai suggerito avrebbe analizzato i dati all'interno del tag? –

5

Primo: L'API di wikipedia consente l'uso di JSON anziché XML e questo renderà le cose molto più semplici.

Secondo: Non è necessario utilizzare parser HTML/XML (il contenuto non è HTML né il contenitore deve essere). Quello che devi analizzare è il formato Wiki all'interno del tag "revisioni" del JSON.

controllare alcuni parser Wiki here


Quello che sembra confondere qui è che l'API consente di richiedere un certo formato (XML o JSON), ma che è è solo un contenitore per un testo nel reale formato che si desidera analizzare:

Questa: {{Birth date|df=yes|1879|3|14}}

Con uno dei parser fornite nel link qui sopra, si sarà in grado di farlo.

+0

OK, quindi posso leggerlo come JSON: 'infile = opener.open ('http://en.wikipedia.org/w/api.php?action=query&prop=revisions&rvprop=content&rvsection=0&titles=Albert_Einstein&format=json') ' Guardando i parser Wiki a cui sei collegato, vedo un sacco di XML/HTML ma nessun JSON elencato. Ne hai uno consigliato? – JBWhitmore

+0

@JBWhimmore il modulo 'json' viene fornito con Python. È ** solo ** un contenitore per i dati reali che si desidera analizzare. Questi dati non sono in XML o HTML o JSON. È in qualche specifico formato Wiki – JBernardo

+0

@JBWhmoremore Vuoi analizzare questo tipo di dati: '{{Data di nascita | df = si | 1879 | 3 | 14}}' e uno dei moduli nel link ti aiuterà. – JBernardo

4

Innanzitutto, utilizzare pywikipedia. Ti permette di interrogare il testo dell'articolo, i parametri del modello ecc. Attraverso un'interfaccia astratta di alto livello. Secondo, andrei con il modello Persondata (guarda verso la fine dell'articolo). Inoltre, a lungo termine, potresti essere interessato a Wikidata, che richiederà diversi mesi per essere introdotto, ma renderà la maggior parte dei metadati degli articoli di Wikipedia facilmente consultabili.

1

Il modello persondata è obsoleto e si dovrebbe invece accedere a Wikidata. Vedi Wikidata:Data access. La mia prima (ora deprecato) risposta a partire dal 2012 è stata la seguente:

Che cosa si dovrebbe fare è quello di analizzare il modello {{persondata}} trovato nella maggior parte degli articoli biografici. Ci sono existing tools for easily extracting such data programmatically, con le tue conoscenze esistenti e le altre utili risposte sono certo che puoi farlo funzionare.

+0

Per quello che vale, nel caso in cui salvi qualcun altro un clic dopo, Sembra che Persondata ora sia deprecato. Il link dice che "... è stato rimosso. D'ora in poi, tali dati dovrebbero essere aggiunti, con una citazione, a Wikidata". –

+0

Infatti. Modificherò la mia risposta. –