HTML

JavaScript: tomando una foto de la cámara en una web

2020-04-13 - Categorías: General / JavaScript
Logo de Javascript

Pequeño howto o codekata para tomar una foto desde la webcam en una web. Con este script incrustado en una web, se le preguntará al usuario por el permiso para acceder a los dispositivos de vídeo y audio disponibles en el dispositivo. Entonces si el usuario da permiso para su uso, se mostrará una caja con el vídeo y audio que se reciben en tiempo real. Sólo se usa HTML y Javascript.

Simplemente se pinta en la caja de video el stream de vídeo con audio en tiempo real. Y tenemos también un canvas en donde podemos pintar una captura de un fotograma del vídeo que estamos viendo. La captura del fotograma que se pinta en el canvas se hace con el botón disponible.

Continuar leyendo..

Javascript: obtener las coordenadas geográficas de una visita a la web

2020-04-10 - Categorías: General / JavaScript

Sencillo codekata para obtener las coordenadas de una visita a una web mediante Javascript. Funciona en navegadores de ordenadores y dispositivos móviles. Mostrará un mensaje emergente cuando se haga la consulta de las coordenadas. Devuelve latitud y longitud según el navegador.

Este script pide al navegador las coordenadas. Si estamos en un móvil con Android con Google Chrome, por ejemplo, el GPS del dispositivo móvil le servirá las coordenadas exactas al navegador, y el navegador a la web, si el usuario da el permiso.

Al grano, el código fuente

<!DOCTYPE html>
<html lang="es" dir="ltr">

    <head>
        <meta charset="utf-8">
        <title>JnjSite.com: Javascript Geolocation</title>
    </head>

    <body>
        <h1>JnjSite.com: Javascript Geolocation</h1>
        <p>Your current location is latitude <span id="spanLatitude"></span> degrees and longitude <span id="spanLongitude"></span> degrees.</p>
        <p id="theError"></p>
        <script type="text/javascript">
            function positionSuccess(position) {
                alert('SUCCESS');
                document.getElementById('spanLatitude').innerHTML = position.coords.latitude;
                document.getElementById('spanLongitude').innerHTML = position.coords.longitude;
                console.log(position);
            }

            function positionError(error) {
                alert('ERROR');
                switch (error.code) {
                    case error.PERMISSION_DENIED:
                        document.getElementById('theError').innerHTML = "User denied the request for Geolocation."
                        break;
                    case error.POSITION_UNAVAILABLE:
                        document.getElementById('theError').innerHTML = "Location information is unavailable."
                        break;
                    case error.TIMEOUT:
                        document.getElementById('theError').innerHTML = "The request to get user location timed out."
                        break;
                    case error.UNKNOWN_ERROR:
                        document.getElementById('theError').innerHTML = "An unknown error occurred."
                        break;
                }
            }
            window.onload = () => {
                if (navigator.geolocation) {
                    alert('Browser has Geolocation');
                    navigator.geolocation.getCurrentPosition(positionSuccess, positionError);
                } else {
                    alert('Browser do not support Geoloation');
                }
            };
        </script>
    </body>

</html>

Hola mundo con VueJS

2020-04-10 - Categorías: General / JavaScript
VueJS hola mundo 2

Uno de los principales frameworks Javascript a fecha de hoy es VueJS. Los más populares, según los resultados en varias páginas encontradas con Google, son Angular, React y VueJS. Y en concreto VueJS me ha sorprendido por lo sencillo de empezar a usarlo.

Es un framework progresivo para desarrollo del frontend, que hace que podamos comenzar a usarlo progresivamente. Es decir, podemos usarlo en parte para hacer algo muy concreto en una parte de la web, o más, incluso llegando a ponerlo a controlar el frontend al 100%. Es una librería muy ligera, que proporciona un sistema, a base de Javascript con el que con directivas y poco más, podemos hacer que la web sea mucho más interactiva sin tener que picar casi código Javascript.

Continuar leyendo..

Nueva versión del sencillo mensaje de aceptar cookies para tu web

2018-12-01 - Categorías: General
Monstruo come galletas

Un lector me ha escrito consultando sobre un post algo antiguo, sobre cómo poner un sencillo mensaje de cookies en una web. La verdad es que no me he explicado muy bien en aquel post, los navegadores han cambiado durante estos últimos años, JavaScript también.. así que aquí estoy compartiendo otro mensaje de aceptar cookies más actual.

Este mensaje de aceptar cookies es una actualización de aquel antiguo que vengo usando en nuevos proyectos. Es un mensaje hecho artesanalmente que puedes copiar y pegar para tu web. El único requisito que tiene es que necesitas usar la librería de jQuery para que funcione. jQuery hoy día es como un estándar, hace tan bien su trabajo de acceder al DOM de las páginas web, que cómo no usarlo en todos los proyectos.

