2015-05-08 26 views
8

Utilizzando rvest in R per raschiare una pagina web, vorrei estrarre l'equivalente di innerHTML da un nodo, in particolare di cambiare line-break in a capo prima di applicare html_text.R: rvest estrazione innerHTML

Esempio di funzionalità desiderata:

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

dovranno produrre output seguente:

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

Con rvest 0.2 questo può essere ottenuto attraverso 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>" 

Con il recente 01.238.876,166 milaquesto non funziona più.

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

La funzionalità desiderata è generalmente disponibile nella funzione write_xml del pacchetto xml2 su cui rvest ora dipende - se solo write_xml potrebbe dare la sua uscita ad una variabile invece di insistere per scrivere in un file. (anche un textConnection non è accettato).

Come soluzione posso temporaneamente scrivere in un file:

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

con questo posso poi per esempio trasformare i tag di interruzione di riga in caratteri di nuova riga:

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

E` c'è un modo migliore per farlo con le funzioni esistenti, ad es rvest, xml2, XML o altri pacchetti? In particolare, vorrei evitare di scrivere sul disco rigido.

+1

Sembra come il deposito di un problema su github potrebbe essere più produttivi ... – hadley

+0

per il follow-up, questo è stato aggiunto come un problema e [alla fine risolto] (https://github.com/hadley/rvest/ problemi/87). La risposta è semplicemente usare 'as.character'. – r2evans

risposta

0

Come indicato da @ r2evans, as.character(doc) è la soluzione.

Per quanto riguarda l'ultima frammento di codice, che vuole estrarre il testo -separated <br> fuori del nodo durante la conversione <br> al ritorno a capo, c'è una soluzione nel momento irrisolta rvest issue #175, comment #2:

La versione semplificata per questo problema:

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"