Не удается найти правильное выражение XPath (для объединения результатов) - PullRequest
2 голосов
/ 13 марта 2011

Я пытаюсь получить список пословиц из википедии .

Я могу выбрать:

  • категории (например, "aanval", "aap")
  • пословицы (например, "De aanhouder wint.")
  • объяснения (например, "Wie blijft probren zijn doel te bereiken, heeft uiteindelijk succes. Je moet volhouden.")

но им трудно присоединиться к ним правильным образом. Я хотел бы в конечном итоге с массивом, как:

array(
  0 => array(
    'category' => 'aanval',
    'proverb' => 'De aanval is de beste verdediging.',
    'explanation' => array(
      0 => 'Je kunt in een strijd of ruzie beter zelf actie ondernemen dan afwachten.',
    )
  ),
  1 => array(
    'category' => 'aap',
    'proverb' => 'Al draagt een aap een gouden ring, het is en blijft een lelijk ding.',
    'explanation' => array(
      0 => 'Wie zich mooi aankleedt wordt daarmee zelf nog niet mooi.',
      1 => 'Of: Wie zich kleedt als iemand van aanzien wordt daarmee nog niet aanzienlijk.',
      2 => 'Of: Fraaie kleding en sieraden maken een lelijk mens niet mooi.'
    )
  ),
  2 => array(
    'category' => 'aap',
    'proverb' => 'Als apen hoger klimmen willen, ziet men gauw hun blote billen.',
    'explanation' => array(
      0 => 'Iemand die meer wil dan hij kan, maakt zich snel belachelijk.',
    )
  ),
);

Вот код, который я сейчас использую:

if ($x = urlToXpath($url, true))
{
  $keywords = array();
  foreach ($x->query('/html/body/div[3]/div[3]/h2/span[@class="mw-headline"]') as $node)
  {
    $keywords[] = trim($node->nodeValue);
  }

  $data = array();
  foreach ($x->query('/html/body/div[3]/div[3]/dl/dd/dl') as $node)
  {
    $proverbs = array();
    foreach ($x->query('dd[@style="font-weight: bold"] | dd/b', $node) as $childNode)
    {
      $proverbs[] = trim($childNode->nodeValue);
    }
    $descriptions = array();
    foreach ($x->query('dd[position()>1]/small', $node) as $childNode)
    {
      $descriptions[] = trim(preg_replace('/^((Ook|Of):)/i', '', $childNode->nodeValue));
    }
    $data[] = array('proverbs' => $proverbs, 'descriptions' => $descriptions);
  }
}

Ответы [ 2 ]

1 голос
/ 13 марта 2011

Чтобы сделать это с xpath, вам, вероятно, потребуется выбрать каждый H2, а затем использовать это решение , чтобы выбрать все узлы, содержащие пословицы между ними.Затем сделайте то же самое на этих узлах, чтобы найти описания.

Возможно, вам будет проще загрузить вики-текст для страницы (например, как этот ) и обработать его с помощью простого текстового анализатора.по строкам в тексте.Или, если не так, вы должны по крайней мере использовать action=render, чтобы получить версию без всего HTML-кода, связанного со скином .

0 голосов
/ 14 марта 2011

Это выражение XPath выбирает нужные (три) узлы для первой пословицы:

 /html/body/div[3]/div[3]/h2[1]/span[@class="mw-headline"]
|
 /html/body/div[3]/div[3]/h2[1]/following-sibling::dl[1]/dd/dl/dd[1]/b 
|  
 /html/body/div[3]/div[3]/h2[1]/following-sibling::dl[1]/dd/dl/dd[2]/small

Требуемые три узла для второй пословицы выбираются этим выражением XPath (обратите внимание, что только индекс увеличивается с 1 до 2):

 /html/body/div[3]/div[3]/h2[2]/span[@class="mw-headline"]
|
 /html/body/div[3]/div[3]/h2[2]/following-sibling::dl[1]/dd/dl/dd[1]/b 
|  
 /html/body/div[3]/div[3]/h2[2]/following-sibling::dl[1]/dd/dl/dd[2]/small

... и т.д.

Это дает вам хороший алгоритм для заполнения ваших массивов - итерируйте индекс: 1, 2, 3, ... до тех пор, пока для некоторого индекса K оценка построенного выражения XPath не выберет никаких узлов - тогда вы закончены.

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