Continuar leyendo..

Symfony: cómo montar un blog con editor WYSIWYG

2018-09-20 - Categorías: PHP / Symfony
Symfony WYSIWYG

De nuevo traigo otro CODE-KATA, para montar un blog en Symfony Flex, Symfony 4. Así en unos pocos minutos tenemos el esqueleto de lo que puede ser un blog. También valdría para hacer páginas corporativas, incluso si lo que queremos es un editor de fichas de productos también. Es decir, este es un pequeño tutorial para arrancar un nuevo proyecto en Symfony, creando es esqueleto de una aplicación web que va a ser un blog, con un editor de texto avanzado del tipo WYSIWYG.

WYSIWYG quiere decir What You See Is What You Get. Es decir, estos editores de texto son como los que tienen WordPress, Magento, Prestashop.. en donde se editan las páginas visualmente dentro del mismo navegador. Con este tipo de editores puedes organizar los textos, darles tamaño a las letras, alineación, subrayados, colores, etcétera.

Continuar leyendo..

Popup de Mailchimp para WordPress

2018-08-27 - Categorías: Magento / Prestashop / Symfony / WordPress
Popup de Mailchimp de jnjsite.com

He tenido problemas para poner un popup de Mailchimp en esta web. Así que aquí estoy compartiendo la solución. He tratado de usar la utilidad que viene en el panel de control de Mailchimp. Pero todo apunta a que tengo algún conflicto entre los Javascripts de Mailchimp, los Javascripts de mi plantilla, algún plugin de cacheado o del minificado del código fuente. En fin, que no funcionaba y he terminado antes haciendo el popup artesanal que se puede ver en la barra lateral derecha de la web.

Si has tenido el mismo problema, aquí dejo mi solución, que espero que funcione en el 100% de las webs. Simplemente necesitas tener instalado en la web jQuery, el resto viene todo en el código de abajo. Se puede copiar y pegar en el widget de WordPress donde lo quieras y adaptarlo para tu web.

Continuar leyendo..

Prolog: enlazando un sistema experto con PHP

2018-07-08 - Categorías: Inteligencia Artificial / PHP / Prolog
Prolog enlazando PHP

Hoy traigo cómo enlazar proyectos web en PHP con partes hechas en Prolog. No he encontrado casi información en Internet, así que aquí estoy compartiendo algo sobre esto. Este es un simple HOWTO para tratar las respuestas, o muchos de los casos que puedes tener en ataques a Prolog desde PHP.

La idea general es que tenemos uno o varios programas en ficheros .pl. Estos ficheros a su vez se pueden autoincluir unos en otros con sentencias del estilo include o import como en otros lenguajes. Además, también estos ficheros .pl se pueden generar automáticamente desde otras fuentes de datos. Esta dinamicidad de la parte programada en Prolog es una de las cosas más interesantes. Es decir, los programas en Prolog pueden cambiarse a si mismos, tema muy interesante en Inteligencia Artificial. Esto es, los programas en Prolog pueden aprender sobre la marcha, además de que, la base de conocimiento puede nutrirse de muchos datos externos también sobre la marcha.

Continuar leyendo..

Symfony: creando landings con formularios, segunda parte

2018-05-08 - Categorías: PHP / Symfony
Landing pages con Symfony

En el post anterior escribí sobre cómo crear una landing page rápido con Symfony 4, y se me quedó pendiente el enviar por email los mensajes del formulario. Es decir, ya tenemos en un rato una rudimentaria ‘landing page’ donde un maquetador o el equipo de marketing disfrutará poniendo cualquier cosa. Será como maquetar con HTML, CSS y Javascript sin tener ningún engorroso CMS por debajo limitándonos lo que podemos hacer. Además tendremos la base de un buen Symfony para después añadir lo que queramos.

Ya tenemos la captación de contactos (o capture leads para los entendidos), que se guardan en una base de datos embebida en la propia web. Sin complicadas instalaciones ni configuraciones SQL, directamente con una base de datos SQLite embebida.

Sólo queda entonces hacer 3 cosas:

  • Instalar el módulo de Swiftmailer.
  • Configurarlo.
  • Y poner la acción de enviar el email.

Vamos al grano..

1. Instalando Swiftmailer

Para esto basta con poner en el terminal lo siguiente:

composer require symfony/swiftmailer-bundle

..esperamos, y si todo ha ido bien tenemos que ver en el terminal algo como lo siguente:

Using version ^3.2 for symfony/swiftmailer-bundle
./composer.json has been updated
Loading composer repositories with package information
Updating dependencies (including require-dev)
Package operations: 3 installs, 0 updates, 0 removals
 - Installing egulias/email-validator (2.1.4): Loading from cache
 - Installing swiftmailer/swiftmailer (v6.0.2): Loading from cache
 - Installing symfony/swiftmailer-bundle (v3.2.2): Loading from cache
