2015-04-08 3 views
1

При использовании пакета XML R, как я могу хранить данные с определенного узла, связанного с этим узлом, например, в том же списке? Я пытаюсь получить данные, очищенные из Интернета, в фрейм данных со связанной информацией, сгруппированной в строки. Есть элементы <span> без атрибутов класса, чтобы различать их, и может быть один или два <span> в каждой связанной группе (строка кадра данных).Использование XML для сопоставления значений дочерних и родительских узлов

Вот пример html, который я сохранил как html_example.html.

<!DOCTYPE html> 
<html> 
    <body> 
     <div class="foo"> 
      <div class="fooname">Name of 1st foo</div> 
      <span>1st span in 1st foo</span> 
      <span>2nd span in 1st foo</span> 
     </div> 

     <div class="foo"> 
      <div class="fooname">Name of 2nd foo</div> 
      <span>Only 1 span in 2nd foo</span> 
     </div> 
    </body> 
</html> 

Вот текущий код синтаксического анализа и вывод:

library(XML) 

html <- readLines("html_example.html") 
parse <- htmlParse(html) 

fooname <- xpathSApply(parse, "//div[@class='foo']/div[@class='fooname']" 
    , xmlValue) 
print(fooname) 

    # > print(fooname) 
    # [1] "Name of 1st foo" "Name of 2nd foo" 

span <- xpathSApply(parse, "//div[@class='foo']/span" 
    , xmlValue) 
print(span) 

    # >  print(span) 
    # [1] "1st span in 1st foo" "2nd span in 1st foo" "Only 1 span in 2nd foo" 

Там в настоящее время нет способа связать значения «fooname» и «Диапазон». Есть ли способ получить результат очистки, чтобы выглядеть примерно так?

foo1 <- list(fooname[1], span[1:2]) 
foo2 <- list(fooname[2], span[3]) 
list1 <- list(foo1, foo2) 
list1 

    # > mylist 
    # [[1]] 
    # [[1]][[1]] 
    # [1] "Name of 1st foo" 
    # 
    # [[1]][[2]] 
    # [1] "1st span in 1st foo" "2nd span in 1st foo" 
    # 
    # 
    # [[2]] 
    # [[2]][[1]] 
    # [1] "Name of 2nd foo" 
    # 
    # [[2]][[2]] 
    # [1] "Only 1 span in 2nd foo" 

В конце концов, не нужно во время выскабливания, я хотел бы создать кадр данных, который выглядит следующим образом. Соответствующее обсуждение here ВПЛ:

FooNames <- c(fooname[1], fooname[2]) 
Span1 <- c(span[1], span[3]) 
Span2 <- c(span[2], NA) 
df <- data.frame(FooNames, Span1, Span2, stringsAsFactors = FALSE) 
df 

    # > df 
    #   FooNames     Span1    Span2 
    # 1 Name of 1st foo 1st span in 1st foo 2nd span in 1st foo 
    # 2 Name of 2nd foo Only 1 span in 2nd foo    <NA> 

ответ

2

Вы можете применить функцию к каждому из узлов, представляющих интерес (div[class="foo"] в данном случае). Простой пример принимает каждый узел и применяет xmlValue к подклассам div class="fooname" и span. Затем он возвращает эти значения как data.frame. Вы можете связать полученные data.frames вместе, чтобы получить желаемый результат:

'<!DOCTYPE html> 
<html> 
    <body> 
     <div class="foo"> 
      <div class="fooname">Name of 1st foo</div> 
      <span>1st span in 1st foo</span> 
      <span>2nd span in 1st foo</span> 
     </div> 

     <div class="foo"> 
      <div class="fooname">Name of 2nd foo</div> 
      <span>Only 1 span in 2nd foo</span> 
     </div> 
    </body> 
</html>' -> appData 
doc <- htmlParse(appData) 
myFunc <- function(x){ 
    div <- xpathSApply(x, "./div[@class='fooname']", fun = xmlValue) 
    span <- xpathSApply(x, "./span", fun = xmlValue) 
    data.frame(FooNames = div, Span1 = span[1], Span2 = span[2]) 
} 
res <- doc["//*/div[@class='foo']", fun = myFunc] 

> do.call(rbind, res) 
FooNames     Span1    Span2 
1 Name of 1st foo 1st span in 1st foo 2nd span in 1st foo 
2 Name of 2nd foo Only 1 span in 2nd foo    <NA> 
+0

Мне нравится использование 'span [2]' для ввода значения или NA, если это необходимо. Является 'doc [" // */div [@ class = 'foo'] ", fun = myFunc]' то же самое, что и xpathApply (doc, "// */div [@ class = 'foo']", fun = myFunc) '? –

+0

'[' является синтаксическим сахаром для вызова 'getNodeSet', как это видно в' getAnywhere («[XMLInternalDocument») ' – jdharrison

+0

Спасибо. Я также получил эту строку для работы с 'xpathApply'. Я также экспериментировал в других случаях с 'xpathApply' и' getNodeSet' и не вижу разницы. Какие-нибудь советы? –

Смежные вопросы