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: Iván Guardado

¡Mi hobbie es la programación! Llevo unos cuantos años dedicándome al desarrollo de software y últimamente especializándome en web. Actualmente trabajo en Cokidoo, de la cual soy cofundador. Si queréis podéis seguirme por twitter.
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, aplicaciones web y aplicaciones móviles.

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 (21 comentarios)

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

Nosé cuánto hace que conozco esta librería… pero mira que no nos tiene salvado veces cuando hemos tenido que recoger cantidades ingentes de datos :)

Yo la verdad es que he usado Curl para cosas muy fijas como por ejemplo, para una página que vendía templates html de templatemonster y en lugar de utilizar el buscador que ellos te dan, en inglés, metido en un iframe y con un diseño fijado por templatemonster, poder usarlo en una página e integrarlo en el diseño de esta sin que vieses por ningún lugar las url a templatemonster.

Pero me apunto esta librería porque no he usado nunca CURL para hacer posts ni similares, así que me viene bien.

Un saludo!

Creo que es importantísimo que antes de programar nada con cURL, os aseguréis que el host que vais a usar para alojar la aplicación no tiene capada esta librería, que me ha pasado más de una vez, y no ha habido manera de convencer al administrador de turno para que la habilitase.

Quitando ese pequeño problema asociado, cURL me parece algo potentísimo y con lo que se pueden hacer cosas muy interesantes.

Bravo por el post :)

Iván Guardado

@Wallack Un buen uso de la librería!! ya que comentas eso, recuerdo que nosotros también la usaramos con Youtube para hacer búsquedas desde nuestro sitio web :)

@Harold Dennison Tienes razón, nosotros nunca hemos tenido problema con los hosts y cURL porque siempre la hemos tenida activada, pero śí es cierto que no siempre lo está.

Gracias por los comentarios!!

Excepcional.
Estaba leyendo el artículo y pensando, que pena que no se comente nada de como conseguir leer tras un logueo para obtener datos automaticamente de una cuenta propia… y ahí estaba, genial.

Mis felicitaciones por el artículo.

@Harold de todas formas por lo general cURL está activada, ya que lo que sí suele estar desactivado por seguridad es la función fopen y derivados :)

pegallego

Muy buen artículo, no hay mucha información sobre esta librería en Español.

Una consulta quería hacer, no soy informático profesional, estoy utilizando esta librería para enviar SMS a través de Movistar y me funciona bien, pero querría eliminar la respuesta (“Http…) para que no apareciera en el navegador del usuario ya que no tiene mucho interés para el y aparece mezclado con otra información que yo le envío, podriais indicarme como puedo hacerlo.

Gracias anticipadas.

con file_get_contents o fopen y tratar como un archivo se puede recuperar un recurso http, con la limitante que el envio de variables tiene que ser por get, pero me parece mas sencillo si solo ire por un recurso al que no envio variables o bien que son por get

Angel

Excelente artículo.
Estoy intenta utilizar tu clase para poder leer el titulo y descripcion de una pagina web.
seria sacar el contenido que tienen y

¿Alguna idea?

@Angel parece que te has comido parte del texto

Nacho

Hola,

Muy bueno el articulo, yo estoy usando esta libreria para un proyecto que tiene que trabajar con web services y me ha venido que ni pintado para obtener la informacion.

Pero querría preguntarte ¿cómo trabaja el lado servidor con las peticiones hechas por una sesion CURL?. Quiero decir, ¿Como acepta el servidor un inicio de sesion mediante curl_init? y ¿como hace para devolver la informacion que le solicita al usuario al llamar a la funcion curl_exec?¿ Que viaja la informacion en el Response_body del protocolo HTTP o algo asi?

Saludos y muchas gracias por tu tiempo

osi

otra pregunta….como puedo yo ejecutar un cron con curl…dicen k es desde el cmd , pero como q no me funciona… saludos

@osi, si tienes instalado todo lo necesario, solo tienes que ejecutar el comando “curl” en la consola y ya te aparecerá la ayuda.

Excelente blog!!!

Disculpa q te moleste con preguntas de principiante pero quisiera saber lo siguiente.. Estoy haciendo una aplicacion Web para encuestras en tiempo real, normalmente usaria Ajax para q los usuarios a traves de una intefaz votaran y se viera reflejado en otra vista su voto instantaneamente.. Sin embargo, no me esta funcionando y decidi ver otras alternativas.. cURL es una de ellas..