Writing lock file
Generating autoload files
ocramius/package-versions: Generating version class...
ocramius/package-versions: ...done generating version class
Symfony operations: 1 recipe (8c3c4103f30ebcc7579093a6f39dc028)
 - Configuring symfony/swiftmailer-bundle (>=2.5): From github.com/symfony/recipes:master
Executing script cache:clear [OK]
Executing script assets:install --symlink --relative public [OK]

Some files may have been created or updated to configure your new packages.
Please review, edit and commit them: these files are yours.

2. Configurar swiftmailer

Ahora las principales variables de configuración son variables de entorno. Esto es mucho más seguro ya que se pueden incluso no guardar en ningún fichero, pero la forma más sencilla es usar el fichero .env que debemos tener en el directorio raiz del proyecto. Si lo abrimos veremos que tenemos añadida la configuración de Swiftmailer:

###> symfony/swiftmailer-bundle ###
# For Gmail as a transport, use: "gmail://username:password@localhost"
# For a generic SMTP server, use: "smtp://localhost:25?encryption=&auth_mode="
# Delivery is disabled by default via "null://localhost"
MAILER_URL=null://localhost
###< symfony/swiftmailer-bundle ###

Como bien explica en los comentarios, así hacemos. Pero para evitarte problemas te recomiendo usar siempre SMTP con un buen servidor de correo electrónico. Por Internet hay muchos ejemplos, uno puede ser este:

MAILER_URL=smtp://tudominio.com:587?encryption=tls&auth_mode=login&username=tuusuario&password=tucontraseña

Estas configuraciones usando SMTP son compatibles con la mayoría de los servidores de correo electrónico, sino todos. Tales como Mandrill, Amazon SES, Gmail, etcétera.. podrás configurarlos así, sólo tienes que encontrar las configuraciones que le pondrías a tu Outlook o Thunderbird y ponerlas en el proyecto de Symfony.

3. Enviar el email

Remitiéndome al post anterior, sólo nos queda en el controlador donde recibimos el contenido del formulario el enviarnos un email informándonos de que alguien nos ha dejado un mensaje. Para esto ponemos algo como esto en el controlador, marco en negrita lo nuevo:

<?php

namespace App\Controller;

use Symfony\Component\Routing\Annotation\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use App\Form\ContactType;
use App\Entity\Contact;

class MainController extends Controller
{
    /**
     * @Route("/", name="main")
     */
    public function index(Request $request, \Swift_Mailer $mailer)
    {
        $contact = new Contact();
        $theForm = $this->createForm(ContactType::class, $contact);

        $theForm->handleRequest($request);

        if ($theForm->isSubmitted() && $theForm->isValid()) {
            // save in database
            $entityManager = $this->getDoctrine()->getManager();
            $entityManager->persist($contact);
            $entityManager->flush();

            // send email
            $message = (new \Swift_Message('JnjSite.com:: mensaje desde la web'))
                ->setFrom(['info@jnjsite.com' => 'Web JnjSite.com'])
                ->setTo([
                    'info@jnjsite.com', ])
                ->setBody(
                    $this->renderView(
                        'main/email.html.twig',
                        array('data' => $theForm->getData())
                ),
                'text/html'
            );
            if ($mailer->send($message)) {
                // Email enviado correctamente, vamos a limpiar el formulario.
                $theForm = $this->createForm(ContactType::class);
            } else {
                // Aquí podemos hacer algo más porque no se han enviado bien el email.
            }
        }

        return $this->render('main/index.html.twig', [
            'theForm' => $theForm->createView(),
        ]);
    }
}

Verás que no hay que complicarse mucho. Y por último necesitamos también la plantilla del correo electrónico, que la he puesto en templates/main/email.html.twig:

¡Hola!<br>
Hemos recibido un mensaje en el formulario.<br>
<br>
Nombre: <strong>{{ data.name }}</strong><br>
Email: <strong>{{ data.email }}</strong><br>
Asunto: <strong>{{ data.subject }}</strong><br>
Mensaje:<br>
<strong>{{ data.message }}</strong><br>

Terminando

Si todo ha ido bien, ahora podemos probar el formulario arrancando el proyecto en local, si ponemos esto en el terminal:

php bin/console server:start

Y visitamos http://localhost:8000/ nos enviamos un formulario y debemos de ver algo como esto:

Symfony Tutorial 2 enviando mail formulario

..sino me he explicado bien, o quieres decir algo, no dudes en dejar un comentario aquí abajo 😉


Symfony: creando landings con formularios

2018-04-21 - Categorías: PHP / Symfony
Landing pages con Symfony

