使用rvest批量爬取HTML表格遇迭代错误,求排查修复
错误原因分析
url_data赋值冗余且易引发问题
你给url_data赋值时嵌套了print()函数,虽然print()会返回字符串,但这是多余操作,可能干扰后续网页读取的稳定性。write.csv位置错误导致df被置空
管道末尾直接调用write.csv(df, "immigrationStatistics.csv"),但write.csv的返回值是NULL,这会让每次循环里的df都被覆盖成空值,后续循环或最后调用view(df)自然会报错。数据未累积,CSV被重复覆盖
每次循环都直接写入同一个CSV文件,会覆盖之前爬取的数据,最终只能得到最后一天的结果,完全达不到批量爬取的目的。日期逻辑与单日代码不一致
单日代码中date直接使用目标日期,但迭代代码写成了date = theDate - 1,会导致日期和对应数据不匹配。
修复后的代码
library(rvest) library(dplyr) library(tidyverse) # 定义日期范围 start <- as.Date("01-09-22", format = "%d-%m-%y") end <- as.Date("30-09-22", format = "%d-%m-%y") # 定义表头 prefixes <- c("arr", "dep") cols <- c("Hong Kong Residents", "Mainland Visitors", "Other Visitors", "Total") headers <- c("Control_Point", crossing(prefixes, cols) %>% unite("headers", 1:2, remove = T) %>% unlist() %>% unname()) # 初始化空数据框用于累积所有数据 all_df <- tibble() theDate <- start while (theDate <= end) { # 生成URL并单独打印 url_data <- paste0("https://www.immd.gov.hk/eng/stat_", format(theDate, "%Y%m%d"), ".html") print(url_data) # 错误处理:避免单页爬取失败中断整个流程 tryCatch({ # 读取网页并提取数据 rows <- read_html(url_data) %>% html_elements(".table-passengerTrafficStat tbody tr") daily_df <- map_dfr(rows, function(x) { x %>% html_elements("td[headers]") %>% set_names(headers) %>% html_text() }) %>% filter(Control_Point %in% c("Airport")) %>% mutate(across(c(-1), ~ str_replace(.x, ",", "") %>% as.integer())) %>% mutate(date = theDate) # 修正日期逻辑,和单日代码保持一致 # 将单日数据追加到总数据框 all_df <- bind_rows(all_df, daily_df) }, error = function(e) { message(paste("爬取", theDate, "数据失败:", e$message)) }) theDate <- theDate + 1 } # 所有数据爬取完成后统一写入CSV write.csv(all_df, "immigrationStatistics.csv", row.names = FALSE) # 查看最终结果 view(all_df)
修复说明
- 拆分
print()与url_data赋值:单独打印URL,确保url_data是纯净的网页链接,避免潜在干扰。 - 添加数据累积逻辑:初始化空数据框
all_df,每次循环将单日数据追加进去,彻底解决数据被覆盖的问题。 - 调整
write.csv执行时机:所有循环结束后统一写入CSV,确保所有爬取到的数据都被保存。 - 增加错误捕获机制:用
tryCatch包裹爬取逻辑,某一天数据爬取失败时会跳过并提示错误,不会中断整个批量任务。 - 统一日期逻辑:将
date = theDate -1改为date = theDate,和单日代码逻辑对齐,保证日期与数据对应准确。
内容的提问来源于stack exchange,提问作者ronzenith
相关产品推荐
相关产品推荐

