Hitzering: preg_match_all was tun wenn die Daten nicht regelkonform sind?

Hallo,

unsere "interne Suchfunktion" funktioniert so lala. Daher dachte ich mir eine einfache Synonymliste dürfte bessere Ergebnisse bringen.

Die typischen Listen sind wirklich schon super. Jetzt dachte ich mir "wikipedia" bzw. "wiktionary" wird hier noch bessere Daten haben. Und das ist auch so. Leider sind die Daten doch recht ungewöhnlich aufbereitet und enthalten auch mal gerne "individuelle" Absätze / Markierungen die ich gerne Filtere.

Es hat sich herrausgestellt, dass die Synonyme in 99% der Fälle in einer Art <dl> HTML Strukturierung zu finden sind.

Daher bereite ich mir die Datensätzte verschieden vor unter anderem mit preg_match_all('|<dl>(.*)</dl>|Uism',$quelle, $items_synonyme_2, PREG_PATTERN_ORDER); vor. Leider kann man hier: https://de.wiktionary.org/wiki/Familie sehen das es kein zweites öffnendes <dl> gibt. Somit also auch nur 1 Datensatz statt 2 ausgegeben werden siehe:

Quelletext Wiktionary

<p>
  <span style="visibility:hidden" id="Synonyme">
    <span id="Anker:Synonyme"></span>
  </span>
</p>
<div style="margin-bottom:-0.5em; font-weight:bold;" title="bedeutungsgleich gebrauchte Wörter">Synonyme:</div>
<dl>
  <dd>[1] <a href="/w/index.php?title=Blutsverwandte&amp;action=edit&amp;redlink=1" class="new" title="Blutsverwandte (Seite nicht vorhanden)">Blutsverwandte</a>,
          <a href="/wiki/Sippe" title="Sippe">Sippe</a>
    <dl>
      <dd>[1a] <a href="/wiki/Kernfamilie" title="Kernfamilie">Kernfamilie</a></dd>
      <dd>[1b] <i>abwertend, salopp:</i> <a href="/wiki/Mischpoke" title="Mischpoke">Mischpoke</a></dd>
    </dl>
  </dd>
  <dd>[2] <a href="/wiki/Abart" title="Abart">Abart</a>,
          <a href="/wiki/Art" title="Art">Art</a>,
          <a href="/wiki/Bereich" title="Bereich">Bereich</a>,
          <a href="/wiki/Departement" title="Departement">Departement</a>,
          <a href="/wiki/Dialekt" title="Dialekt">Dialekt</a>,
          <a href="/wiki/Fach" title="Fach">Fach</a>,
          <a href="/wiki/Gattung" title="Gattung">Gattung</a>,
          <a href="/wiki/Genus" title="Genus">Genus</a>,
          <a href="/wiki/Geschlecht" title="Geschlecht">Geschlecht</a>,
          <a href="/wiki/Gruppe" title="Gruppe">Gruppe</a>,
          <a href="/wiki/Kategorie" title="Kategorie">Kategorie</a>,
          <a href="/wiki/Linie" title="Linie">Linie</a>,
          <a href="/wiki/Rasse" title="Rasse">Rasse</a>,
          <a href="/wiki/Reihe" title="Reihe">Reihe</a>, 
          <a href="/wiki/Rubrik" title="Rubrik">Rubrik</a>,
          <a href="/wiki/Schlag" title="Schlag">Schlag</a>
  </dd>
</dl>

Was kann ich tun um den zweiten Absatz mit zu nehmen? (die <dd> bzw. </dd> benötige ich später noch zum Filtern der individuellen Varianten).

