Browse Category: Desarrollo

Web scraping automatizado para hoteles con PHP

En el tutorial anterior, generamos una página web de hoteles que extrae una lista de habitaciones directamente con la fuente. Sin embargo, esto genera problemas en tiempos de respuesta para el usuario final. Sin embargo, llega a ser muy pesado para nuestro sitio web y para nuestros visitantes. Así que, nuestro objetivo es resolver la optimización de tiempos de respuesta del sitio con Web scraping automatizado.

Conociendo el proyecto

Como punto de partida, te comparto el código fuente del script para hacer scraping un sitio web de hoteles. El cual nos servirá de referencia:

Descargar script

¿Como funciona actualmente este proyecto?

El procedimiento funciona a través de una llamada síncrona, el sitio web finalizará una vez que el script obtenga los datos del portal de TripAdvisor.

De acuerdo a la línea de tiempo, desde que el usuario solicita información al sitio, éste recorre varios nodos haciendo varias peticiones para resolver el resultado final. Entre sus inconvenientes de este método, nos encontramos:

  • El hecho de recorrer varios nodos, hace que el tiempo de respuesta sea más largo. Se genera una dependencia. Cuando se rompe en algún punto del camino, la experiencia del usuario sería poco agradable.
  • Existiría una sobrecarga en nuestro servidor porque cliente -> servidor -> fuente para después, fuente -> servidor -> cliente. Al hacer esto todo el tiempo, hará que consuma muchos recursos del sistema cada vez que entra un nuevo usuario.
  • Regresando a las dependencias. No podemos controlar lo que hacen terceros. Si el equipo de desarrollo de TripAdvisor se le ocurre actualizar las vistas de sus sitios, inmediatamente nuestra página queda fuera de línea.

Todos esos casos pueden llega a ser críticos si llegaran a suceder. Lo más importante es poder ofrecer una excelente experiencia de usuario con los datos obtenidos de terceros. Para esto, requieres una serie de pasos para mejorar la salud del sitio web por medio de la automatización.

Uso de una base de datos

Para resolver estas observaciones, necesitamos cambiar un poco la estructura del proyecto. El objetivo será reducir los tiempos de respuesta para obtener las habitaciones más populares. Para conseguirlo, haremos uso de una base de datos que contenga la información necesaria para la consulta directa.

Workflow de web scraping en BD con MySQL

Con la información en la base de datos, el acceso a los datos es directo. Por lo tanto, el usuario no tiene que esperar a que el sitio haga un scraping a la página fuente. Para tener esa información actualizada necesitas un script que obtenga esos datos periódicamente para mantenerlo actualizado.

Pasos para realizar el refactoring del sitio web

Es hora de hacer refactoring al código que le hará scraping a la página de hoteles. Para esto necesitamos trabajar en varias etapas.

1. Generar la base de datos

Para la estructura, solo requieres una tabla que guarde la relación de habitaciones obtenidas. En mi caso, crearé un par de tablas para agregarle un poco más de información.

Habitaciones ingresadas en base de datos mysql

De acuerdo al diagrama anterior, existen dos tablas que nos servirán para este propósito:

  • Cities: Esta tabla servirá para conocer las ciudades que queremos extraer. Cada registro cuenta con una url de cada fuente.
  • Rooms: Guarda todas las habitaciones obtenidas del script, segmentados por ciudades.

Descarga la Base de datos

2. Crear el conector de la base de datos

// File: connector.php
// Source: https://secure.php.net/manual/en/function.mysqli-connect.php
$mysqli = mysqli_connect(DB_HOST, DB_USER, DB_PASS, DB_NAME);
// Verifica si la conexión es correcta
if (!$mysqli) {
echo "Error: Unable to connect to MySQL." . PHP_EOL; echo "Debugging errno: " . mysqli_connect_errno() . PHP_EOL;
echo "Debugging error: " . mysqli_connect_error() . PHP_EOL; exit;
}

Si no existe un problema, la conexión de base de datos debería correr sin algún inconveniente.

3. Generar el scraper dinámico


// scraper.php
// Call dependences
require 'simple_html_dom.php';
require 'connector.php';
require 'utils.php';
// Crea un objeto de funciones genéricas
$utils = new Utils;
// Antes de obtener nuevos datos, elimina los anteriores
mysqli_query($mysqli, "TRUNCATE TABLE `rooms`");
// Lista las ciudades: 1 => Isla Mujeres, 2 => Cancún, 3 => Playa del Carmen, 4 => Tulum
if ($result = $mysqli->query("SELECT id, source FROM `cities`")) {
/* Recorre todas las ciudades obtenidas para hacer scraping de esas ciudades */
while ($row = mysqli_fetch_assoc($result)) {
// Asigna valores a variables locales
$city_id = $row['id'];
$city_source = $row['source'];
// Crea el objeto DOM de la url fuente con el contenido
$html = file_get_html($city_source, false, null, 0);
// Todos los items de habitaciones fuente tienen esta clase
$wrap_hotels = $html->find('div.prw_meta_hsx_responsive_listing');
// Recorrer todos los contenedores de las habitaciones fuente
foreach($wrap_hotels as $element) {
// Guarda en variables locales, los datos específicos de cada habitación.
$hotel_name = $element->find('.property_title', 0)->plaintext;
// ¿Recuerdas la clase utils? Necesito quitar el formato MX$0.00 y convertirla a numérico
$hotel_price = $utils->format_price_to_int($element->find('.price', 0)->plaintext);
// También necesito obtener la url correcta con esta función prediseñada
$hotel_image_url = $utils->get_standar_image_url($element->find('.inner', 0)->attr);
$hotel_href = $element->find('.photo-wrapper a', 0)->href;
// Guardar esta habitación a la base de datos
mysqli_query(
$mysqli,
"INSERT INTO `rooms` (city_id, name, price, image_url, href)
VALUES ('$city_id', '$hotel_name', '$hotel_price', '$hotel_image_url', '$hotel_href')"
);
}
}
/* Liberar consulta */
$result->close();
}
/* Cerrar conexión */
$mysqli->close();

Puedes descargar las dependenciassimple_html_dom.php yutils.php.

Como primer paso, recorrer la tabla ciudades. Indicará al algoritmo a que ciudades debemos acceder para obtener las habitaciones más populares. El algoritmo para extraer datos funciona igual, con la diferencia que almacenamos los resultados en la tabla rooms.

4. Programar el scraper para mantener los datos actualizados.

Lo que buscamos es delegar la funcionalidad de obtener y generar las habitaciones de manera independiente. Todos los resultados que extrae, serán almacenados en una base de datos. Cuando el usuario, haga una petición, consultará en la BD en vez de hacer el proceso de extracción directamente. Esto ayudará a administrar mejor los recursos del servidor.

Teniendo en cuenta esto, pasamos al proceso de programar tu script para que se repita en un periodo x de tiempo. La clave es mantener el proceso de generar datos de manera aislada como explico en el siguiente diagrama:

Web scraping automatizado utilizando cron

En la automatización, debes manejar los tiempos en base a tu criterio. En este proyecto, haré que el scraper se ejecute cada hora. Con este tiempo, considero, que es suficiente para mantener los datos actualizados sin tener que consumir demasiados recursos de mi servidor.

