Pregunta

Estoy escribiendo un script PHP que implica raspar páginas web.Actualmente, el script analiza la página línea por línea, pero se rompe si hay una etiqueta que abarca varias líneas, como

<img src="example.jpg"
alt="example">

En el peor de los casos, podría preprocesar la página eliminando todos los saltos de línea y luego volviéndolos a insertar en la página más cercana. >, pero esto parece una pifia.

Idealmente, podría detectar una etiqueta que abarque líneas, unirlas solo a las líneas y continuar procesando.
Entonces, ¿cuál es el mejor método para detectar esto?

¿Fue útil?

Solución 4

Quizás para proyectos futuros use una biblioteca de análisis, pero eso es algo aparte de la pregunta que nos ocupa.Esta es mi solución actual. rstrpos es strpos, pero desde la dirección inversa.Uso de ejemplo:

for($i=0; $i<count($lines); $i++)
{
    $line = handle_mulitline_tags(&$i, $line, $lines);
}

Y aquí está esa implementación:

function rstrpos($string, $charToFind, $relativePos)
{
    $searchPos = $relativePos;
    $searchChar = '';

    while (($searchChar != $charToFind)&&($searchPos>-1))
    {
        $newPos = $searchPos-1;
        $searchChar = substr($string,$newPos,strlen($charToFind));
        $searchPos = $newPos;
    }

    if (!empty($searchChar))
    {
        return $searchPos;
        return TRUE;
    }
    else
    {
        return FALSE;
    }
}

function handle_multiline_tags(&$i, $line, $lines)
{
    //if a tag is opened but not closed before a line break,

    $open = rstrpos($line, '<', strlen($line));
    $close = rstrpos($line, '>', strlen($line));
    if(($open > $close)&&($open > -1)&&($close > -1))
    {
        $i++;
        return trim($line).trim(handle_multiline_tags(&$i, $lines[$i], $lines));
    }
    else
    {
        return trim($line);
    }
}

Probablemente esto podría optimizarse de alguna manera, pero para mis propósitos, es suficiente.

Otros consejos

Esta es una de mis cosas que me molestan: nunca analizar HTML a mano. Nunca analizar HTML con expresiones regulares. Nunca analizar HTML con comparaciones de cadenas. Siempre utilice un analizador HTML para analizar HTML; para eso están.

Ha pasado mucho tiempo desde que hice PHP, pero apareció una búsqueda rápida este analizador HTML PHP5.

No escriba un analizador, use el de otra persona: Documento DOM::loadHTML - ese es sólo uno, creo que hay muchos otros.

Bueno, esto no responde la pregunta y es más una opinión, pero...

Creo que la mejor estrategia de scraping (y en consecuencia, eliminar este problema) no es analizar un HTML línea por línea, lo cual no es natural para HTML, sino analizarlo por su delimitador natural:<> pares.

Habrá dos tipos de curso:

  • Etiquetar elementos que se cierran inmediatamente, por ejemplo, < br />
  • Etiquetar elementos que necesitan una etiqueta de cierre separada, por ejemplo, < p > texto < /p >

Puede ver inmediatamente la ventaja de utilizar esta estrategia en el caso de las etiquetas de párrafo(p):Será más fácil analizar párrafos de varias líneas en lugar de tener que rastrear dónde está la etiqueta de cierre.

¿Por qué no lee en una línea y la configura como una cadena, luego verifica la cadena para ver si hay aperturas y cierres de etiquetas? Si una etiqueta abarca más de una línea, agregue la siguiente línea a la cadena y mueva la parte antes de la llave de apertura. a su cadena procesada.Luego simplemente analice todo el archivo haciendo esto.No es hermoso pero debería funcionar.

Si debe ceñirse a su método actual de análisis y es una expresión regular, puede usar el bandera multilínea "m" para abarcar varias líneas.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top