Analizamos y explicamos la librería cURL, una herramienta que permite transferir información con sintaxis de URL. Soporta gran variedad de protocolos (HTTP, FTP, LDAP…) y esta funciona en gran variedad de sistemas operativos. En esta ocasión la utilizaremos en el entorno que a nosotros nos interesa, en PHP.

Autor:

Intentando mejorar cada día en este mundo tan cambiante de la programación. Sígueme en Twitter o en GitHub. Actualmente estoy disponible para contratar.
Descarga Demostración

Introducción: Conociendo la librería cURL

¡Hola a todos! despues de un mes de bastante trabajo y poco tiempo libre para escribir, vuelvo a la carga con un nuevo tutorial en PHP.

Quien no conozca la librería cURL, igual se ha preguntado muchas veces cómo hacen los sitios web para mostrar contenido de otras páginas en la suya. Por ejemplo, se preguntará cómo funciona la famosa aplicación que revisa los links escritos en el texto de una web y muestra una previsualización en miniatura.

O sin ir más lejos, puede que alguna de estas preguntas pasen por su cabeza alguna vez: ¿cómo imprimes en una web el contenido RSS de un dominio ajeno?, ¿cómo descargas una imagen de un servidor ajeno para no hacer abuso de recursos?, ¿cómo es posible iniciar sesión en hotmail para extraer los contactos?. La respuesta es común para todas esas preguntas: usando cURL.

cURL te permite crear conexiones con distintos protocolos bajo distintos SO para poder conectar tus aplicaciones con otros entornos, como el web, Active Directory, etc

cURL es una herramienta que permite abrir conexiones en una amplia variedad de protocolos y que está disponible tanto como herramienta de consola (para ejecutar directamente con comandos) como en librería (para usar en vuestro código) y que permite hacer prácticamente todo: manejo de cookies, descarga de ficheros binarios, envíos de parámetros GET y POST, etc.

Es tan potente y fácil de usar, que podemos crear sin muchos problemas un crawler que recorra páginas web para analizar información, al estilo de por ejemplo el Google Bot.

cURL en PHP

Antes de nada, os recuerdo que podéis ver la documentacion de cURL para PHP desde la página oficial. Todas las funciones y constantes predefinidas tienen el prefijo ‘curl_’ y ‘CURL’ respectivamente, por lo que no hay problema en identificarlas en el código y recordarlas se hace un poco más fácil.

Toda conexión con cURL comienza con curl_init, que nos devolverá un manejador (handler) en caso de éxito o FALSE en caso de fallo. Este manejador será necesario para usar las demás funciones y estará disponible hasta que se llame a la funcion curl_close(). Vamos a ver un ejemplo sencillo:

$handler = curl_init("http://www.google.es");
$response = curl_exec ($handler);
curl_close($handler);
echo $response;

Al ejecutar este pequeño trozo de código, lo que estáis haciendo es abrir una conexión con la página de Google, descargar el contenido como si de un navegador se tratase, e imprimirlo como si fuese contenido propio.

Como véis es muy fácil, pero normalmente suele complicarse un poco más la cosa, porque por ejemplo, hay webs que devuelven una respuesta u otra según el navegador en el que te encuentras, o en un idioma u otro dependiendo del valor de las cabeceras HTTP. Para definir las cabeceras todas correctamente, se usa la función curl_setopt().

Con la funcion curl_setopt() podemos establecer las cabeceras HTTP para recibir el contenido adecuado.

Para indicarle al servidor remoto que tu idioma preferido es el castellano y que tu navegador es Firefox:

curl_setopt($handler, CURLOPT_USERAGENT,"Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.0.1) Gecko/2008070208 Firefox/3.0.1");
curl_setopt($handler, CURLOPT_HTTPHEADER, array("Accept-Language: es-es,en"));

Puedes ver la gran lista de opciones que puedes configurar aquí. Normalmente cuando tienes algún problema con alguna conexión, sueles encontrar la solución jugando con estas opciones.

Envío de formularios POST

Muchas veces la información que necesitamos está sometida a enviar parámetros con el método POST. No pasa nada, cURL como ya hemos dicho, nos permite hacer esto sin mucho esfuerzo. Imagina que queremos iniciar sesión en una web para acceder a nuestro contenido via cURL.

Lo primero que tenemos que hacer es iniciar sesión desde un navegador e identificar que parámetros POST se envían para que el login tenga éxito, esto se puede ver de forma muy fácil con la herramienta Firebug para Mozilla Firefox.

Imaginemos que estos son los parámetros que se envían:

  • user: ontuts
  • password: test
  • url: http://www.example.com/login

Bien ya sabemos todo lo que necesitamos, ahora toca crear el código:

