Zagnieżdżony selektor w xPath

0

Hey,

potrzebuję stworzyć query dla DomXPath(). Selektor CSS, który mnie interesuje to div#content h2.title. Niestety nie potrafię tego zapisać w xPath. Mam skrypt, który znajduje mi wszystkie elementy h2 z nadaną klasą title ale potrzebuję to zawęzić i szukać tylko wewnątrz div o id content

$result = $finder->query(".//h2[contains(@class, 'title')]");
foreach($result1 as $r1){
    $tmpTitle .= $r1->textContent;
}	

Tutaj mała ściąga: https://devhints.io/xpath#axes

niestety nie potrafię sobie poradzić.

1
NewUser2k13 napisał(a):

ale potrzebuję to zawęzić i szukać tylko wewnątrz div o id content

Zgodnie z semantyką nie potrzebujesz "szukać tylko wewnątrz div o id content". Ponieważ powinien istnieć tylko jeden element z takim ID. Może dzięki temu będzie Ci prościej.

PS: jeśli jakimś cudem masz dwa rożne elementy z takim ID - to napisz proszę, czy masz tego świadomość? ew. w jakim celu użyto takiego podejścia?

1
axelbest napisał(a):
NewUser2k13 napisał(a):

ale potrzebuję to zawęzić i szukać tylko wewnątrz div o id content

Zgodnie z semantyką nie potrzebujesz "szukać tylko wewnątrz div o id content". Ponieważ powinien istnieć tylko jeden element z takim ID. Może dzięki temu będzie Ci prościej.

@axelbest Wprowadzasz pytającego w błąd.

Pytający ma dużo divów o różnych id które zawierają h2.title, i jeden z tych divów ma #content, więc @NewUser2k13 chce wyszukać tylko te h2.title które są w div#content. To jest jak najbardziej zasadne.

NewUser2k13 napisał(a):

Hey,

potrzebuję stworzyć query dla DomXPath(). Selektor CSS, który mnie interesuje to div#content h2.title. Niestety nie potrafię tego zapisać w xPath. Mam skrypt, który znajduje mi wszystkie elementy h2 z nadaną klasą title ale potrzebuję to zawęzić i szukać tylko wewnątrz div o id content

$result = $finder->query(".//h2[contains(@class, 'title')]");
foreach($result1 as $r1){
    $tmpTitle .= $r1->textContent;
}	

Tutaj mała ściąga: https://devhints.io/xpath#axes

niestety nie potrafię sobie poradzić.

Co do Twojego pytania, zostaje gwestia czy h2.title ma być bezpośrednio w div#content (a'la div#content > h2.title), czy może być zagnieżdżony. Jeśli może być zagnieżdżony to xPath pod to to:

.//div[@id="content"]//h2[contains(@class, 'title')]
0

@axelbest
Już tłumaczę. Parsuję zewnętrzną witrynę pod kontem poszukiwania pożądanych treści.
Jest to serwis informacyjny, który codziennie dodaje aktualności. Bazując na słowach kluczowych (frazach) szukam linków (href) na tej stronie, które te frazy zawierają (np fraza "Ogłoszenie o naborze" zmieniana jest na ciąg "ogloszenie-o-naborze").
Gdy jest jakieś dopasowanie - pobieram treść tej strony (właściwy artykuł).
Teraz muszę wyciągnąć nazwę tego artykułu i tutaj jest właśnie opisywany problem.
$finder->query(".//h2[contains(@class, 'title')]");
zwraca mi wszystkie elementy h2.title -> tych na stronie jest dużo. Jest to ilość dynamiczna.
Dlatego też chcę zawęzić poszukiwania do fragmentu
div#content h2.title -> w tym div zawsze jest tylko jeden element h2 z klasą title.

@Riddle
Tak, może być zagnieżdżony.
Ogólnie on jest w:
div#content > article > header > h2.title
tak więc
div#content h2.title
może być

Próbowałem też tego co zaproponowałeś:
.//div[@id="content"]//h2[contains(@class, 'title')]
niestety robiąc sobie var_dump()
zwraca mi
DOMNodeList Object ( [length] => 0 )

1
NewUser2k13 napisał(a):

Próbowałem też tego co zaproponowałeś:
.//div[@id="content"]//h2[contains(@class, 'title')]
niestety robiąc sobie var_dump()
zwraca mi
DOMNodeList Object ( [length] => 0 )

No to musiałeś coś źle zrobić, bo dla takiego markup:

<div>
  <div id="content">
    <header>
     <h2 class="title">Title</h2>
   </header>
  </div>
</div>

xPath .//div[@id="content"]//h2[contains(@class, 'title')] znajduje element h2.

0

@Riddle

$doc = new DOMDocument();
$doc->loadHTML($newsHTML);
$finder = new DomXPath($doc);
     
$result1 = $finder->query(".//div[@id='content']//h2[contains(@class, 'title')]");
var_dump($result1);
foreach($result1 as $r1){
    $tmpTitle .= $r1->textContent;
}	

$newsHTML pobieram cURLem

Struktura witryny, którą parsuję:

screenshot-20230614113201.png

1
NewUser2k13 napisał(a):

@Riddle

$doc = new DOMDocument();
$doc->loadHTML($newsHTML);
$finder = new DomXPath($doc);
     
$result1 = $finder->query(".//div[@id='content']//h2[contains(@class, 'title')]");
var_dump($result1);
foreach($result1 as $r1){
    $tmpTitle .= $r1->textContent;
}	

$newsHTML pobieram cURLem

Struktura witryny, którą parsuję:

screenshot-20230614113201.png

Zapisz $newsHtml do pliku, file_put_contents("file.html", $newsHtml); i wrzuć go na forum.

Odpal sobie taki kod, to zobaczysz że dostajesz element:

<?php
$newsHTML = '
<!DOCTYPE html>
<html>
<body>
<div>
  <div id="content">
    <header>
     <h2 class="title">Title</h2>
    </header>
  </div>
</div>
</body>
</html>
';
$doc = new DOMDocument();
$doc->loadHTML($newsHTML);
$finder = new DomXPath($doc);

$result1 = $finder->query(".//div[@id='content']//h2[contains(@class, 'title')]");
var_dump($result1);
class DOMNodeList#4 (1) {
  public $length =>
  int(1)
}
0

Racja, coś nie tak z pobieraniem HTML.
Cała strona jest, ale ten konkretny div#content ma zawartość:

<div id='content'>
<div id="error404"></div>
</div>

Zabieram się za cURL w takim razie.
Dziękuje bardzo za pomoc. Sam na pewno nadal błądziłbym i szukał przyczyny w DomXPath

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