Как сделать веб-скрапинг ключевой статистики из таблиц FinViz по акциям?

Есть ли у кого-нибудь опыт очистки данных с помощью R?

Я хотел бы извлечь соответствующие данные для заданных акций. Я сделал это следующим образом:

library(XML)

stocks <- c("AAPL","MSFT")

for (s in stocks) {
  url <- paste0("http://finviz.com/quote.ashx?t=", s)
  webpage <- readLines(url)
  html <- htmlTreeParse(webpage, useInternalNodes = TRUE, asText = TRUE)
  tableNodes <- getNodeSet(html, "//table")

  # ASSIGN TO STOCK NAMED DFS
  assign(s, readHTMLTable(tableNodes[[9]], 
                          header= c("data1", "data2", "data3", "data4", "data5", "data6",
                                    "data7", "data8", "data9", "data10", "data11", "data12")))

  # ADD COLUMN TO IDENTIFY STOCK 
  df <- get(s)
  df['stock'] <- s
  assign(s, df)
}

# COMBINE ALL STOCK DATA 
stockdatalist <- cbind(mget(stocks))
stockdata <- do.call(rbind, stockdatalist)
# MOVE STOCK ID TO FIRST COLUMN
stockdata <- stockdata[, c(ncol(stockdata), 1:ncol(stockdata)-1)]

Проблема, однако, в том, что я получил его в неправильном формате:

  stock      data1       data2       data3 data4       data5  data6         data7  data8        data9          data10       data11 data12
1  AAPL      Index DJIA S&P500         P/E 16.13   EPS (ttm)  10.22   Insider Own  0.06% Shs Outstand           5.09B    Perf Week -7.35%
2  AAPL Market Cap     839.87B Forward P/E 12.50  EPS next Y  13.20 Insider Trans -7.80%    Shs Float           5.07B   Perf Month -4.38%
3  AAPL     Income      53.13B         PEG  1.38  EPS next Q   2.71      Inst Own 63.20%  Short Float           1.16% Perf Quarter -5.40%
4  AAPL      Sales     239.18B         P/S  3.51  EPS this Y 10.80%    Inst Trans  0.98%  Short Ratio            1.60  Perf Half Y  7.53%
5  AAPL    Book/sh       27.42         P/B  6.02  EPS next Y 14.97%           ROA 13.80% Target Price          192.54    Perf Year 17.05%
6  AAPL    Cash/sh       15.15         P/C 10.89 EPS next 5Y 11.68%           ROE 37.40%    52W Range 138.62 - 183.50     Perf YTD -2.54%

Что я хотел бы сделать, так это то, что определенный запас появляется только один раз в имени строки, а затем имена данных отображаются как имена столбцов, где столбцы затем содержат соответствующие числа...


person Frank    schedule 24.03.2018    source источник
comment
Ваш вопрос похож на (хотя и не является точной копией) stackoverflow.com/questions/40490717/ - проверьте там и посмотрите, поможет ли это. Совет: используйте rvest для парсинга.   -  person mysteRious    schedule 24.03.2018
comment
@mysteRious, я видел конкретный пост перед публикацией, однако он не помог мне в моей проблеме... :(   -  person Frank    schedule 24.03.2018
comment
О, наконец-то я понимаю, что ты пытаешься сделать. Будет работать над этим.   -  person mysteRious    schedule 24.03.2018
comment
@mysteRious Цель состоит в том, чтобы получить его в каком-то стандартном широком формате ... чтобы упростить анализ данных ...   -  person Frank    schedule 24.03.2018


Ответы (1)


Это не супер элегантно, но выполняет свою работу. Он основан на знании того, что интересующие вас данные находятся в 6-м table на этой странице:

library(rvest)
url <- read_html("http://finviz.com/quote.ashx?t=AAPL")
tables <- html_nodes(url,"table")
scraped <- tables %>% html_nodes("table") %>% .[6] %>% 
    html_table(fill=TRUE) %>% data.frame()

Это дает данные, которые выглядят так:

> str(scraped)
'data.frame':   12 obs. of  12 variables:
 $ X1 : chr  "Index" "Market Cap" "Income" "Sales" ...
 $ X2 : chr  "DJIA S&P500" "839.87B" "53.13B" "239.18B" ...
 $ X3 : chr  "P/E" "Forward P/E" "PEG" "P/S" ...
 $ X4 : chr  "16.13" "12.50" "1.38" "3.51" ...
... the rest is truncated

Вы можете получить нужный формат, используя stack:

new_df <- as.data.frame(scraped[, seq(from=2, to=ncol(scraped), by=2)])
new_labels <- as.data.frame(scraped[, seq(from=1, to=ncol(scraped), by=2)])
results_df <- as.data.frame(cbind(stack(new_labels),stack(new_df))[,c(1,3)])
names(results_df) <- c("stock","AAPL")

Это дает results_df, который выглядит следующим образом, который содержит все 72 пары переменная/значение:

> head(results_df)
    Variable       Value
1      Index DJIA S&P500
2 Market Cap     839.87B
3     Income      53.13B
4      Sales     239.18B
5    Book/sh       27.42
6    Cash/sh       15.15

Затем вы можете транспонировать его и добавить стандартные метки с помощью as.data.frame(t(rbind(c("stock","AAPL"),results_df))) .

person mysteRious    schedule 24.03.2018