Este fue mi criterio:

  • Si extendiera más el tiempo como a 4 horas, correría el riesgo de tener un mayor desfase de precios o incluso mostrar habitaciones que no están disponibles.
  • Cuando reduces el tiempo, cada 20 minutos. Estaría empleando recursos del servidor cada 20 minutos para iniciar un proceso de actualización.
  • Otra variable a considerar, es la cantidad de información que necesito procesar. Si necesitara obtener habitaciones de toda la zona sur del país, tendría que extender un poco más los lapsos de tiempo.

Para la automatización, usaré cron porque mis servidores están basados en Unix (Linux, FreeBSD, Mac OS, etc.). Si usas servidores windows, puedes configurar una tarea programada.

Ejecutar el scraper cada hora de manera indefinida

0 * * * * /usr/bin/php /YOUR/PATH/scraper.php &> /dev/null

Sino estás muy familiarizado con la sintaxis de cron, te recomiendo este post: Introducción a tareas programadas con cron. Ahí podrás ver como se define el formato de cada tarea.

5. Actualizar el llenado del template

Debido a que no hacemos scraping cada vez que el cliente solicita un listado de habitaciones. Accederemos directamente a las habitaciones almacenadas en la tabla rooms.

<div class="d-flex flex-wrap">
<?php if ($result = $mysqli->query("SELECT id, name, image_url, href, price FROM `rooms` WHERE city_id = 1")): ?>
<?php while ($hotel = mysqli_fetch_assoc($result)): ?>
<div class="col-lg-4 col-md-4 col-sm-6 col-xs-6 ">
<div class="wrap-box">
<div class="box-img">
<a href="<?php echo 'https://www.tripadvisor.com/' . $hotel['href'] ?>">
<img src="<?php echo $hotel['image_url'] ?>" class="img-fluid" alt="<?php echo $hotel['name'] ?>">
</a>
</div>
<div class="rooms-content">
<h4><a href="<?php echo 'https://www.tripadvisor.com/' . $hotel['href'] ?>"><?php echo $hotel['name'] ?></a></h4>
<p class="price">$ <?php echo $hotel['price'] ?> MX / Por Noche</p>
</div>
</div>
</div>
<?php endwhile; ?>
<?php endif; ?>
</div>

En realidad, no cambió mucho la sintaxis de como esta estructurado el template. La ventaja de realizar este refactoring es:

  • Evitamos la dependencia directa del sitio original. Cuando realizan cambios en sus vistas, podemos actualizar nuestro scraper para adaptarlo a la nueva vista. Mientras tanto, la disponibilidad de nuestros datos no se compromete.
  • Al tener los datos en nuestros propios servidores, hace que las rutas sean más cortas.

Para probar como funciona el proyecto final, te dejo el enlace para que puedas descargarlo: Proyecto Final

Consideraciones especiales

  1. La finalidad de este tutorial es conocer el funcionamiento de un scraper. Puedes usar un Framework PHP que te facilitaría más la vida. Sin embargo, prefiero evitar las distracciones que nos desviaran de nuestro propósito.
  2. Puedes optimizar más el proyecto por medio de carga asíncrona en el lado del cliente, por medio de ajax.
  3. Recuerda que tenemos habitaciones de cuatro ciudades diferentes. En nuestro proyecto, podemos agregar un dropdown que cargue dichas ciudades.

Espero te haya sido de utilidad este tutorial. Cualquier comentario que pueda complementar este post, sería bienvenido. Te agradecería mucho si nos ayudas a compartir este contenido para poder ayudar a otras personas. 

Introducción a tareas programadas usando cron

Introducción a tareas programadas con cron

Las tareas programadas tienen usos muy comunes en la automatización de sistemas que requieren ejecutarse cada x tiempo sin intervención del usuario. Su función es agendar los procesos que deseas ejecutar en tu sistema. Existen diferentes programadores de tareas, en este artículo nos enfocaremos en tareas programadas usando cron.

Cron es un demonio utilizado para ejecutar tareas programadas como copias de seguridad, actualizaciones, envíos de notificaciones periódicas, etc. Esta basado en sistemas operativos tipo Unix (Linux, FreeBSD, Mac OS, etc.). A los procesos que se ejecutan por lapsos de tiempo se les conocen como cron jobs.

Crontab

Sus comandos están escritos en un archivo crontab. En linux, puedes encontrar ese archivo en /etc/crontab. Crontab verificará la fecha y hora en la que se ejecutara el script. Todo lo realizará en modo background. Podemos gestionar los crontabs de la siguiente manera:

Para ver la configuración actual
crontab -l

Para editar
crontab -e

Borra el crontab del usuario
crontab -d

Entendiendo el formato de las crontabs

La tareas cron tienen una sintaxis que ayuda a definir en que intervalos de tiempo se ejecutarán los scripts. Su formato cuenta con 5 espacios seguidos del script a ejecutar.

¿Qué son los asteriscos?

En muchos ejemplos verás un asterisco (*) en lugar de un número. Esto representa todos los números posibles en esa posición. Por ejemplo un asterisco en la posición de hora, haría trabajar un script cada hora.

Ejemplos de configuración de algunas tareas programadas

Tareas cotidianas

Esta tarea se ejecutara cada minuto, todo el tiempo

* * * * * [comando]

Lo traducimos como:

  • Sobre cada minuto
  • Repetir cada hora
  • Todos los días del mes
  • En todos los meses
  • Funcionando todos los días de la semana

Todos los domingos la 1:15 el script realizará un respaldo de las BD de mis sistemas

15 1 * * 0 [comando]

Se traduce como:

  • A partir del minuto 15
  • Desde la 1 de la madrugada
  • Todos los dias del mes
  • En todos los meses
  • Sólo los domingos

Necesito hacer un respaldo el día 1 y el día 16 de cada mes a las 23 horas

0 23 1,16 * * /usr/tasks/backup.sh

Descrito como:

  • En el minuto 0
  • De las 11 de la noche
  • Del día 1 y 16 del mes
  • Para todos los días del mes
  • Puede ser cualquier día de la semana

Por intervalos de tiempo

Arranco un script entre días laborales de lunes a viernes para enviarles un correo a las 9 de la mañana a los clientes deudores del crédito del banco

0 9 * * 1-5 /usr/tasks/sent_notification.sh

Se traduce como:

  • Empezando en el minuto 0
  • Desde 9 de la mañana
  • Todos los días del mes
  • Sobre todos los meses
  • Lunes a Viernes

Necesito verificar cada 15 minutos, en horario de oficina, que clientes nos han estado pagando puntual para acumular sus puntos.

Solución 1. Por medio de listas separadas por comas (,):

0,15,30,45 9-5 * * * /usr/tasks/add_coupons.sh

Solución 2. Interpretado por la diagonal (/) para crear intervalos:

0/15 9-5 * * * /usr/tasks/add_coupons.sh

Caracteres especiales

