2016-08-19 3 views
2

Я заинтересован, чтобы извлечь адреса источника и демо для набора Джекил темы в data.frameИзвлечение hrefs из списка в R с некоторыми отсутствующими значениями

library(rvest) 

info <- read_html("https://github.com/jekyll/jekyll/wiki/themes") 

data <- info %>% 
html_nodes(" #wiki-body li") 

data 
{xml_nodeset (115)} 


[11] <li>Typewriter - (<a href="https://github.com/alixedi/typewriter">source</a>, <a href="http://alixedi.github.io/typewriter">demo</a>)</li> 
[12] <li>block-log - (<a href="https://github.com/anandubajith/block-log">source</a>), <a href="https://anandu.net/demo/block-log/">demo</a>)</li> 
[13] <li>Otter Pop - (<a href="https://github.com/tybenz/otter-pop">source</a>)</li> 

Так я хочу data.frame (ДФ) с 3 колонки, например

name  source          demo 
Typewriter https://github.com/alixedi/typewriter   http://alixedi.github.io/typewriter 

Я могу извлечь все hrefs как вектор, но, как вы можете видеть, из [13] нет демо для некоторых сайтов, так что я потом сталкиваются с трудностями

Есть ли простой способ Я могу создать df из данных? Возможно, с помощью purrr библиотеки

ответ

3

Вот ваш purrr -ish ответ:

library(rvest) 
library(purrr) 
library(dplyr) 

info <- read_html("https://github.com/jekyll/jekyll/wiki/themes") 

themes <- html_nodes(info, xpath=".//div[@class='markdown-body']/*/li") 

zero_to_na <- function(x) { ifelse(length(x)==0, NA, x) } 

df <- data_frame(name=gsub(" [- ]*\\(.*$", "", html_text(themes)), 
       source=map_chr(themes, ~html_attr(html_nodes(., xpath=".//a[contains(., 'source')]"), "href")), 
       demo=map_chr(themes, ~zero_to_na(html_attr(html_nodes(., xpath=".//a[contains(., 'demo')]"), "href")))) 

glimpse(df) 
## Observations: 115 
## Variables: 3 
## $ name <chr> "Jalpc", "Pixyll", "Jekyll Metro", "Midnight", "Leap Day", "F... 
## $ source <chr> "https://github.com/Jack614/jalpc_jekyll_theme", "https://git... 
## $ demo <chr> "http://www.jack003.com", "http://pixyll.com/", "http://blog-... 

попеременно:

map_df(themes, function(x) { 
    data_frame(name=gsub(" [- ]*\\(.*$", "", html_text(x)), 
      source=html_attr(html_nodes(x, xpath=".//a[contains(., 'source')]"), "href"), 
      demo=zero_to_na(html_attr(html_nodes(x, xpath=".//a[contains(., 'demo')]"), "href"))) 
}) 

gsub/sub/и т. Д. Независимо от того, какую часть имени вы не хотите.

+0

Спасибо за функции inc purrr. Это довольно кривая обучения – pssguy

4
data_out <- c() 
for (i in 1:length(data)) { 
    row <- data.frame(html_text(data[i]), as.character(html_children(data[[i]]))[1], as.character(html_children(data[[i]]))[2]) 
    data_out <- rbind(data_out, row) 
} 
names(data_out) <- c("name", "source", "demo") 
data_out$name <- gsub(" - [(]source, demo[)]", "", data_out$name) 
data_out$source <- gsub("<a href=\"|\">source</a>", "", data_out$source) 
data_out$demo <- gsub("<a href=\"|\">demo</a>", "", data_out$demo) 
+0

Спасибо за предоставление еще одной альтернативы – pssguy

2

Вы можете получить те, с демонстрационными данными и те, без демо-данных отдельно, используя XPath, чтобы отделить две группы:

withDemo <- info %>% 
    html_nodes(xpath = "//li[contains(., 'source') and contains(., 'demo')]") 

withoutDemo <- info %>% 
    html_nodes(xpath = "//li[contains(., 'source') and not(contains(.,'demo'))]") 

Затем создайте dataframe для коллекции с источником и демо-ссылки:

sourceNdemo <- withDemo %>% 
    html_children() %>%    # get all children 
    html_attr("href") %>%   # get the href attributes 
    matrix(ncol = 2, byrow = TRUE) # 2 pieces of data for each row 

sourceNdemo <- setNames(
    data.frame(html_text(withDemo), sourceNdemo), # html_text to get "name" column 
    c("name", "source", "demo")) 

Затем создайте фрейм данных для тех, только с исходными данными

source <- withoutDemo %>% 
    html_children() %>% 
    html_attr("href") 

# set demo = NA for easy rbind-ing 
source <- data.frame(name = html_text(withoutDemo), source = source, demo = NA) 

rbind два dataframes

allInfo <- rbind(sourceNdemo, source) 

В колонке "Имя" теперь содержит записи как "Jalpc - (источник, демо)" и "" Bitwiser-материал (источник, демо)». Вы можете избавиться от лишних "(источник, демо)" биты с помощью GSUB:

allInfo$name <- sub("\\s(-\\s)?\\(.+$", "", allInfo$name, perl = TRUE) 
+0

Это оказалось самым быстрым подходом и может быть лучшей альтернативой для больших входов – pssguy

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