Ankündigung

Einklappen
Keine Ankündigung bisher.

[erledigt] preg_match_all - Nicht der ganze Quellcode wird dursucht

Einklappen

Neue Werbung 2019

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

  • [erledigt] preg_match_all - Nicht der ganze Quellcode wird dursucht

    Hallo,
    ich möchte gerne auf folgender Seite: "http://www.wettergefahren.de/DWD/war.../warnings.json" Wetterwarnungen auslesen.
    Das funktioniert so weit auch, aber leider nicht, wenn mehrere Warnungen auftauchen.

    Folgenden Regex habe ich generiert:
    PHP-Code:
    preg_match_all("/Schweiz(.*)start":(.*),"(.*)headline":"(.*)","event"(.*)description":"(.*)","(.*)end":(.*),"type":(.*),"level":(.*),"state/", $utf8$matches); 
    Hier ist ein Beispiel, wie mehrere Warnungen für einen Ort ausschauen:
    Code:
    [{"regionName":"Kreis Sächsische Schweiz-Osterzgebirge - westelbisches Bergland","altitudeStart":null,"altitudeEnd":null,"start":1446032700000,"headline":"Amtliche WARNUNG vor WINDBÖEN","event":"WINDBÖEN","instruction":"","description":"Es treten Windböen mit Geschwindigkeiten bis 60 km/h (17m/s, 33kn, Bft 7) aus südöstlicher Richtung auf.","end":1446058800000,"type":1,"level":2,"state":"Sachsen"},{"regionName":"Kreis Sächsische Schweiz-Osterzgebirge - westelbisches Bergland","altitudeStart":800,"altitudeEnd":null,"start":1446013560000,"headline":"Amtliche WARNUNG vor NEBEL","event":"NEBEL","instruction":"","description":"Durch aufliegende Wolken treten oberhalb 800 m gebietsweise Sichtweiten unter 150 Meter auf.","end":1446051600000,"type":4,"level":2,"state":"Sachsen"}]
    Das Problem hier ist nun, dass nur die erste Warnung erkannt wird, aber die zweite nicht. Seltsamerweise wird dier zweite Warnung aber erkannt, wenn ich einen Zeilenumbruch zwischen den beiden Warnungen habe:
    Code:
    [{"regionName":"Kreis Sächsische Schweiz-Osterzgebirge - westelbisches Bergland","altitudeStart":null,"altitudeEnd":null,"start":1446032700000,"headline":"Amtliche WARNUNG vor WINDBÖEN","event":"WINDBÖEN","instruction":"","description":"Es treten Windböen mit Geschwindigkeiten bis 60 km/h (17m/s, 33kn, Bft 7) aus südöstlicher Richtung auf.","end":1446058800000,"type":1,"level":2,"state":"Sachsen"},
    {"regionName":"Kreis Sächsische Schweiz-Osterzgebirge - westelbisches Bergland","altitudeStart":800,"altitudeEnd":null,"start":1446013560000,"headline":"Amtliche WARNUNG vor NEBEL","event":"NEBEL","instruction":"","description":"Durch aufliegende Wolken treten oberhalb 800 m gebietsweise Sichtweiten unter 150 Meter auf.","end":1446051600000,"type":4,"level":2,"state":"Sachsen"}]
    Wenn ich mit str_replace die Trennung zwischen den Warnungen
    Code:
     },{
    durch
    Code:
     },\n{
    ersetze funktioniert es leider auch nicht.

    Edit: Funktioniert doch. War wieder zu schnell mit fragen.

  • #2
    Das ist JSON, hör auf da mit regex rumzuspielen und schau dir die Daten direkt an: http://php.net/json_decode
    [QUOTE=nikosch]Macht doch alle was Ihr wollt mit Eurem Billigscheiß. Von mir aus sollen alle Eure Server abrauchen.[/QUOTE]

    Kommentar


    • #3
      Danke für deine Anmerkung. Aber damit komme ich irgendwie gar nicht klar. Mein obiges Beispiel funktioniert leider doch nicht richtig.

      Folgenden Ansatz habe ich und bekomme nur NULL.
      PHP-Code:
      $quelle file_get_contents("http://wettergefahren.de/DWD/warnungen/warnapp/warnings.json");
      var_dump(json_decode($quelletrue)); 

      Kommentar


      • #4
        ist kein gültiges JSON

        PHP-Code:
        $quelle file_get_contents("http://wettergefahren.de/DWD/warnungen/warnapp/warnings.json");
        $a json_decode($quelletrue);
        echo 
        json_last_error_msg(); // "Syntax error" 
        Code:
        warnWetter.loadWarnings({"time ...

        Nur vom Prinzip her.. was stört wegmachen, dann läufts durch. Geht sicher sauberer.

        PHP-Code:
        $quelle file_get_contents('http://wettergefahren.de/DWD/warnungen/warnapp/warnings.json');
        $aToRemove = ['warnWetter.loadWarnings('');'];
        $quelle str_replace($aToRemove''$quelle);
        $a json_decode($quelletrue);

        echo 
        "<pre>";
        print_r($a);
        echo 
        "</pre>"
        The string "()()" is not palindrom but the String "())(" is.

        Debugging: Finde DEINE Fehler selbst! | Gegen Probleme beim E-Mail-Versand | Sicheres Passwort-Hashing | Includes niemals ohne __DIR__
        PHP.de Wissenssammlung | Kein Support per PN

        Kommentar


        • #5
          Was da geliefert wird ist JSONP. Habe hier noch diese interessante Funktion gefunden, die sowohl JSON als auch JSONP decodiert:
          PHP-Code:
          function jsonp_decode($jsonp$assoc false) { 
              if(
          $jsonp[0] !== '[' && $jsonp[0] !== '{') { // we have JSONP
                 
          $jsonp substr($jsonpstrpos($jsonp'('));
              }
              return 
          json_decode(trim($jsonp,'();'), $assoc);

          Kommentar


          • #6
            Zitat von hausl Beitrag anzeigen
            ist kein gültiges JSON

            PHP-Code:
            $quelle file_get_contents("http://wettergefahren.de/DWD/warnungen/warnapp/warnings.json");
            $a json_decode($quelletrue);
            echo 
            json_last_error_msg(); // "Syntax error" 



            Nur vom Prinzip her.. was stört wegmachen, dann läufts durch. Geht sicher sauberer.

            PHP-Code:
            $quelle file_get_contents('http://wettergefahren.de/DWD/warnungen/warnapp/warnings.json');
            $aToRemove = ['warnWetter.loadWarnings('');'];
            $quelle str_replace($aToRemove''$quelle);
            $a json_decode($quelletrue);

            echo 
            "<pre>";
            print_r($a);
            echo 
            "</pre>"
            Das funktioniert so weit. Ich komme jetzt allerdings nicht weiter.
            Der Aufbau ist nun wie in dem Screenshot.
            arrays.JPG
            Wie komme ich nun an die einzelnen Schlüssel ran, wie z.B. an event aber nur, wenn regionName = Hannover ist?

            So z.B. funktionierts nicht:
            PHP-Code:
            foreach($matches[4] as $i => $titel)
            {
            if (
            $matches[10][$i] == "1") {
                
            $color 'c5e566'

            Kommentar


            • #7
              zB mit foreach() auf warnings. Unter dem jeweiligen Schlüssel hast du immer [0] und darunter das was du brauchst.
              Oder du suchst dir im web eine fertige search_recursive oder sowas.
              etc. etc.
              The string "()()" is not palindrom but the String "())(" is.

              Debugging: Finde DEINE Fehler selbst! | Gegen Probleme beim E-Mail-Versand | Sicheres Passwort-Hashing | Includes niemals ohne __DIR__
              PHP.de Wissenssammlung | Kein Support per PN

              Kommentar


              • #8
                Ich stehe gerade komplett auf dem Schlauch. Verschachtelte Arrays sind für Anfänger auch nicht gerade einfach...
                Mit folgendem:
                PHP-Code:
                $quelle file_get_contents('http://wettergefahren.de/DWD/warnungen/warnapp/warnings.json');
                $aToRemove = ['warnWetter.loadWarnings('');'];
                $test str_replace($aToRemove''$test);
                $matches json_decode($testtrue);

                echo 
                "<pre>";
                foreach (
                $matches[warnings] as $k => $v) {
                    echo 
                "\$matches[$k] => $v.\n";
                }
                echo 
                "</pre>"
                bekomme ich folgendes ausgegeben:
                Code:
                $matches[109271000] => Array.
                $matches[109183000] => Array.
                $matches[103353000] => Array.
                $matches[105566000] => Array.
                $matches[116053000] => Array.
                $matches[115086000] => Array.
                $matches[105382000] => Array.
                $matches[112052000] => Array.
                $matches[106433000] => Array.
                usw. Wenn ich nun noch hinter $matches[warnings] eine der langen Nummern schreibe, sieht das ähnlich aus:
                Code:
                $matches[0] => Array.
                $matches[1] => Array.
                $matches[2] => Array.
                Bringt mich aber leider immer noch nicht weiter... Müsste ich nicht so die Werte angezeigt bekommen?

                Kommentar


                • #9
                  Nein, sonst würdest du die ja bekommen. Schau dir bitte mal Grundlagen an. Besonders zur Arrayverarbeitung. Dein Code ist ja sogar falsch, keine Quotes um warnings. Und warum escapst du? Und die Zahlen sind deine subArrays, und darunter, jeweils "unterhalb" von [0] ist was du brauchst.. wie ich oben schon erwähnt habe.

                  Zitat von hausl
                  zB mit foreach() auf warnings. Unter dem jeweiligen Schlüssel hast du immer [0] und darunter das was du brauchst.
                  PHP-Code:
                  foreach ($a['warnings'] as $aSub) {
                      echo 
                  $aSub[0]['regionName']."<br>\n";

                  Schau ev. mal ob die ID des Ortes ja immer gleich ist, zB die 109271000 von Deggendorf (siehe dein Screenshot #6). Dann brauchst du das foreach() gar nicht und kannst direkt darauf zugreifen.

                  (Scheibar gibt es keine API dort um direkt ohne immer den ganzen Wulst, einen Ort holen zu können. Hier auch der Hinweis, das zu beachten: http://www.wettergefahren.de/copyright.html )

                  Wenn du zB nur Deggendorf haben willst, kannst du auch so machen (hier geitppt). In deinem Screenshot oben in #6 gibt es für Deggendorf näcmlich 2 Warn-Einträge, daher schön zum Testen.

                  PHP-Code:
                  $locationID 109271000// Deggendorf

                  if (isset($aAllData['warnings'][$locationID])) {
                      
                  $aLocationData $aAllData['warnings'][$locationID];
                  }

                  var_dump($aLocationData); 
                  Zum Parsen des JSONP solltest du übrigens die Funktion in #5 verwenden. Das von mir war nur ein Workaround als Mittel zum Zweck damit ich es laufen lassen kann, keinen Endlösung!
                  The string "()()" is not palindrom but the String "())(" is.

                  Debugging: Finde DEINE Fehler selbst! | Gegen Probleme beim E-Mail-Versand | Sicheres Passwort-Hashing | Includes niemals ohne __DIR__
                  PHP.de Wissenssammlung | Kein Support per PN

                  Kommentar


                  • #10
                    Zitat von 112marv Beitrag anzeigen
                    Verschachtelte Arrays sind für Anfänger auch nicht gerade einfach...
                    Mit zunehmender Tiefe wird es nicht nur für Anfänger schwierig den Überblick zu behalten. Anstelle mit x verschachtelten foreach zu arbeiten, bieten sich hier Iteratoren an. Nun sind diese für Anfänger nicht so leicht zu verstehen und auch nicht immer besonders gut dokumentiert. Eine Nutzung lohnt aber allemal.

                    Die Aufgabenstellung hier etwas verallgemeinert könnte so lauten:
                    Liefere mir alle Childarrays, welche bestimmte vorgegebene Schlüssel beinhalten und diese auf bestimmte Werte zeigen.
                    z.B. 'regionName' => "Stadt Koblenz" oder 'state' => "Rheinland-Pfalz"

                    Die Idee für eine Filterfunktion ist jetzt, die Suchkriterien in einem Array zu übergeben und alle Childarrays welche die Suchkriterien erfüllen unabhängig von der Tiefe einzusammeln. Eine solche Funktion dürfte für ähnliche Probleme sofort nutzbar bzw. leicht erweiterbar sein. Für das Verständnis braucht man nur zu wissen, das der Iterator ein Objekt liefert, über das mit foreach iteriert werden kann und so alle Elemente geliefert bekommt.
                    Mit is_array haben wir nur ein Auge auf Arrays.

                    Erstentwurf der Funktion (Vorschläge zur Optimierung willkommen):
                    PHP-Code:
                    /**
                    * @param $arr array
                    * @param $filter array
                    * @return array
                    */
                    function ArrayFilterChildarraysRecursive(array $arr, array $filter){
                        
                    $res = array();
                        
                    $it =  new RecursiveIteratorIterator(
                          new 
                    RecursiveArrayIterator($arr),RecursiveIteratorIterator::SELF_FIRST
                        
                    );
                        foreach(
                    $it as $subarr){
                          if(
                    is_array($subarr)){
                            
                    $pass true;
                            foreach(
                    $filter as $fkey => $fvalue){
                              if(!isset(
                    $subarr[$fkey]) or ($subarr[$fkey] != $fvalue AND $fvalue !== null)) {
                                
                    $pass false;
                                break;
                              }
                            }
                            if(
                    $pass$res[] = $subarr;
                          }
                        }

                        return 
                    $res;

                    Beispiel für eine Nutzung der Funktion:

                    PHP-Code:
                    $url "http://wettergefahren.de/DWD/warnungen/warnapp/warnings.json";
                    $jsonp file_get_contents($url);

                    $arr jsonp_decode($jsonp,true);  //fkt. aus #5

                    //alle Clientarrays mit key array("state" => "Rheinland-Pfalz" und key "event" irgendwas
                    $filter = array("state" => "Rheinland-Pfalz""event" => null);

                    $res ArrayFilterChildarraysRecursive($arr$filter);

                    //Ausgabe als PHP-Code
                    echo "<pre>".var_export($res,true)."</pre>"
                    Die Testausgabe sieht dann so aus (verkürzt):
                    PHP-Code:
                    array (
                      
                    => 
                      array (
                        
                    'regionName' => 'Kreis Kusel',
                        
                    'altitudeStart' => NULL,
                        
                    'altitudeEnd' => 600,
                        
                    'start' => 1446627780000,
                        
                    'headline' => 'Amtliche WARNUNG vor NEBEL',
                        
                    'event' => 'NEBEL',
                        
                    'instruction' => '',
                        
                    'description' => 'Vor allem in Flussniederungen und Tallagen tritt unterhalb 600 m gebietsweise Nebel mit Sichtweiten unter 150 Meter auf.',
                        
                    'end' => 1446634800000,
                        
                    'type' => 4,
                        
                    'level' => 2,
                        
                    'state' => 'Rheinland-Pfalz',
                      ),
                      
                    => 
                      array (
                        
                    'regionName' => 'Kreis und Stadt Kaiserslautern',
                        
                    'altitudeStart' => NULL,
                        
                    'altitudeEnd' => 600 
                    Dieses Array ist gefiltert und 2-dimensional, also ideal für eine Weiterverarbeitung.

                    Kommentar


                    • #11
                      Vielen vielen Dank jspit. Das hat mir sehr weitergeholfen. Nun habe ich noch ein Problem mit den Umlauten. Wie bekomme ich diese richtig dargestellt? Wenn ich sie mit str_replace ersetzen möchte, passiert gar nichts und wenn ich utf8_encode o.ä. einsetzte funktioniert gar nichts mehr, was wohl daran liegt, dass JSON ja in UTF8 codiert sein muss.

                      Kommentar


                      • #12
                        Hast du die Zeichenkodierung im HTTP-Header gesetzt?

                        Kommentar


                        • #13
                          Das ist mein Header:
                          Code:
                          <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
                          Welche Codierung ist das eigentlich?
                          GLÄTTE, Nebenstraßen, Brücken, Glätte
                          Edit:
                          So gehts zwar, aber schön ist es nicht :
                          PHP-Code:
                          $from = array("Ä""Ö""Ãœ""ä""ö""ü""ß""°");
                          $to = array("Ä""Ö""Ü""ä""ö""ü""ß""°");
                          $test str_replace($from$to$test); 
                          Hier habe ich jetzt eine Tabelle gefunden:
                          http://www.i18nqa.com/debug/utf8-debug.html

                          Kommentar


                          • #14
                            Ich meinte den HTTP-Header und nicht den HTML-Header.

                            str_replace() ist natürlich Quatsch. Oder willst du jetzt Millionen an UTF-Zeichen damit ersetzen?

                            Kommentar


                            • #15
                              Lösung: Nutze konsequent UTF-8

                              Kommentar

                              Lädt...
                              X