我正试图从大量网址(35000)中删除一些不同的细节。我已经使用rvest工作流定义了一些函数,我使用map将每个函数应用到每个url,直接从函数构建一个tibble。我的问题是,因为有很多网址需要很长时间来运行整个事情,我无法找到一种方法来保存结果(除非我把它设为循环,我认为是均匀的慢点)。
我能想到解决这个问题的唯一方法是映射网址的大块并相应地填充这些元素。但是这段代码效率很低,需要我一遍又一遍地手动输入大量数字。
library(rvest); library(tidyverse)
#define function to scrape webdata
##i actually have multiple functions for each css tag i want, and create a tibble column for each one
get_web_info <- function(url) {
read_html(url) %>%
html_nodes("h3:nth-of-type(1)") %>%
html_text()
}
#create tibble scraping the first 500 urls
##only scrape the first 500 because otherwise there's no output until all 35000 urls are done, which takes more than a day
scraped <- tibble(
web_info = map(url_vector[1:500], possibly(get_web_info, otherwise = NULL)),
original_url = url_vector[1:500]
)
#fill in the next 500 rows of the tibble by scraping the next 500 urls
##i would have to copy and paste the code below, manually changing which rows i'm filling in and mapping
scraped$web_info[500:1000] <- map(url_vector[500:1000], possibly(get_web_info, otherwise = NULL))
上面的代码在技术上有效,但我知道这是非常低效的并且容易出错(特别是因为我实际上有4个函数并且将执行上述4次)。
保存大型数据集上的函数映射结果必定是一个常见问题,但我无法找到解决这个问题的方法。
有一些关于添加进度条到地图的讨论,但我认为它没有实现。但是,On the issue thread,jtrecenti发布了一些使用progress
包为map
添加进度条的代码。下面的示例有效,但我不确定它是否适用于您的代码:
progressively <- function(.f, .n, ...) {
pb <- progress::progress_bar$new(total = .n, ...)
function(...) {
pb$tick()
.f(...)
}
}
input <- 1:5
fun <- function(x) {
Sys.sleep(.2)
sample(x)
}
progress_fun <- progressively(fun, length(input))
purrr::map(input, progress_fun)
这会在运行时显示进度条,然后返回:
[[1]]
[1] 1
[[2]]
[1] 1 2
[[3]]
[1] 3 1 2
[[4]]
[1] 2 1 3 4
[[5]]
[1] 5 1 4 3 2