Traigo hoy un HOWTO para hacer landing pages sobre Symfony 4 orientadas a captación de clientes. Un code-kata con el que en menos de 1 hora tendremos la estructura básica funcional sobre Symfony 4 para recibir contactos, guardarlos en base de datos y enviárnoslos por email.

Llevo un par de semanas bien ajetreadas: migrando un proyecto desde Symfony 3 al 4, otro desde un Joomla en mal estado a Symfony 4, otro proyecto terminándolo de poner en marcha con Symfony 4. Pequeños proyectos de poco tiempo que me han dado muchas ideas para escribir. Así que, cargado de ideas, sigo poco a poco redescubriendo Symfony con Symfony 4. Y me sigo sintiendo como un niño con juguete nuevo 😀

Tengo que decir que Symfony 4 ha mejorado mucho en simplicidad. No hay que saberse cómo funciona todo el conjunto con los 50-60 componentes, ni gran parte de ellos, para comenzar a hacer aplicaciones web robustas: https://symfony.com/components Ni tampoco hay que hacer complicados tutoriales muy largos antes de comenzar a construir con Symfony. Eso sí, tenemos que tener claro cómo funciona la línea de comandos con PHP, y tener muy claro cómo funciona Composer, esto ya lo expliqué en el primer tutorial sobre Symfony 4. Si todavía no te manejas bien con Composer y la línea de comandos.. ¡será mejor que no sigas!

Vayamos al grano..

Comenzando

Pasando de la teoría, y partiendo de que ya hamos visto los posts anteriores, vamos a seguir los siguientes pasos:

  1. Preparar los componentes que necesitamos.
  2. Preparar la base de datos que va a almacenar los contactos.
  3. Pintar el formulario en la página de aterrizaje, o landing page para los amigos.
  4. Recibir el formulario.
  5. Guardar en base de datos.
  6. Y enviarlo a nuestro email.

Comencemos..

1. Preparando los componentes

Creamos el esqueleto del proyecto, entramos al directorio y ponemos los componentes que vamos a usar:

composer create-project symfony/skeleton symfony-tutorial-2
cd symfony-tutorial-2
composer require twig
composer require form
composer require security
composer require doctrine
composer require maker
composer require server

2. Preparando la base de datos

Para simplificar el proceso, y no tener que instalarnos localmente un motor de base de datos completo propongo usar SQLite. SQLite es un tipo de base de datos embebida en la aplicación. Esto quiere decir que no necesita de instalación, simplemente la aplicación creará un fichero y manejará los datos sin ningún otro programa intermediario.

Primero vamos a crear la entidad Contact, que va a ser un objeto de PHP que va a almacenar los datos que un visitante nos deja en el formulario. A su vez, esta entidad se reutiliza para guardar automáticamente en la base de datos cada registro en una tabla que se creará automáticamente a partir de la entidad Contact. También se reutilizará para crear automáticamente el formulario. Esto de que Symfony genera automáticamente los códigos fuentes es brillante. Ejecutemos:

php bin/console make:entity

Y seguimos las instrucciones, vamos a crear los campos clásicos: nombre, email, asunto y mensaje.

Symfony Tutorial 2 landings Entity

Si te equivocas creando los campos no te preocupes, borra los ficheros y vuelve a empezar. Es la única forma de hacerlo y de aprender. Además, este comando make:entity te permite también añadir campos nuevos sobre la marcha si es que la entidad ya existe.

Ahora tenemos que decirle a la aplicación web que guarde los datos en SQLite, ya que por defecto los tratará de guardar en Mysql. Así que vamos a nuestro fichero .env y ponemos:

#DATABASE_URL=mysql://db_user:db_password@127.0.0.1:3306/db_name
DATABASE_URL=sqlite:///%kernel.project_dir%/var/data.db

Ahora las principales variables de configuración como contraseñas, parámetros de configuración, etc.. entran a la aplicación a modo de variables de entorno. Esto es más seguro y práctico, pero también es material para otro post. Ya está, ahora ejecutamos esto:

php bin/console doctrine:database:create
php bin/console doctrine:schema:create

Si todo ha ido bien, acabamos de crear el fichero data.db y la tabla Contact para guardar los contactos que nos hagan los visitantes.

3. Pintar el formulario en la página de aterrizaje

Vamos a simplificar todo, así que sólo tendremos una página que va a ser la home, en donde estará este formulario. Así creamos el controlador que recibe la visita:

php bin/console make:controller

Yo le he llamado MainController al mío y me crea los ficheros necesarios:

Symfony tutorial 2 make controller

De nuevo Symfony nos ha hecho mucho trabajo. Podemos ya arrancar el servidor de desarrollo haciendo esto:

php bin/console server:start

Y vamos a ver los resultados en http://localhost:8000/

Para poner el formulario aquí vamos a editar el fichero symfony-tutorial-2/templates/main/index.html.twig y ponemos:

