2015-05-08 41 views
8

Stosując rvest w R złom do strony internetowej, ja tutaj wyodrębnić równoważnik innerHTML z węzła, w szczególności do zmiany przerwy na linii do nowej linii przed nałożeniem html_text.R: rvest ekstrakcji innerHTML

Przykład żądanej funkcjonalności:

library(rvest) 
doc <- read_html('<html><p class="pp">First Line<br />Second Line</p>') 
innerHTML(doc, ".pp") 

sporządza następujące wyniki:

[1] "<p class=\"pp\">First Line<br>Second Line</p>" 

z rvest 0.2 można to osiągnąć przez toString.XMLNode

# run under rvest 0.2 
library(XML) 
html('<html><p class="pp">First Line<br />Second Line</p>') %>% 
    html_node(".pp") %>% 
    toString.XMLNode 
[1] "<p class=\"pp\">First Line<br>Second Line</p>" 

z nowszym rvest 0.2.0.900 to już nie działa.

# run under rvest 0.2.0.900 
library(XML) 
html_node(doc,".pp") %>% 
    toString.XMLNode 
[1] "{xml_node}\n<p>\n[1] <br/>" 

Pożądana funkcjonalność jest ogólnie dostępne w funkcji write_xml pakietu xml2 na którym rvest zależy teraz - jeśli tylko write_xml może dać swoje wyjście do zmiennej zamiast podkreślając zapisu do pliku. (również textConnection nie jest akceptowany).

Jako obejście mogę tymczasowo zapisać do pliku:

# extract innerHTML, workaround: write/read to/from temp file 
html_innerHTML <- function(x, css, xpath) { 
    file <- tempfile() 
    html_node(x,css) %>% write_xml(file) 
    txt <- readLines(file, warn=FALSE) 
    unlink(file) 
    txt 
} 
html_innerHTML(doc, ".pp") 
[1] "<p class=\"pp\">First Line<br>Second Line</p>" 

z tym mogę wtedy na przykład przekształcić tagi podziału wiersza na znaki nowej linii:

html_innerHTML(doc, ".pp") %>% 
    gsub("<br\\s*/?\\s*>","\n", .) %>% 
    read_html %>% 
    html_text 
[1] "First Line\nSecond Line" 

Czy istnieje lepszy sposób, aby to zrobić z istniejącymi funkcjami z np rvest, xml2, XML lub inne pakiety? W szczególności chciałbym uniknąć zapisu na dysk twardy.

+1

Wygląda zgłoszenia problemu na github może być bardziej produktywny ... – hadley

+0

Do obserwacji tego dodano jako problem i [ostatecznie rozwiązany] (https://github.com/hadley/rvest/ issues/87). Odpowiedzią jest po prostu użycie 'as.character'. – r2evans

Odpowiedz

0

Jak zauważyli @ r2evans, rozwiązaniem jest as.character(doc).

chodzi ci ostatni fragment kodu, który chce, aby wyodrębnić -separated tekst <br> z węzła podczas konwersji <br> do NEWLINE, istnieje obejście w aktualnie nierozwiązany rvest issue #175, comment #2:

Uproszczona wersja tego problemu:

doc <- read_html('<html><p class="pp">First Line<br />Second Line</p>') 

# r2evan's solution: 
as.character(rvest::html_node(doc, xpath="//p")) 
##[1] "<p class=\"pp\">First Line<br>Second Line</p>" 

# [email protected]'s solution, simplified: 
innerHTML <- function(x, trim = FALSE, collapse = "\n"){ 
    paste(xml2::xml_find_all(x, ".//text()"), collapse = collapse) 
} 
innerHTML(doc) 
## [1] "First Line\nSecond Line"