Loa caracteres especiales nos ayudan a crear comandos más elegantes:
  • * => Selecciona todos los valores de un campo.
  • – => Selecciona rango de valores (por ejemplo 1-6).
  • ,  => Selecciona valores específicos (por ejemplo 1,3,5 en el nivel de días de la semana, es decir los lunes, miércoles y viernes ).
  • /  => Selecciona incrementos a partir del primer valor (por ejemplo 0/15 que es cada 15 minutos comenzando desde el minuto 0 -> 15, 30 ,45).

Palabras reservadas

Cron al igual que otros lenguajes de programación también maneja palabras reservadas para facilitar su eso. Esto debido a que no necesariamente necesitamos ejecutar en tiempos demasiado específicos:

  • @reboot Ejecuta cada vez que se inicia el servidor
  • @yearly/@annually Se ejecuta una vez al año equivalente a 0 0 1 1 *
  • @monthly Se ejecuta una vez al mes equivalente a 0 0 1 * *
  • @weekly En el primer minuto de la primer hora de la semana equivalente a 0 0 * * 0.
  • @daily/@midnight diario, a las 12:00A.M equivalente a 0 0 * * *
  • @hourly al primer minuto de cada hora equivalente a 0 * * * *

Por ejemplo. Necesito verificar quienes no han pagado sus deudas pendientes y realizar el cargo al final del día.

@daily /usr/tasks/payments.sh

También podemos ejecutar scripts de diferentes lenguajes directamente. En este caso verifico quienes aún no terminaron de registrarse en mi red social para enviarles una invitación. Hago la validación cada hora.

@hourly /usr/bin/ruby /home/task/email/finish_registration.rb

Mi aprendizaje al respecto

Como verás, hay un sin fin de formas de sacarles provecho a las tareas programadas. Mis recomendaciones como desarrollador:

  • Evalua correctamente el tiempo que necesitas para correr un script. Tener un script corriendo cada hora, cuando se necesita conocer la cantidad de deudores al final del día, no es recomendable. Si bien es cierto que funcionará, consumes recursos innecesarios.
  • Las tareas programadas se corren en modo background, por lo tanto el usuario no interactúa con el sistema y no puede ver algún tipo de error. No esta demás hacer un script de pruebas para validar que todo este funcionando correctamente.

Una herramienta estupenda que funciona como demo, es el sitio de Crontab Guru donde puedes probar todo tipo de configuraciones antes de usarlo en tus scripts de producción.

Sitio web de Crontab Guru
Sitio web de Crontab Guru

Espero te haya servido este artículo. Si te fue útil, te agradecería que nos ayudes a compartirlo. Quedamos atentos a tus comentarios que ayude a enriquecer este tema. Estaré entusiasmado de poder interactuar contigo.

Como hacer web scraping para hoteles con PHP Simple HTML DOM

En el pasado tutorial, hicimos una réplica exacta de una página con file_get_contents and cURL. Sin embargo, de esta manera no hay forma de sacarle mucho provecho. Corres el riesgo de que te reporten por plagio o confundan tu proyecto por una página de pishing. El objetivo de este tutorial es obtener las habitaciones más populares de Isla Mujeres con PHP Simple HTML DOM Parser y llenar nuestro template que hemos diseñado previamente con Bootstrap.

La fuente de información será TripAdvisor, uno de las guías más completas para cualquier viajero. Cada vez que accedamos a nuestro proyecto, un script leerá inmediatamente los hoteles más populares según la URL que le hayamos indicado.

Cabe recordar que este es un ejercicio de carácter educativo. No busco promover el plagio de información, sin embargo, existen usos totalmente válidos para esta técnica.

1. ¿Qué necesitas para empezar?

Simple HTML DOM te permite extraer y manipular de manera fácil el html de un sitio web. De la misma manera como lo harías con jQuery o Javascript. Por eso es deseable estar familiarizado con el manejo del DOM en javascript.

2. Extraer la información de los hoteles

Primero necesitamos llamar la dependencia simple_html_dom.php que obtuvimos de su página oficial. En mi caso, tengo identificado la url que vamos a necesitar para extraer información.

// Call dependency
require 'simple_html_dom.php';
// Create DOM from URL or file
$html = file_get_html('https://www.tripadvisor.com/Hotels-g150810-Isla_Mujeres_Yucatan_Peninsula-Hotels.html');

Hasta ahora, hemos extraído el contenido donde se listan los hoteles en TripAdvisor. Este contenido lo almacené en una variable $html para extraer la información que necesitamos. Hasta ahora tenemos una copia exacta de la página de referencia.

3. Identificar las secciones relevantes

Si necesitas obtener una sección del sitio de manera nativa, puedes hacerlo por expresiones regulares usando la función preg_match_all. Sin embargo, es una forma un poco más compleja porque requieres estar creando constantemente expresiones regulares. En este momento es donde Simple HTML DOM hace la magia. Lo que obtuve en la variable $html puedo manipularlo como un objeto a través de funciones definidas por la librería.

Aclarado esto, lo que necesitamos es identificar la sección que deseamos extraer del sitio de TripAdvisor. Esto es sencillo de realizar con el inspector de tu navegador. En mi caso utilizaré el inspector de Google Chrome.

Identificar secciones del sitio web con ayuda del inspector de chrome

Con la herramienta de selección de chrome vamos buscando patrones. En el ejemplo anterior encontramos tres contenedores principales en la plataforma: .header, .page y .footer. En este ejemplo, pondremos atención en el contenedor .page donde esta la lista de las habitaciones que nos importan.

4. Extraer la lista de hoteles de la sección identificada

En este punto lo que queremos es buscar un patrón que identifique como obtener el listado de hoteles. Con el inspector identifiqué las secciones que me interesan:

Visualización de secciones en TripAdvisor

Como podrás observar, hemos encontrado un patrón que comparten todas las contenedores de cada habitación. Todas los contenedores tiene una clase llamada .prw_meta_hsx_responsive_listing. Ahora lo que necesitamos, es obtener toda la información que contiene cada caja con esa clase.


// De todo el contenido, solo necesito la lista de los contenedores de hoteles
$wrap_hotels = $html->find('div.prw_meta_hsx_responsive_listing');

Por medio de la función find, estamos obteniendo todos los contenedores que tienen la clase .prw_meta_hsx_responsive_listing. El resultado es un array que contenido la información interna de cada contenedor. Si haces un echo, el resultado sería algo similar a este:

Array de los hoteles obtenidos en TripAdvisor
Array de los hoteles obtenidos en TripAdvisor

Este array es una muestra de como se guarda la información. Por suerte, con las funciones de Simple HTML DOM nos facilita más las cosas.

5. Identificar las información específica de cada hotel

Ahora lo que necesitamos es extraer los datos específicos de cada hotel. Lo que nos interesa obtener según el template es:

  1. Nombre del Hotel
  2. La foto del hotel o departamento
  3. Precio
  4. Enlace para entrar a los detalles

Hacemos el mismo ejercicio pero en vez de inspeccionar toda la página de hoteles, inspeccionaremos solamente lo que esta en los contenedores que obtuvimos previamente de la clase .prw_meta_hsx_responsive_listing.

Datos del hotel del div con clase .prw_meta_hsx_responsive_listing
Datos del hotel del div contenedor

Identificadas las clases que contienen cada dato que necesitamos, lo primero que necesitamos es recorrer ese array para seleccionar el nombre, precio, imagen y enlace.