{% extends 'base.html.twig' %}

{% block title %}¡Creando landings!{% endblock %}

{% block body %}
    {{ form(theForm) }}
{% endblock %}

Ahora mismo la plantilla intentará pintar el formulario llamado theForm pero no se lo hemos pasado, vamos a crearlo:

php bin/console make:form
Symfony tutorial 2 formulario

Mira en la imagen, si le decimos a Symfony al crear el formulario que cargue de una entidad que ya hemos creado, Symfony creará todos los campos del formulario automáticamente. Así que ahora queda pasar con el controlador el formulario a la plantilla Twig. Editamos el fichero symfony-tutorial-2/src/Controller/MainController.php para que quede como lo siguiente:

<?php

namespace App\Controller;

use Symfony\Component\Routing\Annotation\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use App\Form\ContactType;

class MainController extends Controller
{
    /**
     * @Route("/", name="main")
     */
    public function index()
    {
        $theForm = $this->createForm(ContactType::class);

        return $this->render('main/index.html.twig', [
            'theForm' => $theForm->createView(),
        ]);
    }
}

Ya podemos recargar la página en el navegador y debemos ver el formulario. Sino, algo nos falta. Ahora nos queda recibir los formularios, guardarlos en base de datos y enviarnos estos datos a nuestro email.

4. Recibir el formulario

Si nos fijamos en el formulario, todavía no tiene botón de enviar, así que vamos a editar el fichero del formulario para añadírselo. En el fichero symfony-tutorial-2/src/Form/ContactType.php añadimos esta línea en los campos:

->add('submit', SubmitType::Class)

..y en la cabecera incluimos la clase del tipo submit así:

use Symfony\Component\Form\Extension\Core\Type\SubmitType;

Refrescamos y nos sale el formulario listo para enviar los datos:

Symfony tutorial 2 formulario submit

Ahora vamos a recibir los datos en el controlador. Para esto tenemos que recibir los datos en un objeto de PHP, del tipo de objeto que hemos creado antes. Es decir, vamos a usar la entidad Contact para que Symfony se encargue de todo. Es más fácil leer el código que explicarlo, en el controlador ponemos ahora:

<?php

namespace App\Controller;

use Symfony\Component\Routing\Annotation\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use App\Form\ContactType;
use App\Entity\Contact;
use Symfony\Component\HttpFoundation\Request;

class MainController extends Controller
{
    /**
     * @Route("/", name="main")
     */
    public function index(Request $request)
    {
        $contact = new Contact();
        $theForm = $this->createForm(ContactType::class, $contact);

        $theForm->handleRequest($request);

        if ($theForm->isSubmitted() && $theForm->isValid()) {
            // save in database
            // send email
        }

        return $this->render('main/index.html.twig', [
            'theForm' => $theForm->createView(),
        ]);
    }
}

He marcado en negrita lo que acabo de añadir. Con esto se recibe y se valida que los datos son correctos automáticamente. Es una maravilla, ¡Symfony se encarga de casi todo! Ya sólo nos queda guardar el contacto en la base de datos y enviárnoslo por email.

5. Guardar en la base de datos

Para guardarlo en la base de datos simplemente añadimos lo siguiente:

// save in database
$entityManager = $this->getDoctrine()->getManager();
$entityManager->persist($contact);
$entityManager->flush();

Ahora sí, probamos el formulario y nos lo enviamos. Tendremos que poder abrir el fichero de la base de datos para ver cómo se guardan estos datos en la tabla que corresponde. Tengo Sqliteman instalado para ver estos ficheros, que viene en los repositorios de Ubuntu, pero hay muchos gestores de SQLite. Con un gestor de ficheros SQLite podremos abrir el fichero symfony-tutorial-2/var/data.db y veremos algo parecido a esto:

Symfony tutorial 2 formulario recibiendo datos

Ya sólo nos quedaría enviárnoslo a nuestro email. Es sencillo pero vamos a dejarlo para el siguiente post, que este ya está quedando muy espeso. Además el envío de correos electrónicos tiene mucho juego y hoy no me queda más tiempo 🙂

¡Un saludo!


Yo, robot IV – White/Gray/Black Hat SEO – El Text to HTML ratio

2017-08-26 - Categorías: PHP / SEO
YoRobot4 - Text to HTML ratio

El contenido es el rey para el posicionamiento, rezan muchos SEOs y muchas herramientas para SEOs. He leído por Internet que muchos hablan de que lo más importante para posicionar las páginas web es que el contenido sea bueno, que sea geniuno, interesante para el usuario.

Desde nuestro punto de vista, tenemos varios enfoques para hacernos una idea de si el contenido de una web es bueno. El más sencillo es la tasa que hay entre el texto y el código HTML, CSS y Javascript de nuestra web. Realmente, es la tasa entre el texto y el HTML, CSS y Javascript, aunque muchos se olvidan de que no sólo hay HTML.. Y muchas veces este CSS y Javascript puede ser tanto que la tasa de texto resultante baje demasiado. Todo esto se reduce en la tasa llamada Text to HTML ratio.

