求助:用R的rvest包批量下载指定网页2023文件夹文件失败
问题分析与解决方案
你的代码核心问题是HTML节点选择错误,导致未抓取到正确的文件下载链接,最终下载的是网页而非目标ZIP文件。以下是具体修正步骤:
问题点拆解
- 错误使用
context-menu-list-context-menu-root作为选择器,该节点并非文件链接所在标签 - 链接拼接逻辑有误,未正确处理相对路径
- 未验证抓取到的URL有效性,导致下载错误内容
修正后的代码
1. 优先抓取2023年文件
library(rvest) library(dplyr) # 目标年份(优先2023) target_year <- 2023 base_url <- "https://www.coes.org.pe/Portal/PostOperacion/Reportes/Ieod" year_path <- sprintf("Post%%20Operaci%%C3%%B3n/Reportes/IEOD/%d/", target_year) page_url <- sprintf("%s?path=%s", base_url, URLencode(year_path, reserved = TRUE)) # 读取页面并抓取正确的文件链接 page <- read_html(page_url) # 关键:选择文件列表中的a标签(匹配页面实际结构) urls <- page %>% html_nodes(".file-item a") %>% html_attr("href") %>% # 筛选.htm结尾的文件链接 grep("\\.htm$", ., value = TRUE) %>% # 替换后缀为.zip sub("\\.htm$", ".zip", .) %>% # 拼接完整URL paste0(base_url, .) # 创建存储目录 dir <- file.path(tempdir(), "COES") if (!dir.exists(dir)) dir.create(dir) # 批量下载文件 if (length(urls) > 0) { lapply(urls, function(url) { dest_file <- file.path(dir, basename(url)) download.file(url, dest_file, mode = "wb") # 二进制模式避免ZIP损坏 cat(sprintf("已下载:%s\n", basename(url))) }) # 查看下载结果 cat("\n下载的文件列表:\n") print(list.files(dir)) } else { cat("未找到任何可下载的文件链接,请检查页面结构是否变化。") }
2. 扩展抓取2021-2023年所有文件
如果需要批量处理三年的文件,可添加循环:
library(rvest) library(dplyr) base_url <- "https://www.coes.org.pe/Portal/PostOperacion/Reportes/Ieod" target_years <- 2021:2023 dir <- file.path(tempdir(), "COES") if (!dir.exists(dir)) dir.create(dir) for (year in target_years) { cat(sprintf("\n开始处理%d年文件...\n", year)) year_path <- sprintf("Post%%20Operaci%%C3%%B3n/Reportes/IEOD/%d/", year) page_url <- sprintf("%s?path=%s", base_url, URLencode(year_path, reserved = TRUE)) page <- read_html(page_url) urls <- page %>% html_nodes(".file-item a") %>% html_attr("href") %>% grep("\\.htm$", ., value = TRUE) %>% sub("\\.htm$", ".zip", .) %>% paste0(base_url, .) if (length(urls) > 0) { lapply(urls, function(url) { dest_file <- file.path(dir, sprintf("%d_%s", year, basename(url))) download.file(url, dest_file, mode = "wb") cat(sprintf("已下载:%s\n", basename(url))) }) } else { cat(sprintf("%d年未找到可下载文件\n", year)) } } # 查看所有下载文件 cat("\n所有下载文件:\n") print(list.files(dir))
关键说明
- 节点选择器:
.file-item a是基于目标页面实际HTML结构设置的,若页面后续更新,需重新检查并调整选择器 - 二进制下载:添加
mode = "wb"确保ZIP文件以二进制模式下载,避免文件损坏 - URL编码:使用
URLencode处理路径中的特殊字符(如西班牙语重音),保证页面URL有效
内容的提问来源于stack exchange,提问作者Ahria Mathos
相关产品推荐
相关产品推荐