$url = "http://www.example.com/login";
$postData = array("user" => ontuts, "password" => "test");
/*Convierte el array en el formato adecuado para cURL*/
$elements = array();
foreach ($postData as $name=>$value) {
   $elements[] = "{$name}=".urlencode($value);
}
$handler = curl_init();
curl_setopt($handler, CURLOPT_URL, $url);
curl_setopt($handler, CURLOPT_POST,true);
curl_setopt($handler, CURLOPT_POSTFIELDS, $elements);
$response = curl_exec ($handler);
curl_close($handler);

Con este código lo que hacemos es acceder a la url pero enviando datos adjuntos que el server interpretará y nos devolverá la repuesta adecuada.

Manejando Cookies

En el ejemplo anterior vemos un ejemplo de cómo iniciar sesión en una web, pero si lo probáis comprobaréis que una vez iniciada la sesión, en la próxima petición ya no tendréis acceso.

Eso es debido a que por lo general, cuando inicias sesión, el servidor te genera una cookie que tienes que guardar y que identifica tu sesión para corroborar que eres tu y no otra persona malintencionada (como si fuese una tarjeta de identificación) la que está accediendo.

Por defecto cURL no guarda las cookies pero es fácil obligarle a que lo haga:

//Código de inicio de cURL
//........
//
$cookie_file = "/tmp/".time();
curl_setopt($handler, CURLOPT_COOKIEFILE, $cookie_file);
curl_setopt($handler, CURLOPT_COOKIEJAR, $cookie_file);
$response = curl_exec ($handler);
curl_close($handler);

Es importante advertir que para que las cookies se guarden correctamente, el usuario de apache (normalmente www-data) tiene que tener acceso de lectura y escritura en el directorio que especifiques.

Si juntamos esto con el ejemplo anterior, podríamos crear un script que se conecte por ejemplo a Facebook y escriba algo en tu muro automáticamente, o que recupere una lista de tus amigos, etc…

Una clase para facilitar las cosas

Por último os dejo una clase que he creado hace un par de meses para un proyecto. No se puede decir que sea una clase general ni mucho menos, pero funciona perfectamente para lo que la he usado: inicios de sesión y extracción de datos. Podéis modificarla a vuestro antojo para adaptarla a vuestras necesidades:

/**
 * Clase para gestionar las conexesiones y peticiones a servidores remotos
 */
class HttpConnection {
    private $curl;
    private $cookie;
    private $cookie_path="/cookies";
    private $id;

