如何解决批量抓取数百个网页数据时遇到的HTTP error 504问题
报错原因
HTTP 504是网关超时错误,核心原因是短时间内请求频率过高,触发了目标网站的反爬限制或服务器资源不足无法响应请求。
最优解决方案
- 加入随机等待间隔
Sys.sleep()放在每次请求详情页的逻辑前即可,更推荐用随机间隔代替固定时长,避免固定请求频率被反爬策略识别,通常设置1-3秒的随机等待就能解决大部分超时问题。 - 增加错误捕获机制
用purrr::possibly包装请求逻辑,单次请求失败时返回NA,不会中断整个爬取任务,后续可单独重跑失败的请求。 - 增量分块存储
每爬取固定数量的页面就存储一次临时结果,就算程序意外中断也不需要从头开始跑。 - 模拟浏览器请求头
替换rvest默认的爬虫UA为普通浏览器的UA,降低被识别为爬虫的概率。
修改后的代码示例
# 加载额外需要的包 library(httr) library(stringr) # 定义带错误处理的日期提取函数 safe_get_date <- possibly(function(link) { # 每次请求前随机等待1-3秒 Sys.sleep(runif(1, min = 1, max = 3)) # 发送带模拟浏览器标识的请求 resp <- GET(link, user_agent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36")) # 仅当请求正常时解析内容 if (status_code(resp) == 200) { resp %>% read_html() %>% html_nodes(".date-p span") %>% html_text() %>% paste(collapse = " ") } else { NA_character_ } }, otherwise = NA_character_) # ---------------- 可选分块爬取逻辑 ---------------- # 把所有链接按每20个分为一组 chunk_size <- 20 link_chunks <- split(duma_votes_data$link, ceiling(seq_along(duma_votes_data$link)/chunk_size)) date_results <- list() for (i in seq_along(link_chunks)) { cat("正在抓取第", i, "组,共", length(link_chunks), "组\n") date_results[[i]] <- map_chr(link_chunks[[i]], safe_get_date) # 每爬完一组存一次临时文件,避免数据丢失 saveRDS(date_results, "duma_date_temp.rds") } # 合并结果到原数据框 duma_votes_data$date <- unlist(date_results)
补充说明
如果运行后仍有少量返回NA的记录,筛选出对应链接单独重跑即可,不需要重新爬取全部页面。如果还是频繁出现超时,可适当调长runif的等待时长范围。
内容的提问来源于stack exchange,提问作者w5698
相关产品推荐
相关产品推荐

