Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Wyrażenie regularne - wzorzec
Forum PHP.pl > Forum > PHP
Shinji
Witam,

Potrzebuje utworzyć wzorzec do wyrażenia regularnego i tu odezwała się moja pięta achillesowa. Potrzebuje wyciągnąć z kodu sekwencje takich bloków:

  1. <tr bgcolor=#ffffff onmouseover="this.style.background='#FF4444'" onmouseout="this.style.background='#ffffff'">
  2. <td class="wyniki" nowrap>2010-04-02</td>
  3. <td class="wyniki" nowrap>Polska</td>
  4. <td class="wyniki">Bałtyk Pomorze</td>
  5. <td class="wyniki" nowrap>6,4,3</td>
  6.  
  7. <td class="wyniki" nowrap>last-minute</td>
  8. <td class="wyniki" nowrap><a href=/web/?page=szukaj3;data1eq=2010-04-02;panstwo=1;region=233;miasto=17680012;results=200;allot=ALL;order=nazwaasc;last=L> <b>Lista hoteli</b></a></td>
  9. </tr>


jednak przejscia do kolejnych linijek są dla mnie kolejnym problemem.

Z góry dzieki za pomoc.
tehaha
pokaz jak próbowałeś osiągnąć ten efekt
Shinji
  1. preg_match_all('|<tr bgcolor=#ffffff onmouseover="this.style.background=\'#FF4444\'" onmouseout="this.style.background=\'#ffffff\'">(/\s|/\r)*<td class="wyniki" nowrap>(^<)+</td>(\s|\r)*<td class="wyniki" nowrap>(^<)+</td>(\s|\r)*<td class="wyniki">(^<)+</td>(\s|\r)*<td class="wyniki" nowrap>(^<)+</td>(\s|\r)*<td class="wyniki" nowrap>(^<)+</td>(\s|\r)*<td class="wyniki" nowrap>(.*)</td>(\s|\r)*</tr>|U',$plik,$wycieczki);

ale wywala mi błędy. próbowałem też łopatoligicznie zostawić odstępy tak jak są bez zastępowanai ich \r \s ale też nie pali.
Methestel
Polecam modyfikator 'm' albo 's': Pattern Modifiers

Jeszcze bardziej polecam zainteresować się jakąś biblioteką do XML-a (np SimpleXML) i użyć jej do wyciągania danych z wklejonego przez Ciebie kodu.

DiH
Jezusie, po co mu do tego jakieś biblioteki?

  1. preg_match_all("#<td[^>](.*?)</td>#", $string, $matches);
  2. // $string to przeszukiwany ciag
  3. // $matches to tablica z wynikami
  4. // Ciebie interesuje $matches[0]

Na przyszłość postaraj się użyć wyszukiwarki forum.
Shinji
DiH po pierwsze zauważ, że w niektórych tagach <td> pojawia się element nowrap. Po za tym tak czy inaczej potrzebuje jakoś pogrupować wyniki, a nie gdy podobnych bloków bedzie więcej dane mi się zmieszają.

Methestel mógłbyś powiedzieć troche więcej o tych 2 rozwiązaniach w praktyce. Bo nie dokońca rozumiem manuala.
DiH
Nie rozumiem, o co chodzi z tym nowrap? Jeżeli zaistnieje kilka takich bloków, to pierwszym wyrażeniem wyciągasz wszystko z <tr>
  1. #<tr[^>](.*?)</tr>#s
, a następnym (tym, które podałem) ładne dzielisz resztę. I wtedy żaden bałagan Ci się nie zrobi.
Shinji
Chodzi o to, że w
  1. #<tr[^>](.*?)</tr>#s
zapomniałeś o jednym domknięciu Kleene'ego, powinno być jak coś
  1. #<tr[^>]*>(.*?)</tr>#s