// Recorrer la lista de todos los hoteles obtenidos
foreach($wrap_hotels as $element) {
// Código para trabajar cada elemento
}

Tenemos en la variable $element los datos de cada uno de los hoteles, procedemos a obtener la información específica:


// Recorrer la lista de todos los hoteles obtenidos
foreach($wrap_hotels as $element) {
echo "<b>Nombre del Hotel</b> <br />";
echo $element->find('.property_title', 0)->plaintext . '<br />';
echo "<b>Precio</b> <br />";
echo $element->find('.price', 0)->plaintext . '<br />';
echo "<b>Url de la foto del hotel</b> <br />";
print_r($element->find('.inner', 0)->attr) . '<br />';
echo "<b>Enlace donde estan los detalles del hotel</b> <br />";
echo $element->find('.photo-wrapper a', 0)->href . '<br />' . '<br />' . '<br />';
}

Aplicamos el mismo método find para leer el contenido de cada clase. Para obtener el nombre del hotel y el precio usé el atributo plaintext, para que no me muestre etiquetas html en mis resultados. Así funcionan estos atributos especiales:


// Ejemplos de extracción de datos
$html = str_get_html("<div>foo <b>bar</b></div>");
$e = $html->find("div", 0);
echo $e->tag; // Returns: " div"
echo $e->outertext; // Returns: " <div>foo <b>bar</b></div>"
echo $e->innertext; // Returns: " foo <b>bar</b>"
echo $e->plaintext; // Returns: " foo bar"

Para más información, puedes consultarlo en la documentación oficial. El resultado sería como en la siguiente lista.

