为 ML 相关的网络抓取加载数千个 URL - 代码非常慢,需要效率提示
Loading thousands of URLS for ML-related web-scraping - code is VERY slow, need efficiency tips
我正在通过从各个网站抓取数据来构建一个数据集,用于股票信号预测算法。我的算法设置方式涉及分层 for 循环和加载数千个 URL,因为每个 link 指的是股票及其各种定量统计数据。需要帮助提高处理速度。有什么建议吗?
我已经和几个不同的人谈过如何解决这个问题,有些人推荐矢量化,但这对我来说是新的。我也试过切换到数据table,但我没有看到太大的变化。 eval 行是我学会了以我想要的方式操作数据的技巧,但我认为这可能是它速度慢的原因,但我对此表示怀疑。我也想知道远程处理,但这可能超出了 R 世界。
对于下面的代码,假设还有 4 个这样的部分用于我要加载的来自不同网站的其他变量,并且所有这些块都在一个更大的 for 循环中,因为我正在生成两个数据集 (设置 = c("training, testing")).
tryCatch 用于防止代码在加载 URL 时遇到错误而停止。这些 url 被加载到一个列表中,每个股票一个 - 所以它们很长。第二个 for 循环从 URLS 抓取数据并将它们以正确的格式发布到数据框中。
library(quantmod)
library(readr)
library(rvest)
library(data.table)
urlsmacd <- vector("list", length =
eval(parse(text=as.name(paste0("nrow(", set[y], ")", sep = "")))))
for(h in 1:eval(parse(text=as.name(paste0("nrow(", set[y], ")", sep =
""))))){
urlsmacd[h] <- paste0('http://www.stockta.com/cgi-bin/analysis.pl?
symb=',eval(parse(text=as.name(paste0(set[y],"[,1][h]", sep =
"")))),'&mode=table&table=macd&num1=1', sep = '')
}
for(j in 1:eval(parse(text=as.name(paste0("nrow(", set[y], ")", sep =
""))))){
tryCatch({
html <- read_html(urlsmacd[[j]])
#get macd html
MACD26 <- html_nodes(html,'.borderTd~ .borderTd+ .borderTd:nth-child(3)
font')
MACD26 <- toString(MACD26)
MACD26 <- gsub("<[^>]+>", "", MACD26)
if(!is.na(MACD26)){
MACD26 <- as.double(MACD26)
}
eval(parse(text=as.name(paste0(set[y],"$","MACD26[j] <- MACD26"))))
MACD12 <- html_nodes(html,'.borderTd+ .borderTd:nth-child(2) font')
MACD12 <- toString(MACD12)
MACD12 <- gsub("<[^>]+>", "",MACD12)
if(!is.na(MACD12)){
MACD12 <- as.double(MACD12)
}
eval(parse(text=as.name(paste0(set[y],"$","MACD12[j] <- MACD12"))))
}, error=function(e){cat("ERROR :",conditionMessage(e), "\n")})
}
综上所述,这个过程大约需要 6 个小时。按照这个速度,减少这个过程的时间将使我的项目进展变得容易得多。
感谢 Whosebug 人员的支持。
检查 doParallel 包。它具有 foreach 循环的并行实现。它允许您使用 CPU 的更多核心(如果有可用的话)来为定义的函数执行并行 R 会话。例如:
library(doParallel)
no_cores <- detectCores() - 1
cl <- makeCluster(no_cores, type="FORK")
registerDoParallel(cl)
result <- foreach(i=10:10000) %dopar%
getPrimeNumbers(i)
如果url存储在一个列表中,还有一个并行的lapply。
例子取自这个伟大的post:
https://www.r-bloggers.com/lets-be-faster-and-more-parallel-in-r-with-doparallel-package/amp/
希望对您有所帮助。
我正在通过从各个网站抓取数据来构建一个数据集,用于股票信号预测算法。我的算法设置方式涉及分层 for 循环和加载数千个 URL,因为每个 link 指的是股票及其各种定量统计数据。需要帮助提高处理速度。有什么建议吗?
我已经和几个不同的人谈过如何解决这个问题,有些人推荐矢量化,但这对我来说是新的。我也试过切换到数据table,但我没有看到太大的变化。 eval 行是我学会了以我想要的方式操作数据的技巧,但我认为这可能是它速度慢的原因,但我对此表示怀疑。我也想知道远程处理,但这可能超出了 R 世界。
对于下面的代码,假设还有 4 个这样的部分用于我要加载的来自不同网站的其他变量,并且所有这些块都在一个更大的 for 循环中,因为我正在生成两个数据集 (设置 = c("training, testing")).
tryCatch 用于防止代码在加载 URL 时遇到错误而停止。这些 url 被加载到一个列表中,每个股票一个 - 所以它们很长。第二个 for 循环从 URLS 抓取数据并将它们以正确的格式发布到数据框中。
library(quantmod)
library(readr)
library(rvest)
library(data.table)
urlsmacd <- vector("list", length =
eval(parse(text=as.name(paste0("nrow(", set[y], ")", sep = "")))))
for(h in 1:eval(parse(text=as.name(paste0("nrow(", set[y], ")", sep =
""))))){
urlsmacd[h] <- paste0('http://www.stockta.com/cgi-bin/analysis.pl?
symb=',eval(parse(text=as.name(paste0(set[y],"[,1][h]", sep =
"")))),'&mode=table&table=macd&num1=1', sep = '')
}
for(j in 1:eval(parse(text=as.name(paste0("nrow(", set[y], ")", sep =
""))))){
tryCatch({
html <- read_html(urlsmacd[[j]])
#get macd html
MACD26 <- html_nodes(html,'.borderTd~ .borderTd+ .borderTd:nth-child(3)
font')
MACD26 <- toString(MACD26)
MACD26 <- gsub("<[^>]+>", "", MACD26)
if(!is.na(MACD26)){
MACD26 <- as.double(MACD26)
}
eval(parse(text=as.name(paste0(set[y],"$","MACD26[j] <- MACD26"))))
MACD12 <- html_nodes(html,'.borderTd+ .borderTd:nth-child(2) font')
MACD12 <- toString(MACD12)
MACD12 <- gsub("<[^>]+>", "",MACD12)
if(!is.na(MACD12)){
MACD12 <- as.double(MACD12)
}
eval(parse(text=as.name(paste0(set[y],"$","MACD12[j] <- MACD12"))))
}, error=function(e){cat("ERROR :",conditionMessage(e), "\n")})
}
综上所述,这个过程大约需要 6 个小时。按照这个速度,减少这个过程的时间将使我的项目进展变得容易得多。
感谢 Whosebug 人员的支持。
检查 doParallel 包。它具有 foreach 循环的并行实现。它允许您使用 CPU 的更多核心(如果有可用的话)来为定义的函数执行并行 R 会话。例如:
library(doParallel)
no_cores <- detectCores() - 1
cl <- makeCluster(no_cores, type="FORK")
registerDoParallel(cl)
result <- foreach(i=10:10000) %dopar%
getPrimeNumbers(i)
如果url存储在一个列表中,还有一个并行的lapply。
例子取自这个伟大的post:
https://www.r-bloggers.com/lets-be-faster-and-more-parallel-in-r-with-doparallel-package/amp/
希望对您有所帮助。