2016-06-11 1 views
0

Je vais faire un tour en grattant une page avec simple_html_dom. Sur la page, je racle, il y a une table avec des rangées, et à l'intérieur, un tas de cellules. Je veux avoir des choses dans la troisième cellule de chaque rangée. La cellule en question n'a pas de classe.Pourquoi ce sélecteur simple_html_dom ne fonctionne-t-il pas lorsqu'il est utilisé dans son intégralité, mais pas lorsqu'il est fragmenté en sélecteurs plus petits?

<tr class="thisrow"> 
    <td class="firstcell"><strong>1st</strong></td> 
    <td class="secondcell">nothing in here</td> 
    <td><strong>blah blah</strong></td> 
    <td>something else</td> 
</tr> 

Donc, pour commencer, je suis allé directement à la troisième cellule:

foreach($html->find('tr.thisrow td:nth-child(3)') as $thirdcell) { 
    echo $thirdcell->innertext // this works, no problem! 
} 

Mais je me suis aperçu que je avais besoin des données dans une autre cellule de la ligne (td.firstcell). Cette cellule a une classe, donc je pensais mieux à boucle à travers les lignes, puis utilisez les sélecteurs dans le contexte de cette ligne:

foreach($html->find('tr.thisrow') as $row) { 

    $thirdcell = $row->find('td:nth-child(3)'); 
    echo $thirdcell; // this is now empty 

    $firstcell = $row->find('td.firstcell'); 
    echo $firstcell; // this works! 

} 

Donc, comme vous pouvez le voir, mon sélecteur nième enfant tout à coup dans le contexte de la La boucle de ligne ne fonctionne pas. Qu'est-ce que je rate?

+0

pourriez-vous ajouter le code html cible pour le test? – smoqadam

+0

@smoqadam, bien sûr, merci, je l'ai ajouté. – willdanceforfun

Répondre

2

Il est une limitation de simple html dom. Apparemment, il peut traiter avec nth-child sélecteurs, mais seulement lorsque le parent est dans l'arbre en dessous du nœud sur lequel vous appliquez find.

Mais il est un sélecteur valide, comme le JavaScript équivalent montre:

for (var row of [...document.querySelectorAll('tr.thisrow')]) { 
 
    var thirdcell = row.querySelectorAll('td:nth-child(3)'); 
 
    console.log(thirdcell[0].textContent); // this works! 
 
}
<table border=1> 
 
<tr class="thisrow"> 
 
    <td class="firstcell"><strong>1st</strong></td> 
 
    <td class="secondcell">nothing in here</td> 
 
    <td><strong>blah blah</strong></td> 
 
    <td>something else</td> 
 
</tr> 
 
</table>

Pour contourner ce problème, vous pouvez utiliser l'index de tableau sur le résultat find('td'):

foreach($html->find('tr.thisrow') as $row) { 
    $thirdcell = $row->find('td'); 
    echo $thirdcell[2]; // this works 
} 

Ou, alternativement avec children, comme td sont les enfants directs de tr:

foreach($html->find('tr.thisrow') as $row) { 
    $thirdcell = $row->children(); 
    echo $thirdcell[2]; // this works 
} 
+0

Merci d'avoir expliqué cela, et aussi d'enseigner un très bon moyen de vérifier si mon sélecteur est bon! Je n'aurais jamais imaginé que c'était une limitation dans le paquet. – willdanceforfun

1

vous pouvez utiliser la méthode children($int). $int commence par 0.

essayez ceci:

$row = $html->find('tr.thisrow',0); 

$firstcell = $row->children(2)->innertext; 
$thirdcell = $row->children(0)->innertext; 

aussi vous avez: first_child(), last_child(), parent(), next_sibling(), prev_sibling()