2016-06-11 4 views
0

У меня есть соскабливание страницы с помощью simple_html_dom. На странице, которую я соскабливаю, есть таблица со строками, а внутри них - куча ячеек. Я хочу получить материал в третьей ячейке в каждой строке. У данной ячейки нет класса.Почему этот селектор simple_html_dom не работает, когда он используется целиком, но не разбит на более мелкие селектор?

<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> 

Так, чтобы начать, я пошел прямо к третьей ячейке:

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

Но потом я понял, что мне нужно некоторые данные в другой ячейке в строке (td.firstcell). Эта клетка имеет класс, так что я лучше подумал Переберите строк, а затем использовать селекторы в контексте этой строки:

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! 

} 

Так как вы можете видеть, мой селектор п-й ребенок вдруг в контексте строка цикла не работает. Что мне не хватает?

+0

Вы можете добавить целевой html для теста? – smoqadam

+0

@smoqadam, конечно, спасибо, я добавил. – willdanceforfun

ответ

2

Это ограничение simple html dom. По-видимому, он может работать с селекторами nth-child, но только тогда, когда родительский элемент находится в дереве ниже узла, на котором вы применяете find.

Но действительный селектор, как показывает эквивалент JavaScript:

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>

В качестве временного решения можно использовать индекс массива на find('td') результат:

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

Или, альтернативно, с children, так как td являются прямыми детьми tr:

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

Спасибо за объяснение этого, а также обучение действительно хороший способ проверить, правильно ли мой селектор! Я никогда бы не подумал, что это ограничение в пакете. – willdanceforfun

1

вы можете использовать children($int) способ. $int начинайте с 0.

попробовать это:

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

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

также у вас есть: first_child(), last_child(), parent(), next_sibling(), prev_sibling()

 Смежные вопросы

  • Нет связанных вопросов^_^