Ir directamente al contenido de esta página

Integrar contenido de Twitter por medio de PHP

Dado que ya hemos explicado en entradas anteriores cómo integrar contenidos de los RSS de WordPress y de Flickr, no nos costaba nada ofrecer a nuestros lectores la forma de hacer lo propio con Twitter.

Aviso: en Twitter han elegido un estándar distinto a RSS para sus feeds, concretamente Atom. Por ello, nuestro código de PHP esta vez va a ser algo diferente, por los motivos que explicaremos un poco más abajo.

Pero como siempre, y para empezar, el ejemplo y el código:


<?php
  $xml = new DomDocument();
  $xml->load('http://search.twitter.com/search.atom?q=from%3Ausuario_de_Twitter&rpp=número_de_tweets'); 
  $xpath = new DOMXPath($xml);
  $xpath->registerNamespace('atom','http://www.w3.org/2005/Atom');
  $autor = $xpath->evaluate('string(/atom:feed/atom:entry[1]/atom:author/atom:name)');
  $url = $xpath->evaluate('string(/atom:feed/atom:entry[1]/atom:author/atom:uri)');
  $avatar = $xpath->evaluate('string(/atom:feed/atom:entry[1]/atom:link[@rel="image"]/@href)');
  echo '<h1><img src="'.$avatar.'" alt="" /><a href="'.$url.'">'.$autor.'</a></h1>';
  echo '<ul>';
  $entradas = $xpath->evaluate('//atom:entry');
  foreach($entradas as $e){
    $txt = $xpath->evaluate('string(atom:content)',$e);
    $vinculo = $xpath->evaluate('string(atom:link[@rel="alternate"]/@href)',$e);
    $fecha = $xpath->evaluate('string(atom:published)',$e);
    $fecha = strftime("%d/%m/%Y",strtotime($fecha));
    echo '<li><strong>'.$fecha.'</strong> <em>'.$txt.'</em> <a href="'.$vinculo.'" class="v-tweet">[tweet]</a></li>'; 
  }
  echo '</ul>';
?>
 

La idea básica sigue siendo la misma: cargar el Atom con DomDocument() y recorrerlo para extraer los datos que necesitamos. Sin embargo, esta vez lo vamos a recorrer por medio de DOMXPath(), una clase de PHP que nos permite emplear la sintaxis de XPath.

XPath (XML Path Language) 1.0, es una Recomendación del W3C del 16 de noviembre de 1999 que define un lenguage con el que expresar rutas de recorrido a lo largo del árbol del DOM de un documento, y poder así seleccionar nodos de una forma mucho más precisa y directa de lo que puede lograrse con métodos como getElementsByTagName() o similares.

Pero antes de meternos en ello, vamos a definir lo que tiene que hacer nuestro ejemplo:

Lo primero de todo, claro está, es saber de dónde vamos a sacar el feed que necesitamos. Consultando la Search API Documentation nos informamos de que el URL que necesitamos es…


http://search.twitter.com/search.atom?q=from%3Ausuario_de_Twitter&rpp=número_de_tweets 
 

…así que lo cargamos en una variable que es $xml.


$xml = new DomDocument();
$xml->load('http://search.twitter.com/search.atom?q=from%3Ausuario_de_Twitter&rpp=número_de_tweets'); 
 

Seguidamente creamos una instancia de DOMXPath a la que asignamos ese documento XML, y especificamos el espacio de nombres:


$xpath = new DOMXPath($xml);
$xpath->registerNamespace('atom','http://www.w3.org/2005/Atom'); 
 

Ahora ya podemos empezar a extraer datos.

Como hemos dicho, en este caso vamos a emplear sintaxis de XPath para que la localización de la información que nos interesa sea más eficiente.

Si miramos el feed que obtenemos del Twitter del W3C —por ejemplo— nos encontramos con que cada entrada tiene el siguiente código:


<entry>
  <id>tag:search.twitter.com,2005:27254634050</id>
  <published>2010-10-13T16:02:51Z</published>
  <link type="text/html" href="http://twitter.com/w3c/statuses/27254634050" rel="alternate"/>
  <title>RT @notabene: rencontre presse en cours avec @w3c et @parisweb  #mobileweb #future</title>
  <content type="html">RT &lt;a href=&quot;http://twitter.com/notabene&quot;&gt;@notabene&lt;/a&gt;: rencontre presse en cours avec &lt;a href=&quot;http://twitter.com/w3c&quot;&gt;@w3c&lt;/a&gt; et &lt;a href=&quot;http://twitter.com/parisweb&quot;&gt;@parisweb&lt;/a&gt;  &lt;a href=&quot;http://search.twitter.com/search?q=%23mobileweb&quot; onclick=&quot;pageTracker._setCustomVar(2, 'result_type', 'recent', 3);pageTracker._trackPageview('/intra/hashtag/#mobileweb');&quot;&gt;#mobileweb&lt;/a&gt; &lt;a href=&quot;http://search.twitter.com/search?q=%23future&quot; onclick=&quot;pageTracker._setCustomVar(2, 'result_type', 'recent', 3);pageTracker._trackPageview('/intra/hashtag/#future');&quot;&gt;#future&lt;/a&gt;</content> 
  <updated>2010-10-13T16:02:51Z</updated>
  <link type="image/png" href="http://a1.twimg.com/profile_images/632802013/w3c-avatar_normal.gif" rel="image"/>
  <twitter:geo>
  </twitter:geo>
  <twitter:metadata>
    <twitter:result_type>recent</twitter:result_type>
  </twitter:metadata>
  <twitter:source>&lt;a href=&quot;http://identi.ca&quot; rel=&quot;nofollow&quot;&gt;identica&lt;/a&gt;</twitter:source>
  <twitter:lang>fr</twitter:lang>
  <author>
    <name>w3c (W3C Team)</name>
    <uri>http://twitter.com/w3c</uri>
  </author>