Nombre del Hotel
Hotel Rocamar
Precio
MX$2,053
Url de la foto del hotel
Array ( [class] => inner [style] => background-image:url(https://media-cdn.tripadvisor.com/media/photo-l/0d/6b/4f/fb/hotel-rocamar.jpg); )
Enlace donde están los detalles del hotel

/Hotel_Review-g150810-d1477852-Reviews-Hotel_Rocamar-Isla_Mujeres_Yucatan_Peninsula.html

Nombre del Hotel
Hotel Plaza Almendros
Precio
MX$971
Url de la foto del hotel
Array ( [class] => inner [data-lazyurl] => https://media-cdn.tripadvisor.com/media/photo-l/08/7c/7c/9e/pool–v7986578.jpg )
Enlace donde están los detalles del hotel

/Hotel_Review-g150810-d616791-Reviews-Hotel_Plaza_Almendros-Isla_Mujeres_Yucatan_Peninsula.html

6. Caso especial. Como obtener la url de la imagen

Todo bien hasta el momento, pero aún tenemos un array al obtener la url de la foto. Puedo usar el atributo style $element->find('.inner', 0)->attr->style, pero si observamos bien, no todos tienen ese atributo. Otros items usan el atributo data-lazyurl, y nos da la url en diferente formato. Esto se debe a que las empresas que se preocupan por el rendimiento de sus sitios, no cargan todas las imágenes y se van cargando conforme el usuario le va dando scroll al sitio.Podemos crear una función donde le pasemos de parámetro ese array para devolvernos como resultado la url sin importar como la obtenga.

/**
* @param Array $attr_image Atributos en forma de array
* @return Image URL
*/
function get_standar_image_url($attr_image) {
// Inicia la variable vacía
$url_image = '';
// Si el atributo es style
if (isset($attr_image['style'])) {
// Recuerda que el style nos da el formato así background-image:url(URL_DE_IMAGEN)
// Usé substr para remover esos caracteres y solo dejarme la url como resultado
// Otra forma es usando regex
$url_image = substr($attr_image['style'], 21, -2);
// Nos proporciona bien la url
} else {
// Aquí nos da la url directa
$url_image = $attr_image['data-lazyurl'];
}
return $url_image;
}

Con la función que tenemos, vamos a realizar un refactory al código donde estábamos trabajando. Lo que haré por cuestiones prácticas es guardar los resultados en otro array que le llamaré $list_hotels  con los valores que necesitaré para llenar mi template.


// Creo una nueva variable que guardara los datos que necesito para mi template
$list_hotels = array();
// Recorro el item original
foreach($wrap_hotels as $element) {
$hotel = new stdClass(); // Es más elegante usar objetos
$hotel->name = $element->find('.property_title', 0)->plaintext;
$hotel->price = $element->find('.price', 0)->plaintext;
$hotel->image_url = get_standar_image_url($element->find('.inner', 0)->attr);
$hotel->href = $element->find('.photo-wrapper a', 0)->href;
array_push($list_hotels, $hotel);
}

Ya obtuvimos el array que nos interesa, ¿ahora que sigue? Podemos trabajar con esa lista para llenar los datos del template del proyecto.

7. Llenar el template del proyecto

Con la ayuda de la variable $list_hotels, vamos a reemplazar nuestros cajas estáticas de nuestro proyecto local que tenemos alojados en CodePen. Tomaremos una caja donde muestra la información de nuestro proyecto.


<div class="col-lg-4 col-md-4 col-sm-6 col-xs-6 ">
<div class="wrap-box">
<div class="box-img">
<a href="#">
<img src="https://mexlike.io/wp-content/uploads/2018/06/Habitación-de-hotel.jpeg" class="img- fluid" alt="Habitación de Lujo">
</a>
</div>
<div class="rooms-content">
<h4><a href="#">Habitación de Lujo</a></h4>
<p class="price">$520 / Por Noche</p>
</div>
</div>
</div>

Puedo suponer que ya sabes que haremos con este proyecto. Vamos a repetir esa caja varias veces por medio de un loop. Nos caería de lujo usar foreach para este propósito, quedando de la siguiente manera:


<div class="d-flex flex-wrap">
<?php foreach ($list_hotels as $hotel): ?>
<div class="col-lg-4 col-md-4 col-sm-6 col-xs-6 ">
<div class="wrap-box">
<div class="box-img">
<a href="<?php echo 'https://www.tripadvisor.com/' . $hotel->href ?>">
<img src="<?php echo $hotel->image_url ?>" class="img-fluid" alt="<?php echo $hotel->name ?>">
</a>
</div>
<div class="rooms-content">
<h4><a href="<?php echo 'https://www.tripadvisor.com/' . $hotel->href ?>"><?php echo $hotel->name ?></a></h4>
<p class="price"><?php echo $hotel->price ?> / Por Noche</p>
</div>
</div>
</div>
<?php endforeach; ?>
</div>

Una vez que recorras el array $list_hotels que generamos resultado del web scraping. Tendremos este grandioso resultado:

Resultado final de los hoteles de Mexlike

A partir de ahora, tenemos un listado de 30 hoteles de Isla Mujeres en nuestro sitio web. Lo podemos mostrar en nuestra página web. También pudimos hacer scraping a las páginas destino de cada hotel, pero haría mucho más complejo este tutorial. Si deseas probar como funciona, te dejo el resultado de este ejercicio:

Ver proyecto final para hacer scraping

Consideraciones especiales

  1. Cuando necesitas extraer un sitio con demasiada información, la librería te llega a limitar. Para aumentar esa limitación, puedes entrar dentro de la librería simple_html_dom.php y modificar la constante MAX_FILE_SIZE. Más información
  2. En el anterior punto no siempre es recomendable modificar fragmentos del código. En especial para los que trabajamos con composer, porque las actualizaciones borran tus cambios.
  3. Hicimos dos foreach: El primero tuvimos que obtener datos específicos para guardarlo en otro array y en el segundo caso para usar ese mismo array para llenar las cajas de nuestro proyecto local. Para optimizar el rendimiento, debimos llenar las cajas desde que obtuvimos los datos de los hoteles sin necesidad de crear otro array. Pero se justifica en el siguiente punto.
  4. Intentar leer la página fuente cada vez que accedemos a nuestro proyecto, es un problema grave de rendimiento. Porque tendría que estar leyendo el sitio fuente cada vez que un usuario accede a nuestro sitio. Lo ideal es separar el script donde realizamos el scraping y guardarlo en algún medio de almacenamiento en nuestro servidor como una base de datos y con una tarea programada. El sitio accedería a la información previamente obtenida por el script. Es un tema que abordaremos en el siguiente tutorial.
  5. El código fuente es funcional a la fecha de la publicación. Sin embargo, la página web fuente puede realizar cambios en sus vistas. Es recomendable revisar que el script este constantemente actualizado. Si es necesario, repetir el proceso de inspección del código fuente de las páginas de referencia.

Por favor, cuéntame que tal te pareció este tutorial. Si te fue de utilidad, ayúdanos a compartir este contenido para poder ayudar a más personas. Si tienes alguna duda u observación, estaré encantado de leerte e intercambiar opiniones para enriquecer este post.

Primeros pasos de Web Scraping con PHP

Primero pasos de Web Scraping con PHP

El uso de estas técnicas te pueden ser de mucha utilidad. Con un fragmento de código puedes recorrer un sitio web de la misma forma que se presenta en un navegador. Puedes guardarlo en una base de datos o mostrarlo en alguna parte de tus sitios. Si deseas conocer más sobre sus usos, te recomiendo leer Introducción al Web Scraping.

Elección de Fuentes para los Primeros pasos de Web Scraping

Como primer objetivo necesitas leer un sitio web externo para después embeberlo en tu propio proyecto, de eso trataré en esta entrada. En el Home quiero obtener los hoteles ubicados en Isla Mujeres desde TripAdvisor.

Lo primero que haremos es ir a la página de tripadvisor.com y realizar una búsqueda de hoteles de Isla Mujeres. No voy a seleccionar un Check In o Check Out porque a mí solo me interesa mostrar la relación de hoteles.

Búsqueda en TripAdvisor para obtener hoteles de Isla Mujeres

Una vez realizada la búsqueda, obtendrías resultados similares a la siguiente imagen. Se trata de un listado de hoteles de Isla Mujeres. Lo que nos interesa es tener la url con los parámetros necesarias que nos despliegue solo hoteles de isla mujeres.

Hoteles de Isla Mujeres en TripAdvisor

Extraer un sitio con file_get_contents

Vamos a utilizar la url que obtuvimos para indicarle a nuestro script lo que queremos mostrar. Primero crearé el archivo scraper.php donde contendrá el script que leerá el sitio contenido de la URL señalada.

<?php
// Lee la url y obtiene el contenido en una variable
$html = file_get_contents("https://www.tripadvisor.com/Hotels-g150810-Isla_Mujeres_Yucatan_Peninsula-Hotels.html");
// Se imprime lo que obtuvimos en esa variable
echo $html;
?>

Funciona, pero no siempre llega a ser así. Es necesario tener activado la directiva allow_url_fopen en el php.ini de tu servidor. Sino sabes como activarlo, te recomiendo que te des un clavado en este artículo sobre como activar allow_url_fopen en tu servidor.

Cuando trabajas de manera local, no parece ser un problema. Sin embargo, no todos los servidores dan privilegios de modificar sus archivos de configuración. Así que otra alternativa de poder tener los resultados en nuestro sitio es a través de cURL.

Extraer un sitio con cURL

cURL es una herramienta que te permite obtener información de distintos protocolos, además puedes hacer envíos de parámetros GET y POST. Su uso es tanta común que llega a ser utilizado en los crawlers para recolectar información de la web.

Por esas razones cURL es mi función predilecta porque me permite hacer conexiones. Incluso podría entrar a un área protegida por medio de mecanismos de autenticación.

La pregunta es ¿cómo hacer scraping para obtener un resultados similar al anterior? Realmente es muy sencillo, si bien requieres de más código para definir lo que quieres obtener realmente, lo podríamos encapsular en una función como lo haré en el siguiente ejemplo.

<?php
// Definimos la función cURL
function get_content_with_curl($url) {
// Inicial la función url
$ch = curl_init($url);
// No verifica el peer del certificado. Opcional
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
// Establece la sesión
$data = curl_exec($ch);
// Cierra la sesión
curl_close($ch);
return $data;
}
// Llamo la función previamente definida. La guardo en una variable por si deseo manipularla
$html = get_content_with_curl("https://www.tripadvisor.com/Hotels-g150810-Isla_Mujeres_Yucatan_Peninsula-Hotels.html");
// Imprimir la cadena recibida
echo $html;
?>

Realmente lo que hicimos fue crear una función que nos permitiera obtener un sitio web, tal como lo lee un navegador, por medio de cURL. Con esto ya tenemos el sitio original en nuestro sitio.

Resultados de hoteles de Isla Mujeres de TripAdvisor en Mexlike

Resumiendo, el Scraping se basa en leer datos de otras fuentes. Aquí solamente leímos la web tal como está en la versión original, sin embargo, no le podríamos dar mucho uso de esta manera. Cada vez que requiera obtener datos de otras ciudades, solo llamaría esta función definida previamente. Para ser más selectivo en el contenido que obtenemos de cada sitio, es necesario desarrollar funciones más detalladas, sin embargo no es el objetivo de este post.

Como aclaración, hasta este punto aún no podemos darle un uso éticamente aceptable a esta técnica. Copiar contenido de otras fuentes y usarlo indiscriminadamente en tus sitios podría ser contraproducente. En el próximo post, vamos a especificar que secciones necesitamos de los resultados que nos da TripAdvisor para nuestros proyecto con estilos propios.

Espero te haya gustado este post y/o te haya sido de utilidad, te agradeceríamos mucho si nos ayudas a compartir. Si tienes algún comentario, no dudes escribirnos en la caja de comentarios. Siempre estaremos ansiosos de intercambiar ideas con nuestros lectores.

Introducción al Web Scraping

En internet existe una infinidad de información, es tanta la información que no podemos consumirla toda al misma tiempo. ¿Te imaginas extraer todos esos datos de manera manual recurrentemente? Por suerte, existen aplicaciones que buscan extraer datos, los procesan y ofrecen un información útil para nosotros. Este proceso se le conoce como web scraping.

¿En que consiste el scraping?

Web scraping es una técnica utilizada, por medio de software, para obtener información pública de cualquier web. Esta técnica consiste en buscar fuentes que te proporcionen contenido para fines estadísticos o que mejoren la experiencia de usuario.

Como funciona el Web Scraping
Funcionamiento del Web Scraping con tenido público

Este proceso puede ser único o periódico, dependiendo tus objetivos. Es una alternativa más ágil cuando necesitas obtener una gran cantidad de datos en periodo corto de tiempo. En el mayor de los casos es periódico, porque comúnmente se necesitan datos recientes.

El web scraping no promueve la ilegalidad

Debemos ver al scraping como una técnica que facilita una tarea específica como cualquier otra técnica. El uso que se le de, cambia la perspectiva de las cosas. Debemos pensar en la línea delgada entro lo legal y no. Pero eso depende del tipo de uso que le des. Recomiendo leer este artículo que habla respecto a ese tema: Web Scraping: ¿Legal, ilegal o depende?

Sus usos en la actualidad

Es común que nuevas startups basen sus operaciones en recolectar datos. Llegan a ser técnicas bastante explotadas en la fase inicial de las startups donde la información es crucial para la operación. También existen aplicaciones móviles que usan esa técnicas como los las apps de marcadores, de bolsa de valores y hasta asistentes para realizar tu despensa.

En lo personal he creado dos catálogos donde considero en mi experiencia para que podría servir esta técnica se se maneja adecuadamente:

Que tipos de datos se recomiendan extraer

  • Datos efímeros como marcadores de futbol, tipos de cambios clima, acciones de La Bolsa de valores, etc.
  • Reservaciones de hoteles de diferentes lugares.
  • Encabezados de las noticias más relevantes. Podríamos generar un directorio y darle un uso inteligente a esa información.
  • Contenido para fines internos solamente. Estadísticas, encuestas, opiniones de usuarios acerca de un tema en específico.

Que no se vale e incluso podría ser penalizado

  • Obtener contenido original para replicarlo en tu sitio web.
  • Datos que hagan una alusión personal, aunque sean públicos. Con los buscadores tenemos suficientes, incluso hasta Google ha tenido dificultades con noticias relacionadas a ciertas figuras públicas, conocida como El derecho al olvido, dictada por el Tribunal de Justicia de la Unión Europea.
  • Datos personales como teléfono, correos, direcciones. Los puedes obtener para usos internos pero no los puedes explotar para enviar información al usuario. Las penas por realizar ese tipo de prácticas depende de la legislación en cada país.

¿Quiénes hacen uso del web scraping?

El scraping es una práctica tan común que son usados en las herramientas que frecuentemente usamos, como por ejemplo:

Google

El mayor scrapper de todos los tiempos hasta ahora. Cuenta con un directorio de millones de páginas web que va indexando diariamente a través de sus crawlers.

Google scraper

Twitter

Esta red social que ha tumbado dictaduras hace uso de las vistas previas. Twitter hace una extracción de datos básicos para poder mostrar un vista previa que mejore la experiencia de usuario.

Twitter Scraper

Slack

A diferencia de las anteriores, slack es un sistema de mensajería en tiempo real creado para fines colaborativos. Incluso, prácticamente todos las apps de mensajería cuentan con esta función.

Uso de scraping con slack


Con esto, te puedes dar cuenta que el scraping es una técnica muy útil para enriquecer la experiencia de usuario o incluso realizar estudios que mejoren esa experiencia. Una recomendación es que cuides la frecuencia que consultas un sitio en específico. Si saturas mucho las consultas de un sitio corres el riesgo de que tu ip sea bloqueada.

En futuros posts, te mostraré como realizar scraping con herramientas de terceros, también hacerlo de manera nativa por medio de scripts propios y por último como hacerlo por medio de librerías. Ninguna es mejor que otra, todo depende de las necesidades de tu proyecto.

Si te pareció útil esta entrada, te agradecería que me ayudes a compartirla. Cualquier duda u observación, nos puedes escribir en la caja de comentarios y será un placer poder intercambiar opiniones.

SQL vs NOSQL. Conoce sus diferencias y cuando utilizarlas

Diferencias de SQL vs NOSQL

Los lenguajes de programación que manejan información necesitan de un lugar donde se almacenen los datos. En concreto una base de datos es un conjunto de información organizado en distintos formatos para su posterior uso. Las bases de datos van más allá de sólo utilizar MySQL el cual entra en la categoría de una base de datos relacional.

Base de datos SQL

Structured Query language (SQL) o lenguaje de consulta estructurada, utiliza un estándar para manipular el contenido de las bases de datos relacionales. Cuenta con su propio lenguaje para consultar, insertar, actualizar y eliminar registros de la base de datos.

Se compone de una o varias tablas y cada tabla puede contener múltiples relaciones. En el siguiente elemento pongo como ejemplo en como está estructurada una sencilla base de datos por medio de tablas.

Eventos deportivos por medio de una base de datos relacional

Las tablas representan la entidad de cada modelo de datos. Las relaciones permiten garantizar la persistencia de datos, evita la duplicidad de datos y controla la eliminación en cascada. Para ingresar un nuevo nuevo evento, bastaría con ingresar un nuevo registro en la tabla events.

SQL cuenta con un lenguaje de alto nivel que permite manipular la base de datos casi de cualquier forma. Por su manera de operar ayuda a mantener la integridad de los datos. Por ejemplo:

Para obtener la lista de todos los deportes

SELECT id, name FROM sports

Ingresar varios registros a la tabla categoría

INSERT INTO categories VALUES (Varonil, Femenil, mixto)

Su uso es mas frecuente es en sistemas donde se necesite cuidar la integridad de datos como los bancos, sistemas de ventas, hospitales, CMS como WordPress.

Ejemplos de sistemas de gestión de base de datos son: MySQL, MariaDB, PostgreSQL.

Base de datos NoSQL

También existen otros mecanismos de almacenamientos alternativos a las base de datos relacionales que se definen por tablas. Este tipo de base de datos, se apoyan en otros formatos. Los NOSQL son más adecuados para aquellos que manejan grandes volúmenes de datos. Es por eso que empresas como Facebook, Google, Amazon, Twitter, entro otros han popularizado estos tipos de base de datos.

Esas empresas tenían que enfrentarse a grandes desafíos motivados a la alta demanda de internet. Donde surge la necesidad de proporcionar información de grandes volúmenes de datos e indeterminado número de usuarios en el menor tiempo posible. Esas compañías se dieron cuenta que podían sacrificar la consistencia de los datos que garantiza una base de datos relacional para poder obtener un mejor rendimiento y ofrecer soluciones en tiempo real.

Los puedes usar en soluciones donde requieres interactuar con datos en tiempo real como en un chat, para análisis estadísticos donde procesas mucha información o incluso en blogs.

Algunos tipos de bases de datos NoSQL incluyen diferentes tipos de almacenamiento, por ejemplo: con columnas, documentos, key value store, gráficos, objetos (JSON), XML y otros modos de almacenamiento de datos.

¿Qué hace diferente SQL vs NOSQL?

Una de las diferencias más relevantes entra una NOSQL a una base de datos relacional, es por su forma de almacenamiento no estructurada.

¿Cuál podría ser apropiada para mi proyecto?

Depende mucho de la solución y cuales son los puntos fuertes que necesites ofrecer en tus gestión de información. Ambos tienen sus pros y sus contras. Puedes elegir entre la consistencia (SQL) o la alta disponibilidad (NOSQL). En la mayoría de mis proyectos apuesto por la consistencia porque los proyectos no requieren una disponibilidad en tiempo real de los datos.

¿Qué te pareció el artículo? Quedo al pendiente para tus comentario o cualquier duda. Si te pareció interesante, no dudes en compartirlo.

Crea tu primer sitio web con WordPress

Crear tu primer sitio web con wordpress

Hoy en día montar un sitio web es más fácil que hace una década. Con el surgimiento de los gestores de contenidos, mejor conocidos como CMS, es posible tener un sitio web informativo con un diseño profesional sin conocimientos técnicos avanzados. Incluso existen servicios de hosting que permiten montar tus sitios en cuestión de algunos clics. Así que no existen pretextos para crear tu primer sitio web con WordPress.

¿Porqué WordPress?

WordPress, en los últimos años, se ha convertido en uno de los CMS más populares cuando de sitios web se trata. Inicialmente fue creado para crear blogs, pero gracias a su creciente comunidad fue adaptado para crear sitios web de cualquier temática.

Primeros pasos con WordPress

Existen dos formas de crear un sitio web con WordPress. La primera a través de su plataforma comercial wordpress.com o través de wordpress.org donde podrás descargar su código fuente para instalarlo directamente en tu hosting.

Se requiere un poco de conocimiento básicos sobre como crear una base de datos y acceso a FTP por medio de un cliente como Filezilla.

1. Descarga wordpress

Accede al sitio wordpress.org y da click en el botón Descargar WordPress para obtener los archivos del gestor de contenidos.

Página para descargar wordpress

Vale la pena recalcar que dependiendo el idioma de tu contenido, descargues la versión correspondiente por cuestiones de SEO. Sin embargo, puedes atender ese inconveniente sobre la marcha.

2. Instala los archivos

Descomprime y copia los archivos dentro de la carpeta donde deseas cargar tu sitio web

Directorio de sitio web con wordpress

3.1 Crea la base de datos con phpMyAdmin

Para poder usar tu versión de WordPress, necesitas crear una nueva base de datos. Si tienes acceso a phpMyAdmin, entras a la pestaña de base de datos. Crear el nombre de la base de datos, yo usaré Mexlike como nombre.

Crea la base de datos de mexlike con phpMyAdmin

3.2 Usa un cliente para crear una base de datos

Existen muchos clientes para conectarse a la base de datos como Navicat, Workbench, Sequel Pro, etc… En mi caso particular utilizo Sequel Pro porque no requiero un software tan completo como Navicat.

Crear Base de Datos Mexlike con Sequel Pro

Solamente necesitas entrar a la conexión donde deseas instalar tu base de datos, le das a la opción en elegir base de datos, añadir base de datos y desplegara una ventana donde podrás ingresar el nombre de la base de datos Mexlike.

4. Configura tu sitio web

Ya tienes los archivos en el directorio de tu sitio web y una base de datos activa que servirá para poder completar la instalación. Ahora necesitas configurar tu sitio web con WordPress con el instalador que viene incluido.

Elegir el idioma de tu wordpress

Como mencioné anteriormente, es recomendable que uses el idioma que vaya de acuerdo al contenido de tu sitio. Es hora de agregar los datos de la base de datos que creaste previamente. Ingresa los datos que configuraste previamente de la base de datos mexlike.

Configurar datos de acceso de MySQL en wordpress

El formulario se llena según la configuración de tu hosting:

  • Nombre de la base de datos: Base de datos que creaste
  • Nombre de usuario: Según los datos de acceso
  • Contraseña: Según tu datos de acceso
  • Servidor de la base de datos: Regularmente es localhost
  • Prefijo de la tabla: Puede ser personalizable

Estamos a un paso de terminar. Llegamos a la pantalla que nos dice que estamos listos.

Correr la configuración de base de datos de wordpress
Para finalizar, ingresamos los datos de acceso para fines administrativos.

Ingresar datos para el wp-admin de WordPress

5. Resultado Final

Con esos datos, ya tienes instalado WordPress en tu servidor. A partir de este momento tienes un sitio totalmente a tu control que lo puedes personalizar a través de templates libres, de pago o personalizados.

Sitio web inicial creado con wordpress

Con esto terminamos la primera parte de este tutorial. En el próximo post configuraremos nuestro sitio web con un template libre.

Espero que este post haya sido de tu agrado. Para cualquier duda o sugerencia quedo abierto a través de la caja de comentarios.

¿Debo usar un CMS o desarrollar desde cero?

Debo usar un CMS o desarrollar desde cero

Tienes un proyecto que te gustaría desarrollar, ya sea viniendo de una idea de negocio o por requerimiento de un cliente. La primera pregunta que se nos viene como desarrolladores es el stack a utilizar. Para que el proyecto avance de una manera efectiva, deberíamos quitarnos la bandera de puristas y ser más objetivos en nuestras decisiones.

Como desarrollador entiendo el sentimiento de querer controlar todo, conocer cada parte de la maquinaria. Además, queremos cumplir el reto para resolver algoritmos más complejos. Sin embargo, cuando se trata de crear soluciones, una buena decisión te puede ahorrar muchos dolores de cabeza.

¿Cuáles son los motivos para considerar si debo usar un CMS?

Para empezar, definamos el verdadero propósito de un CMS (Content Management System) también conocido como Sistema Gestor de contenidos. Su función principal proporcionar herramientas que permitan crear, editar y organizar información, de tal manera, que tengamos un sistema totalmente funcional desde un principio.

Lo primero que deberías tomar en cuenta es estudiar los requerimientos del proyecto, con ello podrías trazar una ruta de tiempo, identificar los módulos que son must have y responder cual será tu función como desarrollador para generar valor a través del proyecto.

Además existen factores que deberías considerar en las buenas prácticas en el desarrollo de software:

  • Tiempo de desarrollo: Cuando creas un nuevo proyecto, deberías mucho énfasis en el tiempo. Usa inteligentemente tu tiempo y utiliza los recursos a tu favor.
  • Mantenimiento: Es inevitable tener ciclos iterativos en el tiempo de vida de un sistema sino queremos caer en la obsolescencia programada. Evalúa que tipo de mantenimiento estaríais haciendo en el software una vez liberado.
  • Seguridad: Por lo general, en las comunidades de desarrolladores cuidan mucho ese aspecto.
  • Flujo del proyecto: Evalúa si los módulos son a la medida de acuerdo a los procesos internos de la empresa o proyecto. No es lo mismo implementar un sistema donde generas contenido que un sistema de reclutamiento.

Casos Prácticos

Debo aclarar que no existe una receta de cocina a la hora de tomar una decisión. Pero puedo compartir, en mi experiencia, en que situaciones los CMS son mejores de acuerdo a los puntos anteriores:

Caso 1

Un cliente me pide un sitio web con el contenido editable, pero a la vez quiere integrar sus webinar con una campaña de email marketing.

  • Bajo esas circunstancias tomaría la opción de usar WordPress.
  • Desarrollo un plugin para gestionar el webinar en caso de que no existiera alguna otra solución estable
  • Con ese mismo plugin, podría encargarme de notificar al gestor de email marketing los eventos que sean necesarios

Como te darás cuenta, me apalanqué en el trabajo de la comunidad de WordPress para las cuestiones de contenidos y enfoque mi experiencia en soluciones más enfocadas.

Caso 2

Una startup me pide que desarrolle un sitio con dos páginas de aterrizajes. La primera debe permitir obtener información del prospecto para después mandarles información de su servicio. La segunda página de aterrizaje es un carrito de compra donde ellos ofrecen sus ebooks y camisetas.

  • Para generar contenido, usaré un CMS.
  • Tengo dos opciones: La primera sería usando Prestashop o Magento porque su principal aplicación es la creación de tiendas de comercio electrónico. La otra opción podría usar WordPress apoyado de un plugin de eCommerce.
  • Me decantaré por la segunda opción porque investigando más a fondo con los fundadores, ellos están en un proceso de validación de su producto y por lo tanto no necesitan un sistema tan complejo como prestashop que fue creado para gestionar una gran cantidad de productos. Además su modelo de negocio de ellos va mas por el servicio y la consultoría.
  • Como ellos usan mailchimp para gestionar sus campañas de email marketing, usaré un plugin que permita al cliente recabar información de sus prospectos. Toda la gestión lo hacen con la plataforma
  • Por último, como mencioné antes, usaré un plugin gratuito de eCommerce, usaré WooCommerce porque cuenta con una comunidad muy activa de tal manera que tengo soporte casi garantizado. Ademas, es fácil integrar PayPal y los cobros por tarjeta.

A pesar de que esta solución aparentaba ser mas compleja, tomamos la decisión de usar soluciones estables que cubrían todas las necesidades de los fundadores.

Caso 3

Una agencia especializada en reclutar personal de seguridad me pide que le desarrolle un sistema para gestionar su personal. Además, el cliente me proporciona la información que necesita del reclutado, el estricto proceso de reclutamiento y la documentación que valide todo ese proceso.

  • No conozco un CMS que se acerque a lo que necesita este cliente. Si intentara usar uno e intentara adaptarlo, podría generar una crisis en el mantenimiento.
  • En estas situaciones podría apalancarme a través de un Framework. Donde tenga resulta la autenticación  y tenga definido algún patrón de desarrollo. De esa manera no sacrificó la seguridad y aún estaría creando soluciones completas pero con un desarrollo simple.
  • Diseño las estructuras de datos para almacenar los datos del reclutado, su documentación, proceso de selección y los registros de asignación. Para darle un seguimiento a su rendimiento con el cliente.
  • Módulo para generar y editar información.
  • Sección para asignar registros de entrevista.
  • Herramienta para subir la documentación al sistema.
  • Funcionalidad para registrar la asignación del personal a un cliente.
  • Defino las información que se necesita descargar.

La solución es mas compleja que la descrita anteriormente, pero intento justificar en esta situación de porque no pude usar un CMS. La ventaja es que cualquier cambio en el proceso interno de la empresa, el software permite que sus cambios sean rápidos porque no estamos ante una solución genérica como en caso de los CMS.

Como conclusión

Los CMS cuentan con herramientas que nos pueden ahorrar mucho trabajo y permiten que ofrezcamos valor con retos más enfocados. Su principal función es enfocarse en soluciones muy demandadas, sus módulos llegan a ser muy genéricos. Para propósitos específicos nos juegan como un arma de doble filo.

Mi objetivo es poder generar un debate, porque en el desarrollo no existen las soluciones correctas. Entonces esto corre a criterio según la experiencia de cada programador. Me gustaría saber tu opinión ¿De que manera lo resolverías tú?

5 aplicaciones que ayudaran aumentar tu productividad

Es obvio que existen aplicaciones muy útiles a nuestra disposición  que te ayudarán aumentar tu productividad en el control de tus tareas que realizas día a día. En ocasiones al final del día algunas de estas tareas no llegan a cumplirse, ya sea porque caímos en el mal hábito de perder tiempo o por olvido.

A veces no somos capaces de organizarnos para mejorar  nuestra productividad. Hoy te traemos una recopilación de 5 aplicaciones que te ayudarán a organizarte  y aprovechar mejor tú tiempo.

  Todoist

Con Todoist puedes hacer un seguimiento a todas tus actividades, desde cosas simples, hasta cosas más complejas ayudándote a aumentar tu productividad. Está disponible para Android y iOS, es gatuito, está disponible en español y tiene una versión Premium con opciones adicionales.

Con la  versión gratuita puedes hacer la mayoría de las operaciones básicas de cualquier gestor de tareas tales como organizar listas de tareas, dividirlas en proyectos, marcarlas como completadas, establecer fechas, etc.

Todoist es ligera, rápida, y su sincronización es en tiempo real y en tus dispositivos favoritos (móviles Android, escritorio y navegador web). Incluso cuando no estás conectado/a.

 

  Evernote

Es una aplicación fácil de usar que te proporciona las herramientas que necesitas para mantenerte organizado sin ningún esfuerzo.

Evernote está disponible para Windows y Mac y también en todas las plataformas móviles: IOS, Android y Windows phone e incluso tiene una extensión para Chrome, con Evernote todo el contenido guardado estará disponible en cualquier dispositivo que se utilice.

No sólo te permite tomar notas mejorandolas con enlaces, fotografías, listas de tareas, tablas, archivos adjuntos, escanear tarjetas de negocio y grabaciones de audio, incluso se puede buscar las notas escritas a mano.

Todo lo que realizas en Evernote queda guardado y sincronizado en la nube

 

  Trello

Con Trello  se puede gestionar cualquier tipo de proyecto que hace que la colaboración sea más sencilla, es una aplicación que está disponible para iPhone, iPad, teléfonos Android, tabletas y relojes.

Trello es una aplicación que permite crear tableros de forma rápida  para organizar cualquier proyecto, añadir listas de tareas pendientes, asignar tareas a uno mismo o a sus colaboradores,  organizar por colores o monitorizar las actividades que se están llevando a cabo por cualquier miembro de la lista compartida, realizar comentarios, adjuntar archivos de Google Drive y Dropbox. También ofrece sincronización en la nube.

 

  Time Tune

Es una aplicación de administración del tiempo que ayudará hacer más cosas con su tiempo.

TimeTune aumenta tu productividad de manera que puedes utilizarlo como agenda de actividades diarias, se basa en organizar los días y semanas en secciones, o rutinas, llevando a cabo pequeñas tareas para lograr cumplirla, recordatorio de tareas, calendario de estudios, planificador de horarios, estadísticas de rutinas para analizar y mejorar tu distribución de tiempo etc.

 

  DropBox

Dropbox es un espacio de colaboración creativa diseñado para aliviar la carga de trabajo, recopilar tus archivos en un lugar centralizado y sincronizarlos de forma segura con todos tus dispositivos para que puedas acceder a ellos en cualquier momento, estés donde estés. Además, es sencillo enviar archivos de gran tamaño, incluso a personas que no tienen una cuenta de Dropbox.

Acceder desde diferentes sistemas operativos (Windows, Mac y Linux) y dispositivos móviles (iPhone, Android, iPad, BlackBerry).