Edit Rolf B: HTML lesbarer gemacht

  1. Hallo Hitzering,

    wenn man mal das ganze nicht-strukturelle Brimborium wegnimmt, sieht man, dass hier geschachtelte DLs vorliegen, und das bringt deine Regex durcheinander.

    <dl>
      <dd>[1] <a href="/w/index.php..." class="new">Blutsverwandte</a>,
              <a href="/wiki/Sippe" title="Sippe">Sippe</a>
        <dl>
          <dd>[1a] <a href="/wiki/Kernfamilie">Kernfamilie</a></dd>
          <dd>[1b] ... <a href="/wiki/Mischpoke">Mischpoke</a></dd>
        </dl>
      </dd>
      <dd>[2] <a href="/wiki/Abart">Abart</a>,
              <a href="/wiki/Rubrik">Rubrik</a>,
              <a href="/wiki/Schlag">Schlag</a>
      </dd>
    </dl>
    

    Eine Lösung in der Schublade habe ich nicht. Rekursive Regex gibt es, haben aber eine Form, die sich für meine Gehirnwindungen nicht zurechtbiegen lässt.

    An Deiner Stelle würde ich den DOM Parser über das HTML Fragment jagen und das entstehende DOM rekursiv durcharbeiten.

    Rolf

    --
    sumpsi - posui - clusi
    1. Danke Rolf, jetzt wo du da so schön aufgeschlüsselt hast stimmt es. Hast du eine Idee/Vorschlag wie ich damit umgehen kann?

      1. Hallo Hitzering,

        siehe mein Update des Beitrags. DOM Parser.

        Rolf

        --
        sumpsi - posui - clusi
        1. Danke Rolf,

          ich habe mit der Antwort von https://forum.selfhtml.org/self/2019/jul/18/pregmatchall-was-tun-wenn-die-daten-nicht-regelkonform-sind/1753512#m1753512 nicht gerechnet. Die ist genau das richtige für meinen Fall.

          Vielen vielen Dank

    2. Hello,

      An Deiner Stelle würde ich den DOM Parser über das HTML Fragment jagen und das entstehende DOM rekursiv durcharbeiten.

      Das würde ich auf jeden Fall auch tun!

      1. Schritt: Path-Darstellung von allen betroffenen Elementen erzeugen
      2. Schritt: Die Elemente der Pathliste ganz normal "grepen"

      Das hält das Ganze übersichtlich und man ist schnell fertig.

      Falls Fragen bestehen, helfe ich am Wochenende gerne vom Desktop. Da habe ich mir diverse Modellcodes gespeichert. Dann muss man nicht jedes Mal das Rad neu erfinden.

      Glück Auf
      Tom vom Berg

      --
      Es gibt nichts Gutes, außer man tut es!
      Das Leben selbst ist der Sinn.
  2. Regex ist nicht geeignet zum parsen von html. Am besten verwendest du einen HTML parser.

    Bei deinem Beispiel sind die <dl verschachtelt. Dafür bräuchtest du ein rekursives Suchmuster.

    Etwas in der Art:

    preg_match_all('~<dl>(?:[^<]+|<(?!/?dl\b)|(?R))*+</dl>~i',...
    

    Bei (?R) wird das gesamte Suchmuster wieder eingefügt. Siehe Demo auf Regex101

    1. Danke, das ist super. Ich habe mit der Antwort von https://forum.selfhtml.org/self/2019/jul/18/pregmatchall-was-tun-wenn-die-daten-nicht-regelkonform-sind/1753512#m1753512 nicht gerechnet. Die ist genau das richtige für meinen Fall.

  3. Tach!

    Die typischen Listen sind wirklich schon super. Jetzt dachte ich mir "wikipedia" bzw. "wiktionary" wird hier noch bessere Daten haben. Und das ist auch so.

    Bist du sicher, dass für deinen Zweck das Parsen der HTML-Ausgabe sinnvoll ist? MediaWiki hat eine API, über die man recht einfach an den Quelltext der Seiten rankommt, ohne Brimborium drumherum und ohne dass die Server dieses Brimborium erzeugen müssen.

    Abgesehen von der API kann auch bereits ein angehängtes ?action=raw helfen, die zu bearbeitenden Daten kleiner zu halten.

    dedlfix.

    1. WOW, nein das kannte ich noch nicht. Das vereinfach natürlich alles...

      1. Tach!

        WOW, nein das kannte ich noch nicht. Das vereinfach natürlich alles...

        Freu dich nicht zu früh. Du musst nun erstmal untersuchen, ob du damit wirklich besser zurecht kommst. Vielleicht ist es ja einfacher HTML mit seinen Start- und End-Tags zu parsen, als in der MediaWiki-Syntax die gleiche Datenstruktur zu finden. Deren Syntax kann manchmal auch schwer nachvollziehbar und/oder komplex geschachtelt sein. Viel Erfolg.

        dedlfix.