</entry>
 

Algunos de los datos los necesitamos para cada entrada, pero el nombre del usuario, su avatar y el vínculo a la cuenta sólo los necesitamos una vez, así que los asignamos a tres varables:


$autor = $xpath->evaluate('string(/atom:feed/atom:entry[1]/atom:author/atom:name)');
$url = $xpath->evaluate('string(/atom:feed/atom:entry[1]/atom:author/atom:uri)');
$avatar = $xpath->evaluate('string(/atom:feed/atom:entry[1]/atom:link[@rel="image"]/@href)'); 
 

Y es aquí donde se comprueba que XPath es más eficiente. Por medio de la combinación de getElementById() y getElementsByTagName() obtendríamos listas de nodos en los que tendríamos que seleccionar el que nos interesara y buscar en sus propiedades los nodeValue correspondientes. Además, en el caso de los elementos link, tendríamos que comprobar uno a uno cuál es de los dos el que nos interesa. Con expresiones de XPath podemos apuntar directamente a los nodos concretos y, adicionalmente, con el método evaluate() de DOMXPath() podemos especificar ya el tipo de variable que necesitamos para nuestro código. Así:

Hemos indicado que en evaluate() podemos especificar el tipo de valor devuelto, que en los casos que acabamos de mencionar es string. Pero para el bucle que viene a continuación —con el que extraemos datos de cada entrada— nos viene mejor no indicarlo y recibir así una lista de nodos:


$entradas = $xpath->evaluate('//atom:entry');
 

La doble barra (//) significa «en cualquier parte del documento». Y con esto ya tenemos la lista de nodos con la que trabajamos en el foreach. En él, también por medio de expresiones de XPath como las que hemos comentado, obtenemos los contenidos de content —mejor éste que title, para no perder los vínculos incluidos en el cuerpo del tweet—, el vínculo al propio tweet —el href del link con rel="alternate"— y la fecha de publicación.

A partir de aquí, sólo queda presentar los datos… y ver qué tal funciona.

Esta entrada se publicó el 15 de octubre de 2010, se archivó en , y fue etiquetada como , . Autor: Saúl González Fernández. Hay 9 comentarios ›.

Comentarios

  1. denia99 dice:

    Muy buenas, interesante el codigo escrito, pero tengo un problema, cuando intento traer los datos de un hashtag, ¿a qué puede ser estos dos warnings? Muchas gracias 😉

    Warning: DOMDocument::load(http://search.twitter.com/search.atom?q=%22#eleccions2010%22) [domdocument.load]: failed to open stream: HTTP request failed! HTTP/1.1 403 Forbidden in C:wampwwwcallback.php on line 67

    Warning: DOMDocument::load() [domdocument.load]: I/O warning : failed to load external entity “http://search.twitter.com/search.atom?q=%22#eleccions2010%22” in C:wampwwwcallback.php on line 67

  2. Creo que el problema son las comillas. Prueba con DOMDocument::load('http://search.twitter.com/search.atom?q=%23eleccions2010') en lugar de DOMDocument::load(http://search.twitter.com/search.atom?q=%22#eleccions2010%22).

  3. denia99 dice:

    Muy buenas,

    Muchas gracias por la contestación, tengo otra pregunta, ¿cómo puedo hacer para coger el contenido del tweet, es decir el texto escrito, ignorando las funciones de PageTracker(), etc.?

    Muchas gracias de nuevo.

  4. Si lo único que necesitas es el texto plano, puedes obtenerlos del elemento title de cada entrada.

    Con nuestro código bastaría con sustituir la línea $txt = $xpath->evaluate('string(atom:content)',$e); por $txt = $xpath->evaluate('string(atom:title)',$e);, aunque eso desactivará los vínculos.

  5. Corina dice:

    Solo me aparece el último tweet… yo quisiera que aparecieran por lo menos los últimos cinco y que ademas se visualicen como una marquesina. ¿Tengo que moficar algo? Gracias.

  6. Como indico arriba, hay un parámetro que se puede emplear en el URL con el que se piden los tweets y con el que se puede especificar la cantidad: rpp. En tu caso la dirección quedaría así: .../search.atom?q=from%3Ausuario_de_Twitter&rpp=5.

    En cuanto a que los tweets se presenten como una marquesina, vas a tener que recurrir a JavaScript, porque marquee ha sido depreciado hasta en HTML5. No obstante, si vas a emplear ese efecto igual te viene bien consultar las técnicas de accesibilidad relativas a contenidos con movimiento.

  7. cristian dice:

    Muy buena la data.

    Consulta: ¿después de un pedido tengo manera de que sólo me traiga los nuevos tweets en el próximo pedido? De esta manera generar esa sensación de tiempo real…

    Muchas gracias.

  8. Saúl González Fernández dice:

    @cristian: En la documentación aparece un parámetro que es since_id, que te permite hacer una petición de los tweets posteriores al del ID que proporciones.

  9. Juan dice:

    Tras horas buscando, os dejo la forma más fácil que he encontrado para mostrar el timeline de un usuario:

    https://github.com/davidmigloz/Twitter-Timeline

    Es muy configurable en cuanto a la información que quieres mostrar y puedes personalizar fácilmente el código HTML que genera. Y además, está en español.

    Un saludo

¿Algún comentario?

* Los campos con un asterisco son necesarios

Últimos proyectos

© Digital Icon, S.L., 2007 – 2017