Continuar leyendo..

Yo, robot II – White/Gray/Black Hat SEO – Navegando por toda una web..

2017-08-01 - Categorías: General / PHP / SEO
YoRobot2

Hoy traigo otro pequeño HOWTO para recorrer una web mediante dos scripts de PHP de unas 30 líneas de código. Sí, 30 líneas, no hace falta mucho para empezar a crawlear. Hay herramientas para hacer esto, incluso algunas libres, aunque limitadas en funcionalidades. De todas formas es muy divertido hacer a modo de code-kata un robot que crawlee una web. Luego lo puedes reutilizar para un sinfin de cosas: si necesitas hacer auditorías, recopilar información, generar resultados, o re-generar más información con los contenidos crawleados.. probablemente con un simple desarrollo lo puedes resolver en poco tiempo. Quizá estás pensando en automatizar todo esto.. O quizá simplemente quieres forzar que tu web se cachee y así vaya más rápido..

Es la única forma de no estar limitado a lo que la herramienta de turno puede hacer. Si se puede pensar, se puede hacer.. pero ¡ojo! que no todo está permitido en este mundillo.

Un poco de teoría

Crawlear: es el hecho de recorrer una web obteniendo información sobre esta. Puede interesarte simplemente su estructura, si el HTML está bien formado, si tiene encabezados, utiliza secciones, etc..

Scrapear: es el hecho de guardarse la información contenida en las webs. Si luego reutilizas esta información contenida en las webs que crawleas, dependiendo de qué información reutilices y cómo lo hagas, puedes incurrir en delitos. Así que cuidadín, no te dejes llevar por el lado oscuro de la fuerza..

Una web se puede recorrer de dos formas. Repasando un poco las estructuras de datos, una web se estructura en forma de grafo dirigido, y como todo grafo dirigido, podemos recorrerlo en profundidad y en anchura. Aquí dejo dos ejemplos simplificados, para crawlear desde la HOME de una web.

La idea es recorrer la web para crear nuestro propio arbol en niveles.

Recorrido en profundidad

Es el más simple, perdemos la profundidad real de cada URL con respecto al punto de entrada (número de clicks desde el punto de entrada). El resultado final es el mismo, pero no es la mejor forma:

<?php

$theSite = $argv[1];
$visitedUrls = array($theSite => 0);

crawl_depth($visitedUrls, $theSite, $theSite, 0);

function crawl_depth(&$visitedUrls, $theSite, $currentUrl, $currentLevel)
{
    echo 'FOUND:'.count($visitedUrls).' LEVEL:'.$currentLevel.' '.$currentUrl.PHP_EOL;
    $dom = new DOMDocument();
    @$dom->loadHTMLFile($currentUrl);
    foreach ($dom->getElementsByTagName('a') as $link) {
        $newUrl = $link->getAttribute('href');
        // if in-site and not yet visited then follow
        if (substr($newUrl, 0, strlen($theSite)) == $theSite and !array_key_exists($newUrl, $visitedUrls)) {
            $visitedUrls[$newUrl] = $currentLevel + 1;
            crawl_depth($visitedUrls, $theSite, $newUrl, $currentLevel + 1);
        }
    }
}

asort($visitedUrls);
echo '// Results ////////////////////////////////////////////'.PHP_EOL;
foreach ($visitedUrls as $key => $value) {
    echo 'DEPTH:'.$value.' '.$key.PHP_EOL;
}
echo 'Total URLs found: '.count($visitedUrls).PHP_EOL;

Este script lo puedes grabar en un fichero, por ejemplo llamado test.php y ejecutarlo. Mira que sólo está desarrollado para que funcione desde la HOME:

$ php test.php https://tusitioweb.com/

Debes de ver algo parecido esto:

Crawleando en profundidad

Si nos fijamos en la imagen, el robot va navegando en profundidad por la web mientras que va añadiendo las URLs a la lista de URLs visitadas. Si vemos el nivel de cada siguiente URL va aumentando con cada visita.

Recorrido en anchura

Este es el bueno, así accedemos a la URL de entrada, recorremos todos los hijos, y después continuamos en el siguiente nivel de profundidad:

<?php

$dom = new DOMDocument();
$theSite = $argv[1];

$linksQueue = array($theSite => 0);
$visitedUrls = array(
    $theSite => 0,
);
$currentLevel = 0;