    public function __construct() {
        $this->id = time();
    }
    /**
     * Inicializa el objeto curl con las opciones por defecto.
     * Si es null se crea
     * @param string $cookie a usar para la conexion
     */
    public function init($cookie=null) {
        if($cookie)
            $this->cookie = $cookie;
        else
            $this->cookie = $this->cookie_path . $this->id;

        $this->curl=curl_init();
        curl_setopt($this->curl, CURLOPT_USERAGENT,"Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.0.1) Gecko/2008070208 Firefox/3.0.1");
        curl_setopt($this->curl, CURLOPT_HEADER, false);
        curl_setopt($this->curl, CURLOPT_COOKIEFILE,$this->cookie);
        curl_setopt($this->curl, CURLOPT_HTTPHEADER, array("Accept-Language: es-es,en"));
        curl_setopt($this->curl, CURLOPT_COOKIEJAR, $this->cookie);
        curl_setopt($this->curl, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($this->curl, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($this->curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
        curl_setopt($this->curl, CURLOPT_RETURNTRANSFER,true);
        curl_setopt($this->curl, CURLOPT_CONNECTTIMEOUT, 5);
        curl_setopt($this->curl, CURLOPT_TIMEOUT, 60);
        curl_setopt($this->curl, CURLOPT_AUTOREFERER, TRUE);
}
    /**
     * Establece en que ruta se guardan las cookies.
     * Importante: El usuario de apache debe tener acceso de lectura y escritura
     * @param string $path
     */
    public function setCookiePath($path){
        $this->cookie_path = $path;
    }
    /**
     * Envía una peticion GET a la URL especificada
     * @param string $url
     * @param bool $follow
     * @return string Respuesta generada por el servidor
     */
    public function get($url,$follow=false) {
        $this->init();
        curl_setopt($this->curl, CURLOPT_URL, $url);
        curl_setopt($this->curl, CURLOPT_POST,false);
        curl_setopt($this->curl, CURLOPT_HEADER, $follow);
        curl_setopt($this->curl, CURLOPT_REFERER, '');
        curl_setopt($this->curl, CURLOPT_FOLLOWLOCATION, $follow);
        $result=curl_exec ($this->curl);
        if($result === false){
            echo curl_error($this->curl);
        }
        $this->_close();
        return $result;
    }
    /**
     * Envía una petición POST a la URL especificada
     * @param string $url
     * @param array $post_elements
     * @param bool $follow
     * @param bool $header
     * @return string Respuesta generada por el servidor
     */
    public function post($url,$post_elements,$follow=false,$header=false) {
        $this->init();
        $elements=array();
        foreach ($post_elements as $name=>$value) {
            $elements[] = "{$name}=".urlencode($value);
        }
        $elements = join("&",$elements);
        curl_setopt($this->curl, CURLOPT_URL, $url);
        curl_setopt($this->curl, CURLOPT_POST,true);
        curl_setopt($this->curl, CURLOPT_REFERER, '');
        curl_setopt($this->curl, CURLOPT_HEADER, $header OR $follow);
        curl_setopt($this->curl, CURLOPT_POSTFIELDS, $elements);
        curl_setopt($this->curl, CURLOPT_FOLLOWLOCATION, $follow);
        $result=curl_exec ($this->curl);
        $this->_close();
        return $result;
    }
    /**
     * Descarga un fichero binario en el buffer
     * @param string $url
     * @return string
     */
    public function getBinary($url){
        $this->init();
        curl_setopt($this->curl, CURLOPT_URL, $url);
        curl_setopt($this->curl, CURLOPT_BINARYTRANSFER,1);
        $result = curl_exec ($this->curl);
        $this->_close();
        return $result;
    }
    /**
     * Cierra la conexión
     */
    private function _close() {
        curl_close($this->curl);
    }
    public function close(){
        if(file_exists($this->cookie))
            unlink($this->cookie);
    }
}

Modo de uso

$http = new HttpConnection();
$http->setCookiePath("/my_cookie_path/");
$http->init();
echo $http->get("http://www.google.es");
$http->close();

Como conclusión…

La librería cURL puede llegar a ser extramadamente útil en muchas ocasiones: podemos crear scripts automáticos que entren en determinadas páginas web e interaccionen por nosotros, recoger datos de forma automática y guardarlos en una base de datos, indexar contenido de otras páginas a modo de buscador, recoger todas las imágenes de una misma página como hace facebook al compartir sus enlaces…

Si bien puede que muchos de vosotros no la conocieseis, seguro que para próximos proyectos se os viene a la cabeza esta librería y terminaréis haciendo un buen uso intensivo de cURL :) .

¡Nos vemos en el próximo tutorial!

¿Necesitas desarrollar un proyecto web o para móviles? ¡Estamos disponibles!

Visitar Cokidoo

Cokidoo, los creadores de Ontuts, desarrollamos proyectos tecnológicos centrados en redes sociales y aplicaciones web, aplicaciones móviles y consultoría web y bases de datos.

Somos jóvenes, inquietos, versátiles, apasionados por la innovación y enfocados en las nuevas tecnologías. Con Ontuts tratamos de compartir nuestro conocimiento adquirido en los distintos proyectos, ayudando a la comunidad y mostrando nuestra capacidad tecnológica.

Si necesitas un presupuesto sin compromiso, estamos disponibles, no dudes en contactar con nosotros.

Comentarios en esta publicación (57 comentarios)

¿Te ha gustado esta publicación? ¡Puedes compartir tu opinión con todos nosotros! Simplemente pincha aquí mismo.

Roy

Hola muy buen tuto, solo que no me anda el post, la pagina del google me carga perfecta pero cuando hago la consulta me sale un error 404, esto pasa incluso en el demo que esta en este site, por favor me podrían indicar como arreglarlo

gracias

Jontan

Maestro, gracias por la info uno de los mejores tutoriales que he visto del tema

Fernando

Hola. Genial, no sabía que existía esta posibilidad, que en mi caso me sirve para usar include si está deshabilitado en el servidor. Sólo una pregunta, al usar

Al final, después de mostrarme la página, me sale el número “1″ ¿porqué sale esto y cómo se puede quitar?

También me ha ocurrido que al insertar una web no me muestra las imágenes, aunque sí todo el contenido en texto. Ocurre cuando estas imágenes (hojas de estilo, etc) tienen en la página original una ruta relativa y no absoluta. Estas últimas sí las muestra ¿cómo se soluciona?

Muchas gracias.

Fernando

Perdón, evidentemente no se ha mostrado el código en el mensaje. Me refería a la llamada a la página de Google del primer ejemplo.

Vicent

Estoy utilizando la clase, para validarme en un formulario (con campos post username y password) y después poder entrar a una página del área privada, para analizarla, pero estoy utilizándola mal, porque no puede acceder, algún ejemplo de como hacer esto.