Tak czy inaczej to nie rozwiązuje mojego problemu, gdyż iż ponieważ z kodu z jakiego to wyciagam pojawia się więcej <td></td> które nie są sekwencją bloku. Tak więcej potrzebuje wyrażenia zawierającego cały blok.
Methestel
Przykład rozwiązania z zastosowaniem SimpleXML:
  1. <?php
  2. $sourceCode = '
  3. <table>
  4. <tr bgcolor=#ffffff onmouseover="this.style.background=\'#FF4444\'" onmouseout="this.style.background=\'#ffffff\'">
  5. <td class="wyniki" nowrap>2010-04-02</td>
  6. <td class="wyniki" nowrap>Polska</td>
  7. <td class="wyniki">Bałtyk Pomorze</td>
  8. <td class="wyniki" nowrap>6,4,3</td>
  9. <td class="wyniki" nowrap>last-minute</td>
  10. <td class="wyniki" nowrap><a href=/web/?page=szukaj3;data1eq=2010-04-02;panstwo=1;region=233;miasto=17680012;results=200;allot=ALL;order=nazwaasc;las
    t=L> <b>Lista hoteli</b></a></td>
  11. </tr>
  12. </table>';
  13. $sourceCode = strip_tags($sourceCode, '<table><tr><th><td>'); //zostawiamy tylko tagi table, tr, td, th
  14. $sourceCode = preg_replace('/<([a-z]+) ?[^>]*>/i', '<$1>', $sourceCode); //wywalamy wszystkie atrybuty tagow
  15. $sourceCode = '<?xml version="1.0" encoding="iso-8859-2" ?>'.$sourceCode; //możliwe że będiesz musiał zmienić kodowanie
  16.  
  17. try {
  18. $xml = @new SimpleXMLElement($sourceCode);
  19. } catch (Exception $e) {
  20. echo '<pre>'.print_r($e).'</pre>'; //prymitywna obsługa błędu :)
  21. }
  22.  
  23. foreach ($xml->tr as $tr) {
  24. echo $tr->td[0].'<br />'.$tr->td[1].'<br />'.$tr->td[2].'<br />'.$tr->td[3].'<br />'.$tr->td[4].'<br />';
  25. }
  26. ?>

Wynik:
  1. 2010-04-02
  2. Polska
  3. Bałtyk Pomorze
  4. 6,4,3
  5. last-minute

Można też próbować tak jak Ty próbowałeś zrobić to tylko wyrażeniami regularnymi, ale jest z tym trochę więcej zabawy. Osobiście polecam rozwiązanie którego przykład podałem, ale jeśli koniecznie chcesz to zrobić bez przerabiania na xml albo kod źródłowy strony jest tak zwalony że ciężko jest przerobić go na xml-a daj znać. Coś na to poradzimy smile.gif

A odnośnie modyfikatorów:
m - zmienia zachowanie '^' i '$' w wyrażeniach regularnych. Bez tego modyfikatora wyrażenie zastosowane do wielolinijkowego tekstu dopasuje '^' i '$' kilkakrotnie na początku i na końcu każdej lini tektu. Z tym modyfikatorem '^' i '$' dopasowywane są tylko raz na początku i na końcu tekstu (czyli tak jak większość ludzi się spodziewa smile.gif )
s - kropka w wyrażeniu regularny dopasowuje się także do znaku nowej linii
DiH
A czy mógłbyś zatem podlinkować do tego kodu? Chętnie udowodnię, że da się to zrobić samymi wyrażeniami regularnymi. Jeżeli podasz ten kod, zaznacz które komórki mają zostać uwzględnione w wynikach.
Methestel
Tylko wyrażenia regularne:

  1. <?php
  2. $sourceCode = '<table>
  3. <tr bgcolor=#ffffff onmouseover="this.style.background=\'#FF4444\'" onmouseout="this.style.background=\'#ffffff\'">
  4. <td class="wyniki" nowrap>2010-04-02</td>
  5. <td class="wyniki" nowrap>Polska</td>
  6. <td class="wyniki">Bałtyk Pomorze</td>
  7. <td class="wyniki" nowrap>6,4,3</td>
  8. <td class="wyniki" nowrap>last-minute</td>
  9. <td class="wyniki" nowrap><a href=/web/?page=szukaj3;data1eq=2010-04-02;panstwo=1;region=233;miasto=17680012;results=200;allot=ALL;order=nazwaasc;las
    t=L> <b>Lista hoteli</b></a></td>
  10. </tr>
  11. </table>';
  12.  
  13. $matches = array();
  14. $data = preg_match_all('/<tr ?.*?>.*?<td ?.*?>(.*?)<\/td>.*?<td ?.*?>(.*?)<\/td>.*?<td ?.*?>(.*?)<\/td>.*?<td ?.*?>(.*?)<\/td>.*?<td ?.*?>(.*?)<\/td>.*?<td ?.*?>(.*?)<\/td>.*?<\/tr>/si', $sourceCode, $matches);
  15.  
  16. unset($matches[0]);
  17. foreach ($matches as $cols) {
  18. foreach ($cols as $value) {
  19. echo $value.'<br />';
  20. }
  21.  
  22. }
  23. ?>

Wynik:
  1. 2010-04-02
  2. Polska
  3. Bałtyk Pomorze
  4. 6,4,3
  5. last-minute
  6. Lista hoteli
DiH
  1. $s = file_get_contents('http://strona.pl');
  2.  
  3. preg_match_all("#<tr[^>](.*?)</tr>#s", $s, $matches);
  4.  
  5. for($i = 0; $i < sizeof($matches[0]); $i++) {
  6. $e = strip_tags($matches[0][$i]);
  7. $e = preg_replace("#(\s+)#"," | \r\n",$e);
  8. echo $e.'<br/>';
  9. }


Pozdrawiam
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.