Cómo parsear HTML con preg_match y preg_match_all

Para la mayoría de los desarrolladores web que utilizan habitualmente la función preg_match, la función preg_match_all es una pequeña ventaja, pero para los demás posiblemente sea difícil de entender. La gran diferencia entre preg_match y el preg_match de toda la vida es que todos los valores encontrados son almacenados en un array multidimensional, por lo que puede almacenar un número ilimitado de coincidencias. En la primera parte de este tutorial explicaremos cómo obtener todas las rutas que hacen referencia a imágenes en un documento html. Para las demás partes de un documento HTML la función preg_match es más útil. Para explicarlo, en este artículo hay dos ejemplos más: un testeador de links externos y otro que extrae el título y la meta desctipción de una página web.

Tutorial sobre preg_match

$data = file_get_contents("http://www.programacion.net");
$pattern = "/src=["']?([^"']?.*(png|jpg|gif))["']?/i";
preg_match_all($pattern, $data, $images);

Vamos a echar un vistazo al patrón de la expresión regular:

"/src=["']?([^"']?.*(png|jpg|gif))["']?/i"

La primera parte y la última buscan todo lo que comienza con src y termina en comillas simples o comillas dobles. Da cabida a que sea una cadena larga, puesto que la regla exterior es muy global.

"/src=["']?([^"']?.*(png|jpg|gif))["']?/i"

También chequeo aquellas cadenas largas que comienzan con una comilla simple opcional o comillas dobles seguido de cualquier carácter. La última parte dentro de las llaves es donde se produce la magia.

"/src=["']?([^"']?.*(png|jpg|gif))["']?/i"

Después compruebo si la cadena cuenta con una extensión y si coincide con la expuestas en la expresión regular, devolvemos todas las rutas al array.

Necesito todas las reglas para aislar las partes de la cadena (rutas de imágenes) del resto del HTML. El resultado es el siguiente (accede al array $images con estos índices, o simplemente utiliza print_r ($images)):

$images[0][0] -> src="/images/english.gif"
$images[1][0] -> /images/english.gif
$images[2][0] -> gif

El index[1] es la información que necesito. Prueba esta función preg_match_all en otros documentos HTML y con otras partes a extraer para una mejor comprensión de todo esto.

Testeador de links externos con preg_match

Esta función es muy útil para gente con un portal de enlaces cuyos links son almacenados en una base de datos (MySQL). El script PHP de abajo se utiliza para comprobar si existe un enlace recíproco en una página externa que nosotros designemos. El script se encarga de buscar el patrón, que en este caso es nuestra url, en el documento HTML. En el caso de ser cierto, la función devuelve un true y, si no pasa el patrón de la expresión regular, devuelve un false.

function check_back_link($remote_url, $your_link) {
    $match_pattern = preg_quote(rtrim($your_link, "/"), "/");
    $found = false;
    if ($handle = @fopen($remote_url, "r")) {
        while (!feof($handle)) {
            $part = fread($handle, 1024);
            if (preg_match("/<a(.*)href=["']".$match_pattern.
"(/?)["'](.*)>(.*)</a>/", $part)) {
                $found = true;
                break;
            }
        } 
        fclose($handle);
    }
    return $found;
}
// ejemplo:
//if (check_back_link("http://www.programacion.net", "http://www.ejemplo.com")) echo "link exists";

Extraer el título y la meta descripción de una página web

Con este script es posible obtener la primera parte de un archivo remoto para analizar los elementos HTML en local. El elemento título y la meta descripción se parsean mediante el uso de la función preg_match(). Puedes parsear otros elementos del head si así lo prefieres, insertando ciertas reglas adicionales y patrones de expresiones regulares. El script lee sólo la primera parte (el header) de un archivo remoto para un mejor rendimiento.

<?php
$page_title = "n/a";
$meta_descr = "n/a";
	
if ($handle = fopen("http://www.programacion.net", "r")) {
	$content = '';
	while (!feof($handle)) {
		$part = fread($handle, 1024);
		$content .= $part;
		if (preg_match('/</head>/', $part)) break;
	}
	fclose($handle);
	$lines = preg_split('/r?n|r/', $content);
	$result = true;
	$is_title = false;
	$is_descr = false;
	foreach ($lines as $val) {
		if (preg_match('/<title>(.*)</title>/', $val, $title)) {
			$page_title = $title[1];
			$is_title = true;
		} 
		if (preg_match('/<meta name="description" content="(.*)"s?/?>/', $val, $descr)) {
			$meta_descr = $descr[1];
			$is_descr = true;
		}
		if ($is_title && $is_descr) break;
	}
}

Fuente: web-development-blog.com

COMPARTE ESTE ARTÍCULO

COMPARTIR EN FACEBOOK
COMPARTIR EN TWITTER
COMPARTIR EN LINKEDIN
COMPARTIR EN WHATSAPP