Obtener información de Wikipedia a través de su API
Desde hace un tiempo me venía planteando la posibilidad de tomar información de Wikipedia para completar la información de ciertos ítems. Pensé, para qué reescribir información que ya existe de forma libre? mejor sería aportar y mejorar los artículos de Wikipedia.

Por programas como Amarok o Clementine (que uso a diario), sabía que Wikipedia tenía alguna especie de web service para tomar información. Buscando encontré que MediaWiki, el software detrás de Wikipedia, provee una API que permite realizar consultas de diversos tipos. Esta web service viene habilitado por defecto cuando instalan el software, y Wikipedia permite su uso de forma gratuita. La API no sólo permite consultar información, sino también modificar el contenido de los artículos en sus bases de datos.

Como la información provista en la descripción de la API me resultó algo escasa o muy desparramada, me pareció interesante explicar brevemente como realizar request de artículos.

Para empezar, necesitamos saber que la URL del web service es la siguiente:
  http://@lc.wikipedia.org/w/api.php
donde @lc debe reemplazarse por el código del lenguaje del artículo que se desea obtener. Por ejemplo, si queremos el artículo de la Wikipedia en inglés, el código será 'en' (http://en.wikipedia.org/w/api.php), mientras que para el español, el código será 'es' (http://es.wikipedia.org/w/api.php).
A esta URL deben pasarse dos parámetros obligatorios, y estos parámetros fuerzan el uso de otros para especificar lo que se desea obtener. Existen muchos posibles parámetros y estos se encuentran documentados en MediaWiki - API:Properties.

Los parámetros obligatorios para obtener contenido son los siguientes:
  - format: especifica en qué formato retornar el contenido. Los formatos disponibles actualmente son:
    - json: formato JSON. Soporta la opción callback que permite especificar una función javascript a llamar cuando la carga del contenido esté completa.
    - php: formato serialized de PHP.
    - wddx: formato WDDX.
    - xml
    - yaml
    - rawfm: formato JSON con elementos de debugging (HTML) y callback.
    - txt: PHP print_r().
    - dbg: PHP var_export().
    - dump: PHP var_dump().
    Si bien la API soporta múltiples formatos, tienen pensado removerlos y dejar sólo JSON. En el artículo me centraré sólo en el uso de JSON.
  - action: especifica qué acción realizar. MediaWiki soporta más de 15 acciones, las cuales están descriptas aquí. La acción que nos ocupa en nuestro caso es 'query'. query es una de las acciones más importantes y está documentada aquí.

Hasta ahora contamos con la siguiente URL para obtener contenido, a la cual iremos agregando parámetros según lo que necesitemos:
  http://en.wikipedia.org/w/api.php?format=json&action=query

Ahora bien, la acción 'query' requiere los siguientes parámetros adicionales para obtener contenido:
  - titles, pageids, revids: es necesario utilizar uno de estos tres parámetros para especificar la página que deseamos, ya sea por el título de la misma (titles), su ID (pageids) o el ID de la revisión (revids). Cabe aclarar aca que cada página tiene múltiples revisiones, siendo la más actual la que se está mostrando. Estos parámetros soportan requests de múltiples páginas a la vez, separando el título/ID/revID de cada una utilizando el símbolo | (ejemplo: titles=PáginaA|PáginaB|PáginaC). MediaWiki aconseja solicitar múltiples páginas a la vez para ahorrar procesamiento y ancho de banda.
  En caso de utilizar el título para obtener la página, es necesario normalizarlo antes. La normalización del título implica poner en mayúsculas la primer letra, reemplazar todos los espacios con underscore '_', y ajustar el nombre al lenguaje que se está solicitando.
  - prop: se utiliza para obtener diversos datos acerca de la/s página/s especificadas con titles/pageids/revids. Cada propiedad conlleva el uso de otro parámetro para especificar información adicional sobre lo que se desea. Las propiedades se encuentran documentadas aquí, siendo las que más nos interesan en nuestro caso, las siguientes:
    - info: recupera información básica acerca de una página. Este valor de prop requiere un parámetro adicional, que puede ser inprop (propiedades a obtener, separadas con el símbolo '|'), intoken o incontinue.
    - revisions: retorna las revisiones de la página solicitada, o bien la última revisión de cada una de las páginas listadas (en caso de solicitar más de una página). Revisions cuenta con varios posibles parámetros, de los cuales los que más nos interesan en este artículo son:
      - rvprop: indica qué propiedad obtener de cada revisión. Existen diversas propiedades que se pueden obtener, siendo 'content' la que nos interesa, dado que es la que indica que deseamos obtener el contenido de la revisión. Si no se especifica otro parámetro, se retornará sólo la revisión actual de la página.
      - rvparse: indica que el contenido retornado debe ser parseado y convertido a HTML. Si no se especifica este comando, el contenido será retornado en formato wikitext.
    - imageinfo/ii: obtiene información de imágenes. Esta propiedad también cuenta con varios posibles parámetros, de los cuales nos interesa iiprop. iiprop permite obtener distintos atributos de una imagen, y de estos nos resultan interesantes 'url' y 'size', que permiten obtener la URL donde se encuentra la imágen y el tamaño de la misma.
   
Además de los listados, los siguientes dos parámetros también son de mucha utilidad:
  - redirects: se puede utilizar en conjunto con titles, para que MediaWiki resuelva los redirects necesarios para llegar al contenido, en caso que el título solicitado realice un redirect.
  - continue: en muchos casos, no se retorna todo el contenido en un sólo request. Cuando esto sucede, MediaWiki incluye la variable continue en su respuesta para indicar que hay más contenido por retornar. Para estos casos, se puede utilizar el parámetro continue (sin ningún valor) y así obtener la continuación del último request.

Ya con la teoría, ahora podemos ver como todo esto funciona en la práctica. Como comenté anteriormente, las URLs que armaremos buscan obtener información en formato json, por lo que los parámetros format=json y action=query estarán en ellas.

Como caso de ejemplo tomemos la wiki en español de Mahatma Gandhi. Como no sabemos el ID de la página, podemos buscar usar el título. Para empezar, debemos normalizar el título antes de poder utilizarlo en la query. En este caso, debemos reemplazar el espacio por el underscore, es decir, queda Mahatma_Gandhi.
La información que deseamos traer es la última revisión del artículo, así que elegimos la propiedad "revisions" y el parámetro rvprop=content, para que traiga el contenido:
  http://es.wikipedia.org/w/api.php?format=json&action=query&titles=Mahatma_Gandhi&prop=revisions&rvprop=content

El formato del contenido retornado es el siguiente:
  {
    "query": información y resultado de la consulta. Es un objeto compuesto por:
    {
      "normalized": título normalizado
      "pages": lista de páginas retornadas por la consulta. Es un arreglo asociativo cuyos índices son los IDs de las páginas. Cada elemento del arreglo está compuesto por:
      {
         "ns":
         "pageid": el ID de la página.
         "revisions": arreglo que contiene todas las revisiones de la página. Está ordenado de revisión más nueva a más antigua, siendo 0 la versión actual. Cada uno de estos arreglos. Este arreglo contiene un arreglo con un solo ítem cuyo índice es el símbolo '*', y es éste el que contiene el contenido de la revisión.
         "title": el título de la página.
      }
    }
    "warnings": contiene warnings que arroja el servidor. Por ejemplo, cuando un título no se encuentra, se retorna un warning en este objeto.
  }
Según lo visto, el contenido de la revisión se puede acceder de la siguiente manera: respuesta.query.pages[].revisions[0]['*']. Si consultamos por una sola página, tendremos un sólo ID de página.

El contenido retornado es texto con formato wikitext. Wikitext es un lenguaje de marcado liviano, es decir, como HTML o LaTeX, pero mucho más simple. El mismo se encuentra descripto en Help:Wiki markup. Existen parsers para este lenguaje, programados en distintos lenguajes. Una lista de parsers se puede encontrar en MediaWiki - Alternative parsers.
En caso que deseen obtener texto formateado en HTML, pueden utilizar el parámetro rvparse de la siguiente manera:
  http://es.wikipedia.org/w/api.php?format=json&action=query&titles=Mahatma_Gandhi&prop=revisions&rvprop=content&rvparse

Cuando vemos el contenido retornado en formato wikitext, observamos que las imágenes no tienen el link a donde se encuentran hosteadas, sino una referencia como "Archivo:Gandhi Nehru Indira.jpg". Si normalizamos el nombre del archivo y adherimos el contenido de lo anterior a un link de Wikipedia, encontramos que se obtiene la imagen en el sitio de Wikipedia: http://es.wikipedia.org/wiki/Archivo:Gandhi_Nehru_Indira.jpg. Pero si queremos embeber la imagen en nuestro site, debemos conocer la URL de la imagen. Para ello se utiliza la propiedad imageinfo, el parámetro iiprop=url|size y el nombre normalizado de la siguiente manera:
  http://es.wikipedia.org/w/api.php?format=json&action=query&titles=Archivo:Gandhi_Nehru_Indira.jpg&prop=imageinfo&iiprop=url|size
La cual responde con un objeto similar al anterior, pero en este caso el arreglo "pages" contiene solo un ítem con índice "-1". Este ítem es un objeto que ahora contiene un atributo denominado imageinfo, que es un arreglo de imagenes. Como solicitamos sólo una imagen, tendrá un solo elemento. Cada elemento de este arreglo tiene el siguiente formato:
  "size": el tamaño de la imagen.
  "width": el ancho de la imagen.
  "height": el alto.
  "url": la URL donde la imagen se encuentra hosteada.
Es decir, la URL se puede obtener de la siguiente manera: respuesta.query.pages[-1].imageinfo[0].url

Bien, con esto ya podemos hacer consultas a Wikipedia y obtener tanto el texto como las imagenes. Formatear el texto obtenido, si lo obtienen en lenguaje wikitext, es otro tema. Estuve programando un parser en javascript, el cual interpreta parte del lenguaje, pero todo lo que se encuentra encerrado entre llaves "{}" tiene muchas variantes e interpretarlo todo no es tan simple. Algún día publicaré el código si es que lo termino. Entre los parsers que se encuentran en la página que cité, implementan parte de lenguaje, no se si hay alguno que interprete todo.

Espero que les resulte útil la información, ya que me costó un par de días interpretar e implementar lo básico de lo que provee esta API.

0 comentarios:

Publicar un comentario