Frage

Ich schreibe ein PHP-Skript, das das Scrapen von Webseiten beinhaltet.Derzeit analysiert das Skript die Seite Zeile für Zeile, bricht jedoch ab, wenn ein Tag vorhanden ist, das sich über mehrere Zeilen erstreckt, z. B

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

Im schlimmsten Fall könnte ich die Seite möglicherweise vorverarbeiten, indem ich alle Zeilenumbrüche entferne und sie dann am nächsten Punkt wieder einfüge >, aber das scheint eine Flickschusterei zu sein.

Im Idealfall wäre ich in der Lage, ein zeilenübergreifendes Tag zu erkennen, nur diese zu Zeilen zu verbinden und mit der Verarbeitung fortzufahren.
Was ist also die beste Methode, um dies zu erkennen?

War es hilfreich?

Lösung 4

Vielleicht werde ich für zukünftige Projekte eine Parsing-Bibliothek verwenden, aber das ist etwas außerhalb der vorliegenden Frage.Das ist meine aktuelle Lösung. rstrpos ist strpos, aber aus der umgekehrten Richtung.Beispielanwendung:

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

Und hier ist diese Implementierung:

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);
    }
}

Dies könnte wahrscheinlich in irgendeiner Weise optimiert werden, aber für meine Zwecke ist es ausreichend.

Andere Tipps

Das ist einer meiner liebsten Ärgernisse: niemals HTML manuell analysieren. Niemals HTML mit regulären Ausdrücken analysieren. Niemals Analysieren Sie HTML mit Zeichenfolgenvergleichen. Stets Verwenden Sie einen HTML-Parser, um HTML zu analysieren – dafür sind sie da.

Es ist lange her, dass ich das letzte Mal PHP verwendet habe, aber eine schnelle Suche ergab dieser PHP5-HTML-Parser.

Schreiben Sie keinen Parser, sondern verwenden Sie den von jemand anderem: DOMDocument::loadHTML - Das ist nur einer, ich denke, es gibt noch viele andere.

Nun, das beantwortet die Frage nicht und ist eher eine Meinung, aber...

Ich denke, dass die beste Scraping-Strategie (und folglich die Beseitigung dieses Problems) nicht darin besteht, einen HTML-Code Zeile für Zeile zu analysieren, was für HTML unnatürlich ist, sondern ihn anhand seines natürlichen Trennzeichens zu analysieren:<> Paare.

Es wird natürlich zwei Arten von Kursen geben:

  • Markieren Sie Elemente, die sofort geschlossen werden, z. B. < br />
  • Markieren Sie Elemente, die ein separates schließendes Tag benötigen, z. B. < p > Text < /p >

Bei Absatz(p)-Tags erkennt man sofort den Vorteil dieser Strategie:Es wird einfacher sein, verstümmelte Absätze zu analysieren, anstatt nachverfolgen zu müssen, wo sich das schließende Tag befindet.

Warum lesen Sie nicht eine Zeile ein, setzen sie auf eine Zeichenfolge und überprüfen dann die Zeichenfolge auf Tag-Öffnungen und -Abschlüsse. Wenn sich ein Tag über mehr als eine Zeile erstreckt, fügen Sie die nächste Zeile zur Zeichenfolge hinzu und verschieben Sie den Teil vor die öffnende Klammer zu Ihrer verarbeiteten Zeichenfolge.Dann analysieren Sie einfach die gesamte Datei, indem Sie dies tun.Es ist nicht schön, aber es sollte funktionieren.

Wenn Sie bei Ihrer aktuellen Parsing-Methode bleiben müssen und es sich um einen regulären Ausdruck handelt, können Sie die verwenden mehrzeilige Flagge „m“, um sich über mehrere Zeilen zu erstrecken.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top