R语言按日期序列循环爬取网页表格并存储的问题求助
R批量爬取日期维度数据修复方案
你原代码跑不通的核心原因有三个:一是请求体里的vfecha参数写死了固定日期,完全没关联你预设的fechas日期序列;二是文件名生成逻辑写的timestamp <- 1:seq_along(i)是无意义的动态序列,既没绑定索引也没绑定日期;三是没有容错和请求间隔,很容易跑一半中断或者被服务器拦截。
修正后完整代码
# 加载依赖 library(httr) library(rvest) library(janitor) library(dplyr) library(purrr) # 固定配置项 headers <- c("Content-Type" = "application/x-www-form-urlencoded; charset=UTF-8") target_url <- "http://old.emmsa.com.pe/emmsa_spv/app/reportes/ajax/rpt07_gettable.php" # 替换成你自己的存储路径,注意路径末尾要加/ save_dir <- "c:/Users/.../Desktop/data/" # 自动创建不存在的存储目录,避免存文件时报路径错误 dir.create(save_dir, recursive = TRUE, showWarnings = FALSE) # 第一步:生成符合接口格式要求的日期序列 # 接口要求vfecha格式为「日/月/年」,例如22/06/2022 # 下面示例是生成2022年6月全月的日期,替换起止日期为你需要的范围即可 fechas <- seq.Date( from = as.Date("2022-06-01"), to = as.Date("2022-06-30"), by = "day" ) |> format("%d/%m/%Y") # 第二步:map方式批量爬取(你需要的map循环写法) # walk函数专门处理存文件这类无返回值的副作用操作,比普通map更适配 walk(fechas, function(current_date){ # 动态拼接当前日期对应的请求体 req_body <- paste0("vid_tipo=1&vprod=&vvari=&vfecha=", current_date) # 发请求,内置3次失败自动重试,避免网络波动中断任务 resp <- RETRY( verb = "POST", url = target_url, add_headers(.headers = headers), body = req_body, times = 3 ) # 解析页面表格 precios <- resp |> content() |> html_element(".timecard") |> html_table() |> row_to_names(1) |> clean_names() |> filter(producto != "") |> # 用across替代已过时的mutate_at,长期兼容性更好 mutate(across(matches("precio"), as.numeric)) |> as_tibble() # 生成符合命名要求的文件名:把日期里的/替换成-,适配Windows文件命名规则 file_suffix <- gsub("/", "-", current_date) save_path <- paste0(save_dir, "data_", file_suffix, ".rds") # 保存文件 saveRDS(precios, file = save_path) # 打印进度,方便看跑到哪了 cat("完成爬取:", current_date, " 保存路径:", save_path, "\n") # 加1秒请求间隔,避免请求太频繁触发反爬 Sys.sleep(1) }) # 如果习惯用基础for循环,用下面这段替换上面的walk部分即可 # for (current_date in fechas) { # req_body <- paste0("vid_tipo=1&vprod=&vvari=&vfecha=", current_date) # resp <- RETRY("POST", target_url, add_headers(.headers = headers), body = req_body, times = 3) # precios <- content(resp) |> html_element(".timecard") |> html_table() |> row_to_names(1) |> clean_names() |> filter(producto != "") |> mutate(across(matches("precio"), as.numeric)) |> as_tibble() # file_suffix <- gsub("/", "-", current_date) # save_path <- paste0(save_dir, "data_", file_suffix, ".rds") # saveRDS(precios, file = save_path) # cat("完成爬取:", current_date, "\n") # Sys.sleep(1) # }
对应问题说明
- 按日期序列爬取问题:每次循环都会动态把当前日期拼接到请求体的
vfecha参数上,每个日期对应一次独立请求,不会再重复爬取固定日期的数据 - 文件名嵌入日期问题:爬取到的日期是
22/06/2022格式,把斜杠替换为横杠(Windows系统文件名不允许出现/字符)后直接拼接到文件名中,就能生成你需要的data_22-06-2022.rds格式 - 请求参数绑定问题:没有用固定写死的请求体字符串,每次循环实时拼接当前日期到
vfecha参数位,和日期序列一一对应 - 爬取与存储优化建议:
- 用
httr::RETRY替代原生POST,遇到网络波动、服务器临时5xx错误会自动重试3次,不会因为单次请求失败中断整个批量任务 - 加1秒请求间隔,避免高频请求触发服务器反爬拦截
- 开头加了自动创建存储目录的代码,不用手动提前建文件夹,避免路径不存在报错
- 用
across替代已经进入生命周期末期的mutate_at,后续dplyr版本升级不会出现函数弃用警告 - 如果后续需要做全量数据分析,可以在爬取时把每个日期的结果存在同一个列表里,最后用
bind_rows()合并成一张总表,额外存一份总rds文件,不用后续逐个读取拼接
- 用
内容的提问来源于stack exchange,提问作者Carlos Garibotto
相关产品推荐
相关产品推荐

