Nochmal XPath

Einklappen
X
 
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • Nochmal XPath

    Also mit der genauen Xpath-Abfrage komme ich mal wieder nicht klar. Im Quelltext der zu lesenden Seite sieht es so aus:

    HTML-Code:
          <div class="tituloNoticia mi12 t6" style="">         <h3 style="">             <a href="http://www.publico.es/455147/izquierda-politica-y-movimientos-sociales-un-futuro-en-comun" style="">Izquierda política <br>y movimientos sociales: ¿Un futuro en común?</a>         </h3>     </div>
    Ich brauche den link und den nodeValue und habe meine Abfrage so gestaltet, aber wahrscheinlich wieder irgendwas vergessen:

    PHP-Code:
    foreach ($xPath->query("//div[@class=\"tituloNoticia mi12 t6\"]/h3/a") as $element) {
         

         
    $href $element->getAttribute('href');
         
    $title $element->nodeValue
    Ich weiß z. B. nicht, wie man in einer xpath-Abfrage mit den Leerstellen umgeht, die in dem class-Namen stehen. Oder wie ich mit "style="" umgehe (oder Platzhalter setze)? Gibt es da eigentlich eine gute Übersicht à la "Wenn ich auf das und jenes zugreifen will, frage ich so....?"

    Gruß und Dank
    newbie1955

    P.S. habe jetzt zwischendurch mal viel rumprobiert, und das Merkwürdige: Manchmal wurden href und noveValue ausgegeben, manchmal nicht, und wenn ich die weiteren classes: "//div[@class=\"tituloNoticia mi12 t3\"]/h3/a" dazu abfragen will, kommen die gar nicht???? Die Seite ist
    http://www.publico.es/
    Zuletzt geändert von newbie1955; 11.05.2013, 19:01.

  • #2
    Habe ich noch nicht probiert, ein Gedanke wäre jedoch, gebe nur eine Klasse an. Es ist nicht eine Klasse, sondern es sind 3 Klassen, die durch eine Leerstelle getrennt notiert werden und möglicherweise sollte es genügen, nur die erste Klasse anzugeben. Genau weiß ich es aber nicht, wie man das am besten schreibt.

    Edit: Vergiss die Seite, die scheint beim Laden abzubrechen und nur einen leeren Body zu übertragen, auch wenn ein User Agent gesetzt wird. Lasse Dir mal hinter loadHTML mit saveHTML anzeigen, was da enthalten ist. Bei mir ein leerer Body.

    Ich habe die mal über meinen Testbot geholt, die scheint nur gzip komprimiert auszuliefern und das müsste erst entpackt werden. Was ich mit dem Bot abhole, sieht zumindest ähnlich wie Binärdaten aus.

    Code:
    HTTP/1.1 200 OK
    Server: nginx/1.2.5
    Date: Sat, 11 May 2013 19:15:58 GMT
    Content-Type: text/html; charset=UTF-8
    Content-Length: 32739
    Connection: close
    Cache-Control: max-age=60,must-revalidate
    Expires: Sat, 11 May 2013 19:16:49 GMT
    Vary: Accept-Encoding,User-Agent
    Content-Encoding: gzip
    Eventuell müsste der Seite mitgeteilt werden, dass man keine komprimierten Daten möchte. Wie und was schreibt man da? Da müsste ich erst einmal lange, lange suchen.

    PHP-Code:
    header("Content-Encoding: ...?"); 
    Oder Du wurstelst Dich hier durch: PHP: Zlib-Funktionen - Manual
    Zuletzt geändert von Melewo; 11.05.2013, 21:55.

    Kommentar


    • #3
      Oha

      klingt kompliziert, vor allem verstehe ich nicht, wieso mal erfolgreich etwas von der Seite geholt wurde und dann wieder nicht. Naja, werde mal mit Deinen Tipps etwas rumprobieren.

      Danke
      Gruß
      newbie1955

      Kommentar


      • #4
        Schaue Dir mal "Method 1 : Accept-Encoding" an, dass könnte eine Lösung sein, sieht nicht kompliziert aus, nur ich habe heute keine Lust mehr zum Experimentieren.

        PHP file_get_contents giving garbled output

        Passend dazu solltest Du Dir dann noch den Punkt "14.3 Accept-Encoding" durchlesen, ich habe es nur halb verstanden:

        HTTP/1.1: Header Field Definitions

        Kommentar


        • #5
          Jedenfalls, bevor Du mit XPath experimentierst, müsste ja zuerst einmal $data als Quelltext ausgegeben werden können. Doch mal kommt nichts, wenn es dann geht, wird nur bei den ersten zwei Aufrufen HTML normal ausgeliefert, beim dritten Aufruf ist es ein Wirrwarr von Steuerzeichen oder was auch immer das darstellen soll. In dem Zusammenhang halte ich es zumindest für komprimierte Daten.

          PHP-Code:
          <?php
          ini_set
          ("user_agent""Mozilla/5.0 (compatible; Test/PHP)");
          header("Content-Type: text/html; charset=UTF-8");
          ?>
          <!DOCTYPE html>
          <html>

          <head>
          <title>Nur eine Testseite</title>
          </head>

          <body>
          <h1>Mit Accept-Encoding</h1>

          <?php
          error_reporting
          (-1);
          ini_set("display_errors"true);

          $opts = array(
              
          "http" => array(
                  
          "method" => "GET",
                  
          "header" => "Accept-Encoding: gzip;q=0, compress;q=0\r\n"
              
          )
          );

          $context stream_context_create($opts);
          $data file_get_contents("http://www.publico.es"false$context);

          echo 
          htmlspecialchars($dataENT_QUOTES);

          ?>
          </body>
          </html>
          Der Code von der verlinkten Seite brachte es nicht bei den bisherigen Tests. In dem Zusammenhang, bislang hielt ich q bzw. den Wert von q für einen Qualitätsfaktor. Wenn ich nun unter der zweiten verlinkten Seite bei den Definitionen nachlese, so sollte ja ein q-Faktor von 0 für unakzeptabel stehen.

          14.3 Accept-Encoding
          ...
          1. ... a qvalue of 0 means "not acceptable."

          Würde ich jetzt so schreiben:

          1. ... ein q = value von 0 bedeutet "nicht akzeptabel."
          Womit der Server eigentlich die Daten nicht mehr komprimiert ausliefern sollte oder wie verstehst Du das?

          Das andere Beispiel auf der Seite (das längere) würde wohl funktionieren, wenn denn die Funktion gzdecode verfügbar sein sollte, ist sie bei mir aber nicht und bei php.net steht:

          (No version information available, might only be in SVN)
          Somit bliebe jetzt als möglicher Weg, den ganzen Code mal Schritt für Schritt durchzugehen und eventuell für eine andere Funktion anzupassen. Habe mal begonnen, mehr aber auch noch nicht.

          Oder Du speicherst die eben zwischen als temp und ladest die dann zum Entpacken, das wäre relativ einfach, ist jedoch unpraktisch bei häufigen Aktualisierungen und auch unpraktisch, wenn Du da 10 bis 20 verschiedene Quellen pro Seite laden möchtest.

          Edit: Hatte einen Denkfehler, weil ich mich von dem Listing auf der verlinkten Seite beeinflussen ließ und da etwas ungereimt dargestellt wird:

          PHP-Code:
          echo gzdecode(file_get_contents("http://www.example.com"));

          if(!
          function_exists("gzdecode")) {
          function 
          gzdecode($data) {

          ... 
          Das kann nicht funktionieren, weil bei echo die Funktion gzdecode noch unbekannt ist, da ja erst in den Zeilen darunter eine Prüfung erfolgt und falls gzdecode unbekannt ist, die Funktion erst definiert wird. Umgekehrt funktioniert es schon einmal mit der Ausgabe von HTML. Also, erst die Funktion, dann der Aufruf. Falls es denn funktioniert, zweimal blieb die Seite leer, doch die restlichen Aufrufe, die lieferten halt keinen komprimierten Datenmüll mehr.
          Zuletzt geändert von Melewo; 12.05.2013, 20:43.

          Kommentar


          • #6
            Fertig!

            Die letzten Aufrufe funktionierten alle, auch das Auslesen mit XPath.
            Nur um Deine Mitarbeit ist es nicht bestens bestellt.

            PHP-Code:
            <?php 
            if (isset($_SERVER["HTTP_USER_AGENT"]) and !empty($_SERVER["HTTP_USER_AGENT"])) {
                
            $agent htmlspecialchars($_SERVER["HTTP_USER_AGENT"]);
            }
            else {
            $agent "Mozilla/5.0 (compatible; Test/PHP)";
            }
            header("Content-Type: text/html; charset=UTF-8");
            error_reporting(-1);
            ini_set("display_errors"true);
            ini_set("user_agent"$agent);
            libxml_use_internal_errors(true);

            if(!
            function_exists("gzdecode")) {

                function 
            gzdecode($data) {

                    
            $len strlen($data);

                    if (
            $len 18 || strcmp(substr($data,0,2),"\x1f\x8b")) {
                        return 
            null;
                    }
                    
            $method ord(substr($data,2,1));
                    
            $flags  ord(substr($data,3,1));

                    if (
            $flags 31 != $flags) {
                        return 
            null;
                    }

                    
            $mtime unpack("V"substr($data,4,4));
                    
            $mtime $mtime[1];
                    
            $xfl   substr($data,8,1);
                    
            $os    substr($data,8,1);
                    
            $headerlen 10;
                    
            $extralen  0;
                    
            $extra     "";
                    if (
            $flags 4) {
                        if (
            $len $headerlen 8) {
                        return 
            false;
                    }
                    
            $extralen unpack("v",substr($data,8,2));
                    
            $extralen $extralen[1];
                    if (
            $len $headerlen $extralen 8) {
                        return 
            false;
                    }
                    
            $extra substr($data,10,$extralen);
                    
            $headerlen += $extralen;
                    }

                    
            $filenamelen 0;
                    
            $filename "";
                    if (
            $flags 8) {
                        if (
            $len $headerlen 8) {
                            return 
            false;
                    }
                    
            $filenamelen strpos(substr($data,8+$extralen),chr(0));
                    if (
            $filenamelen === false || $len $headerlen $filenamelen 8) {
                        return 
            false;
                    }
                    
            $filename substr($data,$headerlen,$filenamelen);
                    
            $headerlen += $filenamelen 1;
                    }

                    
            $commentlen 0;
                    
            $comment "";
                    if (
            $flags 16) {
                        if (
            $len $headerlen 8) {
                            return 
            false;
                    }
                    
            $commentlen strpos(substr($data,8+$extralen+$filenamelen),chr(0));
                    if (
            $commentlen === false || $len $headerlen $commentlen 8) {
                      return 
            false;
                    }
                    
            $comment substr($data,$headerlen,$commentlen);
                    
            $headerlen += $commentlen 1;
                    }

                    
            $headercrc "";
                    if (
            $flags 1) {
                        if (
            $len $headerlen 8) {
                            return 
            false;
                    }
                    
            $calccrc crc32(substr($data,0,$headerlen)) & 0xffff;
                    
            $headercrc unpack("v"substr($data,$headerlen,2));
                    
            $headercrc $headercrc[1];
                    if (
            $headercrc != $calccrc) {
                      return 
            false;
                    }
                    
            $headerlen += 2;
                    }

                    
            $datacrc unpack("V",substr($data,-8,4));
                    
            $datacrc $datacrc[1];
                    
            $isize unpack("V",substr($data,-4));
                    
            $isize $isize[1];

                    
            $bodylen $len-$headerlen-8;
                    if (
            $bodylen 1) {
                        return 
            null;
                    }
                    
            $body substr($data,$headerlen,$bodylen);
                    
            $data "";
                    if (
            $bodylen 0) {
                        switch (
            $method) {
                            case 
            8:
                                
            $data gzinflate($body);
                                break;
                            default:
                                return 
            false;
                        }
                    }
                    if (
            $isize != strlen($data) || crc32($data) != $datacrc) {
                        return 
            false;
                    }
                    return 
            $data;
                }
            }
            ?>
            <!DOCTYPE html>
            <html>

            <head>
            <title>Nur eine Testseite</title>
            </head>

            <body>
            <h1>Testseite</h1>
            <ul>
            <?php
            $data 
            gzdecode(file_get_contents("http://www.publico.es"));

            $doc = new DOMDocument();
            $doc->loadHTML($data);

            $xPath = new DOMXPath($doc);

            $zaehler 0;
            foreach (
            $xPath->query("//div[@class=\"tituloNoticia mi12 t3\"]/h3/a") as $element) {

                
            $hreft $element->getAttribute('href');
                
            $title $element->nodeValue;

                echo 
            "<li><a href=\"".htmlspecialchars($hreftENT_QUOTES)."\" target=\"_blank\">".htmlspecialchars($titleENT_QUOTES)."</a></li>\n";
                
            $zaehler++;
                }
            ?>
            </ul>
            </body>
            </html>
            Die Kommentare habe ich entfernt, damit das Listing nicht noch länger wird, ist aber praktisch die Funktion aus dem 3. Beispiel von dieser Seite:

            PHP: gzdecode - Manual

            Kommentar


            • #7
              Sorry

              aber ich musste mal zwischendurch meinem Job nachgehen. Ich bin Dir wirklich für Deine Arbeit dankbar, habe Deinen vorigen Test ausprobiert, der ja mal vernünftige Sachen, mal wirres Zeug brachte, genau wie von Dir beschrieben.

              Und den Text zum Accept: Encoding habe ich auch nicht besser verstanden, ich hatte daraufhin das Ganze erstmal etwas ruhen lassen und wusste nicht, dass Du weiter so engagiert daran bastelst, Und wie gesagt, mein Job rief.

              Also, noch mal Danke, war keine Ignoranz, wenn ich mich mal nicht gemeldet habe.

              Werde Deinen Code gleich morgen ausprobieren und habe dann bestimmt noch ein paar dumme oder weniger dumme Fragen.

              Gruß
              newbie1955

              Kommentar


              • #8
                Wollte ja gestern auch nicht damit beginnen und mich um andere Dinge kümmern. Nur dann fand ich doch keine Ruhe. Versuche diese Funktion zu verstehen, vorher müsste ich aber diese RFC 1952 Spezifikation verstehen, nehme ich mal an. Vielleicht sollte ich es auf bessere Zeiten verschieben.

                Kommentar


                • #9
                  Noch 'ne Xpath-Frage

                  Hallo, noch mal zum Thema XPATH - (hatte erst damit ein neues Thema aufgemacht, sorry!)

                  Hier der Quelltext der zu lesenden Seite

                  [COLOR=#000080]<div class=[COLOR=#0000ff]"mbk-headline"[/COLOR]>[/COLOR] [COLOR=#000080]<strong>[/COLOR][COLOR=#008000]<a href=[COLOR=#0000ff]"/Nachrichten/Niedersachsen/Uebersicht/Landtagspraesident-fuer-automatische-Diaetenerhoehung"[/COLOR] class=[COLOR=#0000ff]"mbk-containerlink"[/COLOR]>[/COLOR] Landtagspräsident für automatische Diätenerhöhung[COLOR=#008000]</a>[/COLOR][COLOR=#000080]</strong>[/COLOR] [COLOR=#000080]</div>[/COLOR]
                  Hier mein -leider erfolgloser - Versuch:

                  PHP-Code:
                                              foreach ($xPath->query('//div[@class="mbk-headline"]/a') as $element) { 
                  Hat jemand eine Ahnung, wo mein Fehler liegt?

                  Gruß
                  newbie1955
                  Zuletzt geändert von newbie1955; 16.05.2013, 16:46.

                  Kommentar


                  • #10
                    Zitat von newbie1955 Beitrag anzeigen
                    Hat jemand eine Ahnung, wo mein Fehler liegt?
                    An Deiner Vergesslichkeit?
                    Die Antworten hast Du doch schon erhalten, siehe: http://www.php-resource.de/forum/php...rkt-nicht.html

                    Zitat von Melewo Beitrag anzeigen
                    Bei mir funktioniert es, wenn ich die Reihenfolge von Knoten und Kindern einhalte ...
                    Zitat von litterauspirna Beitrag anzeigen
                    wenn du bei deinem DIV einsteigst und irgendwo dort in der Hierarchie zu einem a Tag willst, musst du natürlich auch den Hierarchie Pfad bis dahin angeben, wie soll denn das a Tag sonst gefunden werden?

                    Kommentar


                    • #11
                      Ja,..

                      aber ich habe es auch mit //a oder /strong/a versucht, ebenso ohne Erfolg. Zwischen der class und dem a ist ja nur eine <strong>-Angabe, wie stelle ich die in der Abfrage dar? als /strong/a klappt es ja nicht. ALso, ich bin nicht so sehr vergesslich, als dass ich vielmehr einen Hinweis auf eine gute xpath-Syntaxerklärung bräuchte. (möglichst auf Deutsch)

                      Danke
                      Gruß
                      newbie1955

                      Kommentar


                      • #12
                        Ich habe da keine Probleme.

                        Testdatei:
                        HTML-Code:
                        <!DOCTYPE html>
                        <html>
                        
                        <head>
                        <title>Test</title>
                        </head>
                        
                        <body>
                        <h1>Nur ein Test</h1>
                        <p>Probleme?</p>
                        <div class="mbk-headline"> <strong><a href="/Nachrichten/Niedersachsen/Uebersicht/Landtagspraesident-fuer-automatische-Diaetenerhoehung" 
                        class="mbk-containerlink"> Landtagspräsident für automatische Diätenerhöhung</a></strong> </div>
                        </body>
                        </html>
                        Ausgabe mit:
                        PHP-Code:
                        <!DOCTYPE html>
                        <html>

                        <head>
                        <title>Test</title>
                        <meta charset="UTF-8">
                        </head>

                        <body>
                        <h1>Test</h1>
                        <div class="border">

                        <ul>
                        <?php
                        error_reporting
                        (-1);
                        ini_set("display_errors"true);

                        $data file_get_contents("abc.html");
                        $doc = new DOMDocument();

                        $doc->loadHTML($data);

                        $xPath = new DOMXPath($doc);

                        $zaehler 0;
                        foreach (
                        $xPath->query('//div[@class="mbk-headline"]/strong/a') as $element) {

                            
                        $hreft $element->getAttribute('href');
                            
                        $title $element->nodeValue;

                            echo 
                        "<li><a href=\"".htmlspecialchars($hreftENT_QUOTES)."\" target=\"_blank\">".htmlspecialchars($titleENT_QUOTES)."</a></li>\n";
                            
                        $zaehler++;
                        }

                        ?>
                        </ul>
                        </div>
                        </body>
                        </html>
                        Und wenn es dennoch Probleme geben sollte, dann hilft halt nur die Datei herunterladen und suchen, bis der Fehler gefunden ist.

                        In der Wikipedia ist ja ein Überblick und da sind auch einige weitere Seiten unten verlinkt, doch so für einen Überblick gefällt mir eigentlich diese Seite, zumal da die grafische Darstellung der Achsen recht gut zu sein scheint:

                        SELFHTML: XML / Darstellung von XML-Daten / XPath-Syntax

                        Habe das jetzt aber nicht alles gelesen, werde ich aber vielleicht noch machen. Eigentlich auch nicht schlecht:

                        XPath ? Wikipedia

                        Doch wenn ich mal die ausführliche Notation nehme, wie bei selfhtml beschrieben, dann klappt das halt auch.
                        PHP-Code:
                        foreach ($xPath->query('//child::div[@class="mbk-headline"]/child::strong/child::a') as $element) { 
                        Vielleicht wäre diese Schreibweise ja für Dich nicht schlecht, damit Du immer weißt, wessen Kind was ist. Also, wenn die Großeltern ihre Enkel sehen möchten, können sie nicht ihre eigenen Kinder übergehen, ohne dass es Störungen gibt.
                        Zuletzt geändert von Melewo; 17.05.2013, 21:42.

                        Kommentar


                        • #13
                          Oh, mensch

                          ...irgendwo gab es dieses emoticon, wo sich jemand selbst mit dem Hammer auf den Kopf haut, das würde jetzt passen:

                          ich hatte ja bei mir noch eine größer/kleiner Abfrage drin, um die Ausgabe auf max. 13 Zeilen zu begrenzen und statt

                          HTML-Code:
                          if ($zaehler <= 13)
                          geschrieben
                          HTML-Code:
                          if ($zaehler >= 13)
                          .

                          Da kann es ja nix werden.

                          Vielen Dank dennoch für die Grundsätzliche Hilfe, besonders SELFHTML ist ein guter Tipp, da hatte ich vor sehr langer Zeit schon mal was gefunden zu Xpath und es aber wieder vergessen (Vergesslichkeit!!). Werde mir jetzt alles in ein eigenes Manual für den Desktop kopieren, damit ich hier wenigstens zu Xpath möglichst keine dummen Fragen mehr stelle. Und auch der Tipp mit der ausführlichen Notierung ist gut.

                          Gruß
                          newbie1955

                          Kommentar


                          • #14
                            Ein Forum ist ja mit dafür da, um Fragen zu stellen, nur nach dem Du Dich über Monate in XPath eingearbeitet hast, solltest Du doch nun eigentlich kein Newbie in Sachen XPath mehr sein, sondern einer der Experten auf diesem Teilgebiet, der auf alle Fragen von anderen eine Antwort geben könnte, wenn diese Fragen XPath betreffen.

                            Damit meine ich jetzt nicht, dass Du ein Experte in Sachen Programmierung sein solltest, dazu sind die Themen und Sprachen viel zu komplex, doch halt ein Experte auf einem Teilgebiet, mit dem Du Dich seit Monaten beschäftigt hast. Und irgendwie klang das noch nicht so richtig danach.

                            Kommentar


                            • #15
                              Tja

                              ich sollte sicher schon besser sein, hadere aber immer wieder mit Detailproblemen. Selbst nach Lektüre der Selfhtml-Seite über xpath.
                              Nur mal so als Beispiel (ohne dass ich jetzt dazu eine Antwort will):

                              HTML-Code:
                                                          <div class="mbk-header">                     <strong class="block-subheadline"> Teterow</strong>                     <a href="/Nachrichten/Sport/Fussball/Bergring-Teterow-zum-93.-Mal-Mekka-des-Motorsports" class="mbk-containerlink mbk-headline"> Bergring Teterow zum 93. Mal Mekka des Motorsports</a></strong>                 </div>
                              Das habe ich so versucht:
                              PHP-Code:
                              foreach ($xPath->query('//div[@class="mbk-header"]/strong[@class="block-subheadline"]//a') as $element) { 
                              und so
                              PHP-Code:
                              foreach ($xPath->query('//div[@class="mbk-header"]/strong[@class="block-subheadline"]/a') as $element) { 
                              Beides ohne Erfolg. Werde da weiter herumfrickeln, aber ich verstehe eben nicht so richtig, wo dann das child aufhört usw. Und wie man beispielsweise Platzhalter einfügt.

                              Also bevor ich das nicht wirklich super beherrsche, kann ich auch nicht so richtig anderen helfen. Da würde ich wohl eher falsches verbreiten.
                              Will aber im Prinzip gerne das PHP-Wissen, das ich mittlerweile habe, auch an newbies weitergeben.

                              Gruß
                              newbie1955

                              P.S. Habe inzwischen erfolgreich gefrickelt und festgestellt, dass strong ja in diesem Fall nix mit meinem a zu tun hat. Naja, so tastet man sich voran...Werde mir jetzt noch mal ein xpath-Plugin für firefox holen, dann wirds schon werden.
                              Zuletzt geändert von newbie1955; 18.05.2013, 18:54.

                              Kommentar

                              Lädt...
                              X