Solo necesito pasar a mi doc, httprequest.jsp varias variable para que el las interprete y modifique la grafica..

Parece sencillo usando el ejemplo que pones arriba pero no me funciono!.. Me podrias dar una mano.

Saludos desde Venezuela!

¡Buenas! Una pregunta de principiantes :P

¿Cómo se haría para capturar el enlace de, por ejemplo, una imagen en concreto? (contando con que solo aparece una imagen en la página con la que se conecta).

Con que me des una pistilla bastará :)

Un saludo y muy buena entrada :D

Hola Antonio! La verdad que eso nunca lo he hecho por eso no te lo puedo decir. Sin embargo tenemos pendiente investigarlo y hacer un tutorial, asique…no dejes de leernos :)

juan

Me pueden ayudar.
quiero utilizar curl para agregar anuncios a algunas paginas web de forma automatica con informacion de mi propia pagina. En mi pagina web tengo muchos registros y quiero registrarlos automaticamente en otras paginas.

Les agradesco si me pueden ayudar.

las paginas a las que quiero registrarles mis registros son

http://www.tufuturacasa.com
y
http://www.inmosalvador.com/inmo/busquedasip/Tipo/Ventacasas/Venta_Casas_El_Salvador.
y
http://elsalvador.inmobiliaria.com/

sergio

¿podria utilizar esta libreria para integrar dos script de php que estan en dos dominios diferentes y dos servidores diferentes?

cURL esta destinada para realizar peticiones HTTP digamos es como si hicieras tu browser.. te traes la respuesta por lo generar el http se cuelgan las paginas web q son textos planos con codigo HTML en su interior, ahora bien puede ser un webservice que no te retorne HTML si no un XML o muy de moda los JSON por su comodidad en la programación JS/XHR.

@Antonio para jalar los enlaces lo primero es tener el codigo del recurso(el html de la otra web) una vez que lo tengas lo puedes almacenar en una cadena y esta atravez de expresiones regulares buscar las etiquetas <img y obtener su src con lo cual tienes las imagenes del recurso que consultaste.. todo seria mas facil si tu recurso fuera un XHTML bien formado.. esto es uno de los motivos reales no el que todo dicen.. es que es "estandar" para respetar los estandares.. bla bla…
el XHTML fue consevido para limpiar el HTML de la basura que tenia y lograr tener a la par un HTML y un XML, el XML lo puedes consumir en cualquie otro tipo de aplicación, es alli cuando se agradece una buena codificacion de un XHTML, con lo cual solo tendrias que cargar el recurso convertirlo en un documento DOM y solo decir doc.getElementByTag("img") y con eso traerte todas las etiquetas IMG, eso es lo que realmente se busca con el XHTML tener a la par un XML que sea facil de consumir para las aplicaciones que puedan consultarlo.

@osi PHP originalmente fue concevido como un toolkit para CGI para Webs, pero al cabo de los años y de su cresimiento se ha convertido en un lenguaje de proposito general, no solo para la web, aunque la fama de este y su origen esta enfocado para esta solucion, en PHP se pueden programar script tipo shell, aunque estos se llevan mejor en linux por que incluso se pueden crear demons(servicios) que se eten ejecutando detras del sistema sin itervencion humana, incluso puedes codificar estos deamos y crear servidores que se comuniquen por sockets etc.. en pocas palabras hay mucho mas que programacion web en PHP, para todo esto investiga PHP-CLI que es practicamente el mismo php que conoces solo que enfocado a una programacion en consola, ademas tabien existe la programacion de entorno grafico convinandoce con la libreria GTK, busca algo de PHP-GTK, son algunas de las cosas que poco explotan de PHP mas que nada por la ignorancia de su existencia y la fama de PHP de ser un lenguaje supuestamente solo para paginitas web

The Specialist

Muy buen articulo…Pero los datos del post no me funcionaron con la forma que tu diste……
Para que me funcionara tube que psasar la data de la sigiente forma:

curl_setopt($handler, CURLOPT_POSTFIELDS, “user=VALOR&password=VALOR”);

Añade Tu Comentario