2017-03-15 6 views
3

R을 사용하고 html 문서를 구문 분석하려면 xml2 패키지를 사용합니다. I는 다음과 같습니다 html 파일의 조각, 추출 :R 및 xml2 : 노드가없는 경우에도 자식 노드 및 정보를 읽는 방법

text <- ('<div> 
<p><span class="number">1</span>First&nbsp;<span class="small-accent">previous</span></p> 
<p><span class="number">2</span>Second&nbsp;<span class="accent">current</span></p> 
<p><span class="number">3</span>Third&nbsp;</p> 
<p><span class="number">4</span>Fourth&nbsp;<span class="small-accent">last</span> A</p> 
</div>') 

을 그리고 내 목표는 텍스트에서 정보를 추출하고, 보이는 데이터 프레임으로 변환하는 것입니다 같은이 :

number  label text_of_accent type_of_accent 
1  1  First   previous  small-accent 
2  2  Second   current   accent 
3  3  Third         
4  4 Fourth A    last  small-accent 

library(xml2) 
library(magrittr) 

html_1 <- text %>% 
    read_html() %>% 
    xml_find_all("//span[@class='number']") 

number <- html_1 %>% xml_text() 

label <- html_1 %>% 
    xml_parent() %>% 
    xml_text(trim = TRUE) 

text_of_accent <- html_1 %>% 
    xml_siblings() %>% 
    xml_text() 

type_of_accent <- html_1 %>% 
    xml_siblings() %>% 
    xml_attr("class") 

불행하게도, label, text_of_accent, type_of_accent이 추출되지 않습니다

나는 다음과 같은 코드를 시도

label 
[1] "1First previous" "2Second current" "3Third"   "4Fourth last A" 

text_of_accent 
[1] "previous" "current" "last" 

type_of_accent 
[1] "small-accent" "accent"  "small-accent" 

그냥 xml2 내 목표를 달성 할 수 있는가 아니면 몇 가지 추가 도구가 필요합니다 :의 나는 기대? 적어도 label에 대한 텍스트 조각을 추출 할 수 있습니까?

+1

당신이 무엇을 기대 필드를 알고있는 경우에 나는, 논리적으로 추측하고, 상위 노드 반복을 사용하고 발견되지 않는 한 아이들을 NULL로 채 웁니다. 그게 도움이 되니? –

답변

4

는 그것은 xml2와 이유를 수행 할 수 있습니다 labelxml_text() 이러한 문제가 발생하지 않도록하기 위해, 현재 노드의 텍스트를 찾을 수 XPath는 text()를 사용하여, 노드는 현재 노드를 포함하고 그 아이의 모든 텍스트를 알게되어 엉망 먼저, 다음을 추출하고 또한 일부 노드가 존재하는지 확인하고 적절하게 누락 된 경우를 처리해야합니다

# read in text as html and extract all p nodes as a list 
lst <- read_html(text) %>% xml_find_all("//p") 

lapply(lst, function(node) { 
    # find the first span 
    first_span_node = xml_find_first(node, "./span[@class='number']") 

    number = xml_text(first_span_node, trim = TRUE) 

    # use the text() to find out text nodes from the current position 
    label = paste0(xml_text(xml_find_all(node, "./text()")), collapse = " ") 

    # find the second span 
    accent_node = xml_find_first(first_span_node, "./following-sibling::span") 

    # check if the second span exists 
    if(length(accent_node) != 0) { 
     text_of_accent = xml_text(xml_find_first(accent_node, "./text()")) 
     type_of_accent = xml_text(xml_find_first(accent_node, "./@class"))  
    } else { 
     text_of_accent = "" 
     type_of_accent = "" 
    } 

    c(number = number, label = label, 
     text_of_accent = text_of_accent, 
     type_of_accent = type_of_accent) 
}) %>% 
do.call(rbind, .) %>% as.data.frame() 


# number  label text_of_accent type_of_accent 
#1  1 First  previous small-accent 
#2  2 Second   current   accent 
#3  3 Third        
#4  4 Fourth A   last small-accent 
+0

화려한 솔루션 :) – Vilmantas