Wyrażenia regularne - wycinanie fragmentów

0

Dzień dobry
nie wiem jak wydobyć konkretną wartość ze zmiennej w której znajduje się kod html.

Dokładnie chcę pobrać cały link o klasie abc który znajduje się w konkretnym miejscu.
Niestety na stronie mam go w kilku miejscach.
Interesuje mnie tylko jedno miejsce w ścieżce ->klasa3 >klasa4 >abc

Przykład:

<p class="klasa1">
<div class="klasa2">
<a class="abc">
</a>
</div>
</p>

<p class="klasa3">
<div class="klasa4">
<a class="abc">
</a>
</div>
</p>

próbuje użyć

if(preg_match_all('#<a class="abc">(.*?)</a>#is', $zmienna, $wyniki) 

jednak pokazuje to mi 2 elementy z klasy abc. Chce tylko z wyżej podanej ścieżki.

Czy jest możliwość zawęzić ilość wyszukanych wyników do np. 15?

1

Nie ustawiłeś wyrażenia dla dla atrybutu class i dla tego wyświetla Ci tylko dwa wyniki.
Spróbuj kodu:

if(preg_match_all("#<p class=\"([A-Za-z0-9]+)\">(.*?)</p>#si",$zmienna,$wynik)) {
	foreach($wynik[1] as $i => $klasa) {
		if(preg_match_all("#<div class=\"([A-Za-z0-9]+)\">(.*?)</div>#si",$wynik[2][$i],$wynik2)) {
			foreach($wynik2[1] as $i2 => $klasa2) {
				if(preg_match_all("#<a class=\"([A-Za-z0-9]+)\">(.*?)</a>#si",$wynik2[2][$i2],$wynik3)) {
					foreach($wynik3[1] as $i3 => $klasa3) {
						echo "-> {$klasa} -> {$klasa2} -> {$klasa3}\r\n";
					}
				}
			}
		}
	}
}

Wynik:

-> klasa1 -> klasa2 -> abc
-> klasa3 -> klasa4 -> abc
3

@ewelROSSA: Zabrałeś się za coś za co wielu się już zbierało i poległo. Nie próbuj parsować HTML'a regexpami, bo to przysporzy Ci tylko krew i łzy. Użyj odpowiedniego parsera HTML. Jest jeden wbudowany w PHP, są też inne do pobrania. Ten z wykorzystaniem kodu z PHP wyglada tak:

        $code = <<<HTML
<div class="klasa1">
    <div class="klasa2">
      <a class="abc"></a>
    </div>
</div>
<div class="klasa2">
    <div class="klasa2">
      <a class="abc"></a>
    </div>
</div>
HTML;

        $document = new DOMDocument();
        $document->loadHTML($code);

        foreach ($document->getElementsByTagName('div') as $child) {
            if ($child->getAttribute('class') === 'klasa1') {
                // Tutaj $child to jest Twój `div` z klasą `klasa1`
            }
        }

Jeśli potrzebujesz tylko obiekt w klasie klasa1 -> klasa2 -> klasa3 to polecam zrobić pętlę w pętli, lub zrobić z tego funkcję, lub skorzystać z findera, jest ich kilka np:

  • DOMXPath - użycie $finder->query("//*[contains(concat(' ', normalize-space(@class), ' '), '
  • Zend_Dom_Query - użycie - $finder->query("*[class~=\"$classname\"]");

Dzięki za wezwnie @cerrato :D Śmieszne że zostałem regexerem.

Pętla w pętli, gdybyś chciał.

     foreach ($document->getElementsByTagName('div') as $child) {
            if ($child->getAttribute('class') === 'klasa1') {
                // Tutaj $child to jest Twój `div` z klasą `klasa1`

                foreach ($child->getElementsByTagName("div") as $innerChild) {
                    if ($innerChild->getAttribute('class') == 'klasa2') {
                        $a = 2;
                    }
                }
            }
        }
0

Bardzo dziękuję za zainteresowanie tematem.
Aktualnie stanąłem na:

<?php
//pobieram wszystkie tabele
if(preg_match_all("#<table[^>]*?>(.*?)</table>#si",$page,$wynik)){
    foreach($wynik[1] as $i => $klasa){
		
               //pobieram zawartość  znacznika p o klasie klasa2 z tabeli
               if(preg_match_all('#<p class="klasa2">(.*?)</p>#si',$wynik[1][$i],$wynik3)){
            foreach($wynik3[1] as $i3 => $klasa3){
				echo $wynik3[1][$i3];
            }
		}
	//pobieram z tabeli zawartość znacznika h3 (jest to znacznik a który wyświetlam)
        if(preg_match_all("#<h3[^>]*?>(.*?)</h3>#si",$wynik[1][$i],$wynik2)){
            foreach($wynik2[1] as $i2 => $klasa2){
				echo $wynik2[1][$i2]);
			}
        }	
		

    }
}
?>

Spróbowałem porwać się na

$document = new DOMDocument();
$document->loadHTML($code);

Jednak nie działa mi opcja:

$document->getElementByClassName('klasa')

oraz

$document->find(div[class*=klasa3])

Pobieranie pojedynczych elementów typu class="abc" jest do zrealizowania
inaczej sprawa się ma z elementami typu:

<div class="abc xyz " >.....</div>
...
<div class="abc ">.....</div>

chcę np pobrać div xyz i niestety nie jest to możliwe

if($document->getAttritube('class')==='xyz')

czasami znajdują się spacje między nazwami klas itd itp.

Więc chyba pozostanę przy preg_match_all. Czy jest możliwe zoptymalizowanie tego co podałem na początku ? trochę muli strona jak się wykonuje kilka takich pętli na stronie.

próbowałem odchudzić skalpowany tekst:

strip_tags($strona,'<table><p><h3><a>');

jednak usuwa to tylko znaczniki

1 użytkowników online, w tym zalogowanych: 0, gości: 1