Andaba yo buscando una fuente de datos para una visualización que quiero montar y me veía, como en aquella gráfica que hice de películas de James Bond, tirando de tablas en la Wikipedia y extrayendo información utilizando alguna librería de scraping.
El caso es que tenía en la cabeza desde hace tiempo echarle un ojo a Wikidata. Wikidata es un proyecto similar a la Wikipedia, pero en lugar de tener entradas en una enciclopedia tiene datos que puede leer fácilmente tanto una máquina como un ser humano. Para entendernos, en lugar de tener Mateo Morral tiene Q3047716. Esta página contiene más información sobre la estructura de datos empleada.
La gracia de todo esto es que Wikidata, a través de esta interfaz (o mediante algún lenguaje de programación que otro), acepta peticiones SPARQL. Aquí puede encontrarse una guía con instrucciones y varios ejemplos. Durante estos días pasados he estado trasteando con esto y aquí van algunas chapucillas que he conseguido hacer funcionar (o no).
Alcaldes de Montreal desde los 90
Aquí va el primer ejemplo que conseguí echar a andar:
SELECT ?mayor ?mayorLabel ?start_term ?end_term ?partyLabel WHERE {
?mayor (wdt:P31/wdt:P279*) wd:Q5. # look for human beings
?mayor wdt:P39 wd:Q177645. # that list "Mayor of Montreal" as occupation
?mayor p:P39 ?statement. # and from their term
?statement pq:P580 ?start_term. # obtain the start date
OPTIONAL {?statement pq:P582 ?end_term}. # and the end date, if present
OPTIONAL {?mayor p:P102 [ps:P102 ?party]}. # and the party, if present
FILTER(year(?start_term) >= 1990 || year(?end_term) >= 1990) # and just take people around 1990 onwards
SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE],en". }
}
ORDER BY ?start_term
Recapitulando (todo esto está en la guía que he enlazado allí arriba, pero para vagos):
- Las queries se forman mediante tripletes: qué, de qué tipo, cómo lo vamos a llamar (no necesariamente en ese orden).
- Las variables se llaman
?var
. - La última línea de la cláusula
WHERE
(SERVICE ...
) activa el uso de variables especiales,?varLabel
, que imprimen el valor de una variable en algún lenguaje humano. - Un Q5 es un humano. Un
Q177645 es un alcalde de Montreal.
Esta query inspecciona seres humanos que han sido (
P39
, ocupación) alcaldes de Montreal en algún momento. - Usando
OPTIONAL
podemos asignar variables que igual no están ahí. Es el equivalente de unLEFT JOIN
en SQL de toda la vida. - Aún estoy intentando comprender completamente cuándo usar cada modificador
(
wdt:
,wd:
,p:
,ps:
ypq:
). De momento estoy componiendo las queries hacia atrás: voy a un objecto que sé que tiene que estar en el resultado final y voy inspeccionando de qué tipo es cada elemento que necesito filtrar.
El resultado:
mayor mayorLabel start_term end_term partyLabel http://www.wikidata.org/entity/Q3171790 Jean Doré 1986-01-01T00:00:00Z 1994-01-01T00:00:00Z Montreal Citizens' Movement http://www.wikidata.org/entity/Q3384158 Pierre Bourque 1994-01-01T00:00:00Z 2001-01-01T00:00:00Z Vision Montreal http://www.wikidata.org/entity/Q1558936 Gérald Tremblay 2002-01-01T00:00:00Z 2012-11-05T00:00:00Z Quebec Liberal Party http://www.wikidata.org/entity/Q3307998 Michael Applebaum 2012-11-16T00:00:00Z 2013-06-18T00:00:00Z Union Montreal http://www.wikidata.org/entity/Q3219045 Laurent Blanchard 2013-06-25T00:00:00Z 2013-11-03T00:00:00Z Vision Montreal http://www.wikidata.org/entity/Q3022603 Denis Coderre 2013-11-03T00:00:00Z 2017-11-15T00:00:00Z Liberal Party of Canada http://www.wikidata.org/entity/Q27959212 Valérie Plante 2017-11-16T00:00:00Z
Esto es correcto a grandes rasgos, pero tiene sus cositas:
- No aparece el partido de la alcaldesa actual, que debería ser Project Montréal. Su página de la Wikipedia sí lo refleja, pero los datos de Wikidata, si lo he entendido bien, se rellenan de forma colaborativa e independiente, así que puede haber discrepancias (de hecho, hay discrepancias).
- Denis Coderre aparece como miembro del Partido Liberal. Aunque perteneció a ese partido, su campaña municipal la llevaba un partido llamado, directamente, Équipe Denis Coderre. Sin embargo, su nodo en Wikidata, Q3022603, lista únicamente el Partido Liberal.
Alcaldes de Madrid desde los 90
A ver si lo mismo funcionase, cambiando únicamente Q177645
por Q17078548
("Alcaldes de Madrid"), y especificando que ahora queremos el idioma de las
etiquetas en castellano:
mayor mayorLabel start_term end_term partyLabel http://www.wikidata.org/entity/Q2748778 José María Álvarez del Manzano 1979-04-03T00:00:00Z 2003-06-14T00:00:00Z Partido Popular http://www.wikidata.org/entity/Q2748778 José María Álvarez del Manzano 1979-04-03T00:00:00Z 2003-06-14T00:00:00Z Unión de Centro Democrático http://www.wikidata.org/entity/Q467829 Alberto Ruiz-Gallardón 1987-06-10T00:00:00Z 2003-05-25T00:00:00Z Partido Popular http://www.wikidata.org/entity/Q2827364 Agustín Rodríguez Sahagún 1987-06-30T00:00:00Z 1991-07-05T00:00:00Z Unión de Centro Democrático http://www.wikidata.org/entity/Q2827364 Agustín Rodríguez Sahagún 1987-06-30T00:00:00Z 1991-07-05T00:00:00Z Centro Democrático y Social http://www.wikidata.org/entity/Q467829 Alberto Ruiz-Gallardón 1987-07-28T00:00:00Z 1995-07-04T00:00:00Z Partido Popular http://www.wikidata.org/entity/Q2748778 José María Álvarez del Manzano 1989-01-01T00:00:00Z 1991-01-01T00:00:00Z Partido Popular http://www.wikidata.org/entity/Q2748778 José María Álvarez del Manzano 1989-01-01T00:00:00Z 1991-01-01T00:00:00Z Unión de Centro Democrático http://www.wikidata.org/entity/Q2827364 Agustín Rodríguez Sahagún 1989-06-29T00:00:00Z 1991-07-05T00:00:00Z Unión de Centro Democrático http://www.wikidata.org/entity/Q2827364 Agustín Rodríguez Sahagún 1989-06-29T00:00:00Z 1991-07-05T00:00:00Z Centro Democrático y Social http://www.wikidata.org/entity/Q9025210 Luis María Huete 1991-01-01T00:00:00Z 1995-01-01T00:00:00Z Partido Popular http://www.wikidata.org/entity/Q2748778 José María Álvarez del Manzano 1991-07-05T00:00:00Z 2003-06-14T00:00:00Z Partido Popular http://www.wikidata.org/entity/Q2748778 José María Álvarez del Manzano 1991-07-05T00:00:00Z 2003-06-14T00:00:00Z Unión de Centro Democrático http://www.wikidata.org/entity/Q467829 Alberto Ruiz-Gallardón 1995-01-01T00:00:00Z 2003-01-01T00:00:00Z Partido Popular http://www.wikidata.org/entity/Q9025210 Luis María Huete 1995-07-06T00:00:00Z 1999-07-14T00:00:00Z Partido Popular http://www.wikidata.org/entity/Q19592761 Manuela Carmena 1996-07-26T00:00:00Z 2001-11-07T00:00:00Z Ahora Madrid http://www.wikidata.org/entity/Q41266 Ana Botella 2003-06-14T00:00:00Z 2015-06-13T00:00:00Z Alianza Popular http://www.wikidata.org/entity/Q41266 Ana Botella 2003-06-14T00:00:00Z 2015-06-13T00:00:00Z Partido Popular http://www.wikidata.org/entity/Q467829 Alberto Ruiz-Gallardón 2003-06-14T00:00:00Z 2011-12-22T00:00:00Z Partido Popular http://www.wikidata.org/entity/Q2733245 Juan Barranco 2008-03-25T00:00:00Z 2011-06-06T00:00:00Z Partido Socialista Obrero Español http://www.wikidata.org/entity/Q467829 Alberto Ruiz-Gallardón 2011-11-30T00:00:00Z 2014-09-24T00:00:00Z Partido Popular http://www.wikidata.org/entity/Q5992655 Manuel Cobo Vega 2011-12-22T00:00:00Z 2011-12-27T00:00:00Z Partido Popular http://www.wikidata.org/entity/Q467829 Alberto Ruiz-Gallardón 2011-12-22T00:00:00Z 2014-09-23T00:00:00Z Partido Popular http://www.wikidata.org/entity/Q41266 Ana Botella 2011-12-27T00:00:00Z 2015-06-13T00:00:00Z Alianza Popular http://www.wikidata.org/entity/Q41266 Ana Botella 2011-12-27T00:00:00Z 2015-06-13T00:00:00Z Partido Popular http://www.wikidata.org/entity/Q19592761 Manuela Carmena 2015-06-13T00:00:00Z Ahora Madrid http://www.wikidata.org/entity/Q19592761 Manuela Carmena 2015-06-13T00:00:00Z Ahora Madrid
Esto, esto... esto es muy feo por varios motivos, pero vamos a ceñirnos a la salida de la query. Están pasando varias cosas:
- Hay gente que estuvo en varios partidos y esto hace que aparezcan duplicados
(o casi duplicados). Vamos a pensar en un
JOIN
mal filtrado. - De igual forma, hay gente que fue alcalde / alcaldesa de Madrid, pero también tuvo otros cargos, bien antes, bien después. Lo mismo que en el punto anterior.
Dio la casualidad de que la lista de alcaldes de Montreal sale limpia porque no tiene estos problemas, pero aquí hay que afinar un poco más. Tenemos que asegurarnos de que:
- El cargo que estamos obteniendo es la alcaldía (el objeto
?statement
que filtramos). - El partido que estamos obteniendo es aquél al que pertenecieron mientras ejercían el cargo.
El primer punto es fácil. El segundo es imposible, o al menos no he encontrado por ninguna parte la fecha de las distintas afiliaciones. Por ejemplo, podemos acudir a Álvarez del Manzano (Q2748778) para ver que esa información no aparece. De todas formas, si arreglamos el primer punto y ampliamos la lista a alcaldes desde los 80 en adelante, pasan otras cosas:
SELECT ?mayor ?mayorLabel ?start_term ?end_term ?partyLabel WHERE {
?mayor (wdt:P31/wdt:P279*) wd:Q5. # look for human beings
?mayor wdt:P39 wd:Q17078548. # that list "Mayor of Madrid" as occupation
?mayor p:P39 ?statement. # and from their term
?statement ps:P39 wd:Q17078548. # **and only for the term as "Mayor of Madrid"**
?statement pq:P580 ?start_term. # obtain the start date
OPTIONAL {?statement pq:P582 ?end_term}. # and the end date if present
OPTIONAL {?mayor p:P102 [ps:P102 ?party]}. # and the party if present
FILTER(year(?start_term) >= 1980 || year(?end_term) >= 1980) # and just take people around 1980 onwards
SERVICE wikibase:label { bd:serviceParam wikibase:language "es". }
}
ORDER BY ?start_term
mayor mayorLabel start_term end_term partyLabel http://www.wikidata.org/entity/Q1344166 Enrique Tierno Galván 1979-04-19T00:00:00Z 1986-01-19T00:00:00Z Partido Socialista Obrero Español http://www.wikidata.org/entity/Q2827364 Agustín Rodríguez Sahagún 1989-06-29T00:00:00Z 1991-07-05T00:00:00Z Unión de Centro Democrático http://www.wikidata.org/entity/Q2827364 Agustín Rodríguez Sahagún 1989-06-29T00:00:00Z 1991-07-05T00:00:00Z Centro Democrático y Social http://www.wikidata.org/entity/Q2748778 José María Álvarez del Manzano 1991-07-05T00:00:00Z 2003-06-14T00:00:00Z Partido Popular http://www.wikidata.org/entity/Q2748778 José María Álvarez del Manzano 1991-07-05T00:00:00Z 2003-06-14T00:00:00Z Unión de Centro Democrático http://www.wikidata.org/entity/Q467829 Alberto Ruiz-Gallardón 2003-06-14T00:00:00Z 2011-12-22T00:00:00Z Partido Popular http://www.wikidata.org/entity/Q5992655 Manuel Cobo Vega 2011-12-22T00:00:00Z 2011-12-27T00:00:00Z Partido Popular http://www.wikidata.org/entity/Q41266 Ana Botella 2011-12-27T00:00:00Z 2015-06-13T00:00:00Z Alianza Popular http://www.wikidata.org/entity/Q41266 Ana Botella 2011-12-27T00:00:00Z 2015-06-13T00:00:00Z Partido Popular http://www.wikidata.org/entity/Q19592761 Manuela Carmena 2015-06-13T00:00:00Z Ahora Madrid
Seguimos teniendo gente duplicada (por pertenencia a varios partidos), pero vamos a ignorar eso, que hay otros asuntos. Resulta que ahora pasamos de Tierno Galván a Rodríguez Sahagún directamente. ¿Por dónde se nos ha caído Juan Barranco? Resulta que Juan Barranco, alias Q2733245, aparece listado como Alcalde de Madrid pero sin fecha de inicio ni fin. Como estamos pidiendo que la fecha de inicio sea obligatoria, su nodo no aparece en el resultado final.
Películas de James Bond
Supongamos que quiero replicar el artículo de James Bond que enlacé antes. Necesito una tabla con las siguientes columnas:
- Título de la película.
- Año de estreno.
- Actor que interpretó a Bond.
- Recaudación en taquilla.
Como he comentado antes, lo más sencillo es partir de una entrada que sabemos que tiene que aparecer en el resultado final y trabajar hacia atrás. Por ejemplo: Skyfall.
Esto es lo que he conseguido:
SELECT ?film ?filmLabel (MIN(?publication_date) AS ?first_pub_date) ?actor_nameLabel ?box_office
WHERE {
SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE],en". }
# Select films of the James Bond series published in the past
?film (wdt:P31/wdt:P279*) wd:Q11424. # films
?film wdt:P179 wd:Q2484680. # of the James Bond series
?film p:P577 [ps:P577 ?publication_date]. # get the publication date
FILTER (year(?publication_date) <= 2018) # remove "Bond 25" from the list
# Cast member: get who played James Bond
?film p:P161 ?actorStatement. # actors in the movie
?actorStatement pq:P453 wd:Q2009573. # but only the one playing Bond
?actorStatement ps:P161 ?actor_name.
# Box office
?film p:P2142 ?box_officeStatement.
?box_officeStatement ps:P2142 ?box_office
}
GROUP BY ?film ?filmLabel ?actor_nameLabel ?box_office
ORDER BY ?first_pub_date
film filmLabel first_pub_date actor_nameLabel box_office http://www.wikidata.org/entity/Q107724 Thunderball 1965-01-01T00:00:00Z Sean Connery 205000000 http://www.wikidata.org/entity/Q334780 Moonraker 1979-06-26T00:00:00Z Roger Moore 210300000 http://www.wikidata.org/entity/Q212145 The World Is Not Enough 1999-11-08T00:00:00Z Pierce Brosnan 361832400 http://www.wikidata.org/entity/Q30931 Die Another Day 2002-11-22T00:00:00Z Pierce Brosnan 432000000 http://www.wikidata.org/entity/Q4941 Skyfall 2012-10-23T00:00:00Z Daniel Craig 1109000000 http://www.wikidata.org/entity/Q18602670 Spectre 2015-10-26T00:00:00Z Daniel Craig 880674609
Aprovecho esta query para enseñar que aquí también se puede meter un GROUP BY
:
hay películas que tienen varias fechas de estreno --no se estrenan a la vez en
todo el mundo--, así que aquí estoy cogiendo la primera. El problema ahora es
que, de todas las películas de James Bond, solamente 6 tienen toda la
información necesaria; a todas las demás les falta la recaudación en taquilla.
No solamente eso, sino que desconozco exactamente en qué unidad está el
resultado: sé que son dólares americanos, pero no sé si son del año del estreno
o están normalizados de alguna forma.
Conclusiones
Wikidata es prometedor. La idea de tener un equivalente wikipedístico al que preguntarle datos directamente para procesarlos después, sin tener que pasar por el tedio de analizar código HTML, es cañera. Aunque escribir las queries es complicado inicialmente, después de un par de días de ensayo y error la mayoría de las cosas van saliendo solas, pero el problema principal no es ese: son los datos incompletos, contradictorios o erróneos. Si he entendido bien el sentido del proyecto, en algún momento la propia Wikipedia utilizará parcialmente información de Wikidata, pero todavía no estamos ahí.