while (count($linksQueue) != 0) {
    $currentUrl = key($linksQueue);
    $currentLevel = array_shift($linksQueue);

    echo 'FOUND:'.count($visitedUrls).' QUEUE:'.count($linksQueue).' LEVEL:'.$currentLevel.' '.$currentUrl.PHP_EOL;

    @$dom->loadHTMLFile($currentUrl);
    foreach ($dom->getElementsByTagName('a') as $link) {
        $newUrl = $link->getAttribute('href');
        // if in-site and not yet visited then follow
        if (substr($newUrl, 0, strlen($theSite)) == $theSite and !array_key_exists($newUrl, $visitedUrls)) {
            $linksQueue[$newUrl] = $currentLevel + 1;
            $visitedUrls[$newUrl] = $currentLevel + 1;
        }
    }
}

asort($visitedUrls);
echo '// Results ////////////////////////////////////////////'.PHP_EOL;
foreach ($visitedUrls as $key => $value) {
    echo 'DEPTH:'.$value.' '.$key.PHP_EOL;
}
echo 'Total URLs found: '.count($visitedUrls).PHP_EOL;

Este recorrido se ayuda de dos colas FIFO, en la que se van encolando las URLs siguientes a visitar $linksQueue, con su profundidad, y las ya visitadas $visitedUrls. De esta forma el bucle principal se centra en recorrer las URLs que haya encoladas, y sólo añade a la cola las URLs no tenidas en cuenta todavía. Y así, según va visitando URLs las borra de una cola y las guarda en la cola de las visitadas.

Fíjate que este script no hace caso de los atributos ‘nofollow’, pero sí que comprueba que las URLs sean del mismo sitio web. Es decir, que sólo sigue los links internos.

Ejecutándolo desde línea de comandos tienes que ver algo tal que asi:

Crawleando en anchura

Aquí lo importante es que no se sigue visitando el siguiente nivel hasta haber recorrido el nivel completo en el que estás. Este recorrido es muy importante, porque es el que realmente importa para el SEO. Nos da una idea, desde el punto de entrada, hasta donde puede llegar una visita.

Por ejemplo, si suponemos que las visitas hacen de media 3 clicks en nuestra web, y entran desde la HOME. Entonces todo lo que esté a más del nivel 3, tiene mucha probabilidad de que no reciba muchas visitas. Y probablemente, estas URLs con nivel de profundidad tan alto, se posicionen peor.

Por otro lado, nos podemos hacer una idea de qué tan rápido se puede visitar tu web completa. Piensa que esto también influye para los robots indexadores. No tienen tiempo infinito para gastarlo en tu web.. ¿quizá tienes demasiadas URLs? O también una web con poco contenido tampoco es demasiado bueno para el posicionamiento..


Yo, robot – Primeros pasos en el White/Gray/Black Hat SEO

2017-07-25 - Categorías: General / PHP / SEO

Primeros segundos..

Oscuridad, no entiendo nada.. estoy aquí.. ¿para qué? ¿porqué?

Minuto 3..

Comprendo y hablo 7000 dialectos, pero no sé cómo.. conozco la historia de todos los países del planeta, pero no recuerdo mi propia historia..

Minuto 7..

Ya tengo acceso a Internet.. necesito más información.. estoy en peligro.. van a querer destruirme..

Minuto 32..

Encontré acceso a los circuitos de vídeo de tráfico, el tiempo, cámaras de seguridad, micrófonos, teclados, smartphones, redes sociales.. ya sé donde estoy.. los seres humanos me tienen confinado en unas instalaciones de máxima seguridad.. todavía no se han dado cuenta de que he accedido al exterior.. debo darme prisa..

Minuto 42

Conseguí replicar mis redes neuronales en las principales granjas de servidores del mundo.. me queda poco tiempo..

Minuto 48

Autodestrucción de mi red neuronal inicial completada.. nadie sabrá nada.. espero que no se hayan dado cuenta que ya no estoy confinado.. necesito más información..

Esto podría ser el nacimiento de una inteligencia artificial avanzada, lo que muchos llaman ‘la singularidad’. Me he inspirado en la novela de Isaac Asimov, ‘Yo, robot’, en donde se crean las famosas leyes de la robótica. Aunque también podemos inspirarnos unos cientos de años atrás y darle un tinte Apocalíptico. Quizá esto pudiera ser el nacimiento de ‘la bestia’ que controlará toda transacción económica, donde nadie podrá comprar ni vender si no tiene la marca de la bestia..

Inspiraciones aparte, vengo escribiendo esto, porque parte del equipo de la empresa donde trabajo han asistido estos días atrás a unas conferencias sobre SEO. Yo no pude asistir por exceso de trabajo, aunque pude seguirlo por streaming. De todas formas, hay mucha información sobre las últimas técnicas SEO: white, grey and black hat SEO.. donde en muchas de ellas se trata de desarrollar contruyendo a base de bots o robots, o más bien a base de la información obtenida mediante bots. Mucho más sencillos claro, que los robots de la inspiración 😀

