XPath для td / th на основе количества tr - PullRequest
0 голосов
/ 25 января 2019

Использование XPath для webscrape.

Структура:

<table>
  <tbody>
     <tr>
        <th>
        <td>

но один из этих тр содержит только один или один тд.

<table>
      <tbody>
         <tr>
            <th>

Так что я просто хочу очистить, если TR содержит два тега внутри. Я даю путь

 $route = $path->query("//table[count(tr) > 1]//tr/th");

или

 $route = $path->query("//table[count(tr) > 1]//tr/td");

Но это не работает.

Я даю ссылки на порядковый стол здесь. Последние два TR первого стола имеют только один TD. Это вызывает проблему. И 2-я или 3-я таблица имеет ту же проблему.

https://www.daiwahouse.co.jp/mansion/kanto/tokyo/y35/gaiyo.html

      $route = $path->query("//tr[count(*) >= 2]/th");
      foreach ($route as $th){
          $property[] = trim($th->nodeValue);
      }

      $route = $path->query("//tr[count(*) >= 2]/td");
      foreach ($route as $td){
          $value[] = trim($td->nodeValue);
      }

Я пытаюсь выбрать TH и TD одновременно. НО, если TR содержит один TD, то это порождает проблему. Потому что в счетах и ​​TD и TH не совпадают, я соскребаю больше TD, чем TH

Ответы [ 3 ]

0 голосов
/ 25 января 2019

Если я правильно понимаю, вы хотите th элементов в tr с, которые содержат два элемента? Я думаю, что это то, что вам нужно:

//th[count(../*) = 2]
0 голосов
/ 25 января 2019

Я включил в свой ответ более явный путь с оператором or для подсчета элементов TH и TD

$html = '
  <html>
    <body>
      <table>
        <tbody>
          <tr>
            <th>I am Included</th>
            <td>I am a column</td>
          </tr>
        </tbody>
      </table>
      <table>
        <tbody>
          <tr>
            <th>I am ignored</th>
          </tr>
        </tbody>
      </table>
      <table>
        <tbody>
          <tr>
            <th>I am also Included</th>
            <td>I am a column</td>
          </tr>
        </tbody>
      </table>
    </body>
  </html>
';

$doc = new DOMDocument();
$doc->loadHTML( $html );

$xpath = new DOMXPath( $doc );
$result = $xpath->query("//table[ count( tbody/tr/td | tbody/tr/th ) > 1 ]/tbody/tr");

foreach( $result as $node )
{
  var_dump( $doc->saveHTML( $node ) );
}

// string(88) "<tr><th>I am Included</th><td>I am a column</td></tr>"
// string(93) "<tr><th>I am also Included</th><td>I am a column</td></tr>"

Вы также можете использовать его для любых потомков глубины

//table[ count( descendant::td | descendant::th ) > 1]//tr

Измените xpath после условия (часть в квадратных скобках), чтобы изменить то, что вы возвращаете.

0 голосов
/ 25 января 2019

Этот XPath,

//table[count(.//tr) > 1]/th

выберет все th элементы во всех table элементах, имеющих более одного tr потомка (независимо от наличия tbody).


Этот XPath,

//tr[count(*) > 1]/*

выберет всех дочерних элементов tr элементов с более чем одним дочерним элементом.


Этот XPath,

//tr[count(th) = count(td)]/*

выберет все дочерние элементы tr элементов, где число th дочерних элементов равно количеству td дочерних элементов.


OP опубликовал ссылку на сайт.Корневой элемент находится в пространстве имен xmlns="http://www.w3.org/1999/xhtml".

См. Как XPath работает с пространствами имен XML?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...