使用rvest网页抓取时链接不完整及编码适配问题求助
解决网页表格爬取的编码适配与数据合并问题
一、编码问题的根源
你遇到的并非单纯编码问题——硬指定encoding="latin1"会强制用单一编码解析所有页面,但不同年份的页面可能返回不同编码格式(比如部分旧页面用UTF-8,部分用latin1),强制指定反而会导致解析错误,无法识别目标表格。read_html本身具备自动检测编码的能力,无需硬编码指定。
二、修正后的完整爬取代码
以下代码解决了编码适配、URL构造错误、数据合并效率低的问题,同时自动添加年月信息列:
library(rvest) library(dplyr) # 定义要爬取的年份和月份范围 yr_list <- seq(2019, 2020) mes_list <- seq(1, 12) # 用列表存储各年月的表格,避免循环rbind的低效率 table_collection <- list() for (yr in yr_list) { for (mes in mes_list) { # 用sprintf简洁构造URL,避免原代码的语法错误 target_url <- sprintf( "http://transparencia.uantof.cl/index.php?action=plantillas_selec_archivo&ig=21&m=%d&a=%d", mes, yr ) # 读取HTML,让read_html自动识别编码 page_content <- read_html(target_url) # 提取页面中的表格,header=TRUE确保表头正确识别 page_tables <- html_table(page_content, header = TRUE) # 检查是否存在有效表格,避免空页面报错 if (length(page_tables) >= 1) { target_table <- as.data.frame(page_tables[[1]]) # 添加年月标识列 target_table$年份 <- yr target_table$月份 <- mes # 将表格存入列表,用年月作为命名便于排查 table_collection[[paste0(yr, "_", mes)]] <- target_table # 打印爬取进度 cat(sprintf("已完成 %d年%d月 数据爬取\n", yr, mes)) } else { cat(sprintf("%d年%d月 无有效表格或页面不存在\n", yr, mes)) } } } # 合并所有表格(dplyr::bind_rows比基础R的do.call(rbind, ...)更稳定) combined_data <- bind_rows(table_collection) # 查看合并后的数据结构 str(combined_data)
三、关键优化点说明
- 编码自动适配:移除
encoding="latin1"参数,让read_html根据HTTP响应头或页面元标签自动识别编码,适配不同年份的页面。 - URL构造修正:用
sprintf替代原代码错误的paste写法,避免语法错误,同时让URL构造更清晰。 - 高效数据合并:用列表存储每个表格,最后一次性合并,比循环中反复
rbind效率提升数倍,尤其适合大数据量场景。 - 错误容错:增加表格存在性判断,避免因空页面或无表格导致的代码中断。
- 年月信息添加:为每个表格手动添加
年份和月份列,满足后续数据溯源需求。
四、额外建议
- 如果部分页面的目标表格不是第一个,可以通过浏览器开发者工具查看表格的CSS类或ID,用
html_nodes(page_content, "table.target-class") %>% html_table()精准提取,避免拿到无关表格。 - 可在循环中添加
Sys.sleep(1),控制请求频率,避免因频繁访问被网站封禁。
内容的提问来源于stack exchange,提问作者Maria Palma
相关产品推荐
相关产品推荐

