Как извлечь текст только из родительского узла HTML (исключая дочерний узел)?

У меня есть код:

<div class="activityBody postBody thing">
    <p>
        <a href="/forum/conversation/post/3904-22" rel="post" data-id="3904-22" class="mqPostRef">(22)</a>
        where?
    </p>
</div>

Я использую этот код для извлечения текста:

html_nodes(messageNode, xpath=".//p") %>% html_text() %>% paste0(collapse="\n")

И получаем результат:

"(22) where?"

Но мне нужен только текст «p», исключая текст, который может находиться внутри «p» в дочерних узлах. Мне нужно получить этот текст:

"where"

Есть ли способ исключить дочерние узлы при получении текста?

Mac OS 10.11.6 (15G31), версия RSrudio 0.99.903, R версия 3.3.1 (21.06.2016)


person Ildar Gabdrakhmanov    schedule 31.08.2016    source источник


Ответы (2)


Это захватит весь текст из <p> дочерних узлов (что означает, что он не будет включать текст из подузлов, которые не являются «эмиттерами текста»:

library(xml2)
library(rvest)
library(purrr)

txt <- '<div class="activityBody postBody thing">
    <p>
        <a href="/forum/conversation/post/3904-22" rel="post" data-id="3904-22" class="mqPostRef">(22)</a>
        where?
    </p>
  <p>
    stays 
    <b>disappears</b>
    <a>disappears</a>
    <span>disappears</span>
    stays
  </p>
</div>'

doc <- read_xml(txt)

html_nodes(doc, xpath="//p") %>% 
  map_chr(~paste0(html_text(html_nodes(., xpath="./text()"), trim=TRUE), collapse=" "))
## [1] "where?"     "stays stays"

К сожалению, это довольно "с потерями" (вы теряете <b>, <span> и т. Д.), Но это или решение @ Floo0 (также потенциально с потерями) может сработать для вас.

Если вы используете пакет XML, вы действительно можете редактировать узлы (т.е. удалять элементы узлов).

person hrbrmstr    schedule 31.08.2016
comment
Спасибо, Боб и Floo0. Это именно то, что я искал. И теперь я понял, что большая часть моей проблемы будет решена, как только я узнаю больше о функциях XPATH. Еще раз спасибо за то, что повернули меня в правильном направлении. - person Ildar Gabdrakhmanov; 31.08.2016

Если вы уверены, что нужный текст всегда идет последним, вы можете использовать:

doc %>% html_nodes(xpath=".//p/text()[last()]") %>% xml_text(trim = TRUE)

В качестве альтернативы вы можете использовать следующее, чтобы выбрать все "непустые" треки.

doc %>% html_nodes(xpath=".//p/text()[normalize-space()]") %>% xml_text(trim = TRUE)

Для получения дополнительных сведений о normalize-space() см. https://developer.mozilla.org/en-US/docs/Web/XPath/Functions/normalize-space.

Третий вариант - использовать пакет xml2 напрямую через:

doc %>% xml2::xml_find_chr(xpath="normalize-space(.//p/text())")
person Rentrop    schedule 31.08.2016