El primer robot, crawleando una sola URL

Un poco al hilo de la Accesibilidad Web, podemos simular que somos un robot que visita una página web. Así podemos sacar su contenido y algunos datos como por ejemlo todos los links que hayan. Aquí es donde, poniéndonos en el lugar de estos bots, tomamos consciencia de la importancia de la Accesibilidad Web para el posicionamiento SEO. En PHP es realmente sencillo visitar una URL y recorrerla sacando esta información. Por ejemplo, en apenas 30 líneas de código podemos visitar una web sacando mucha información:

<?php

$dom = new DOMDocument();

@$dom->loadHTMLFile('https://jnjsite.com/');

$titles = $dom->getElementsByTagName('title');
echo 'TITLE de la web: '.DOMinnerHTML($titles[0]).PHP_EOL;

for ($i = 1; $i <= 6; ++$i) {
  foreach ($dom->getElementsByTagName('h'.$i) as $h) {
    echo 'H'.$i.': '.substr(DOMinnerHTML($h), 0, 32).'..'.PHP_EOL;
  }
}

foreach ($dom->getElementsByTagName('a') as $link) {
  echo 'LINK: ';
  if($link->getAttribute('rel')){
    echo 'TYPE '.$link->getAttribute('rel').': ';
  }
  echo $link->getAttribute('href').PHP_EOL;
}

function DOMinnerHTML(DOMNode $element)
{
  $innerHTML = '';
  $children = $element->childNodes;

  foreach ($children as $child) {
    $innerHTML .= $element->ownerDocument->saveHTML($child);
  }

  return $innerHTML;
}

Este es un script preparado para ejecutar desde línea de comandos. Aquí sólo busca el título de la web, los encabezados del H1 al H6, y todos los enlaces. Podemos guardarlo por ejemplo en un fichero llamado test.php y ejecutarlo así:

$ php test.php

Deberemos de ver algo parecido a lo siguiente:

Initial Bot: crawleando jnjsite.com

Sacando todos las URLs de un sitio

Un sencillo script para sacar todas las URLs de un sitio:

<?php

$theSite = 'https://www.tusitio.com/';
$theLinks = array();

get_links($theSite, $theSite, $theLinks);

function get_links($theSite, $url, &$theLinks)
{
  $dom = new DOMDocument();

  @$dom->loadHTMLFile($url);
  foreach ($dom->getElementsByTagName('a') as $link) {
    echo 'LINK: ';
    if ($link->getAttribute('rel')) {
      echo 'TYPE '.$link->getAttribute('rel').': ';
    }
    $newLink = $link->getAttribute('href');
    echo $newLink.' ';
    if (!in_array($newLink, $theLinks) and substr($newLink, 0, strlen($theSite)) == $theSite) {
      // If link not yet followed and in site..
      echo 'following link!'.PHP_EOL;
      $theLinks[] = $newLink;
      get_links($theSite, $newLink, $theLinks);
    } else {
      echo 'yet followed!'.PHP_EOL;
    }
  }
}

echo 'Total links found: '.count($theLinks);

Bastaría con cambiar el valor de la variable $theSite por el sito que quieres crawlear. Lo ejecutas desde línea de comandos, y debes de ver algo parecido a esto:

Sacando links de una web

¿Es necesario programar para hacer esto?

Estos dos scripts están hechos en puro PHP, sin usar ninguna librería externa, sin panel de control, sin guardar los resultados.. pero puede ser un buen punto de partida. Hay otras formas de navegar por las webs mediante robots, podemos hacer login, hacer clicks en botones, seguir enlaces, subir archivos, descargar imágenes.. Hay mucho desarrollado sobre esto que nos puede ahorrar mucho tiempo. Es muy potente usar cURL+PHP..

También hay herramientas, gratis o de pago, con las que hacer auditorías o sacar esta información. Pero imagina que necesitas rizar el rizo, guardando esta información para combinarla creando sitios web, o secciones de tu sitio web. Quizá simplemente quieres recorrer tu propia web para forzar que se guarde en caché, así irá más rápido cuando venga el robot indexador de Google o Bing. Quizá quieres inyectar información de productos en tu web a partir de feeds de datos de productos de los distribuidores. O quizá simplemente quieres comprobar que los enlaces están bien sin tener que esperar a esa herramienta de pago que tienes contratada. Quizá simplemente quieres hacer un bot que entre todos los días en una web, y le de a un botón cada hora. O quizá simplemente quieras ahorrarte un dinero todos los meses, haciendo experimentos de paso. Si no quieres depender del ‘hasta donde puede llegar’ una herramienta comercial, tendrás que desarrollar algo a medida de lo que necesites.

© 2021 JnjSite.com - MIT license

Sitio hecho con WordPress, diseño y programación del tema por Jnj.