R中download.file()返回403 Forbidden错误,网站加验证后代码失效求解决
网站新增用户验证后的PDF下载解决方案
针对你遇到的网站新增用户验证导致原R下载代码失效的问题,给你几个可行的解决方向:
1. 模拟带会话的HTTP请求(推荐用httr2包)
普通的download.file无法维持会话状态,而网站验证通常依赖Cookie或会话标识。用httr2可以先建立会话,通过验证后再发起下载请求:
library(tidyverse) library(rvest) library(httr2) # 初始化会话,获取页面Cookie session <- request("https://burnsville.civicweb.net/filepro/documents/25657/") %>% req_perform() # 解析页面获取文件列表(和你原来的逻辑一致) page <- session %>% resp_body_html() df <- tibble( names1 = page %>% html_nodes(".document-link") %>% html_text2() %>% str_remove_all("\\r") %>% str_squish(), links = page %>% html_nodes(".document-link") %>% html_attr("href") %>% paste0("https://burnsville.civicweb.net", .) ) # 循环下载,复用会话 walk2(df$links, df$names1, function(link, name) { tryCatch({ request(link) %>% req_headers( "User-Agent" = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36", "Referer" = "https://burnsville.civicweb.net/filepro/documents/25657/" ) %>% req_cookies(resp_cookies(session)) %>% # 复用会话Cookie req_perform(path = paste0(name, ".pdf")) }, error = function(e) { message(paste("下载失败:", name, "错误信息:", e$message)) }) })
2. 使用无头浏览器处理交互验证
如果网站需要点击同意按钮、输入简单图形验证码等交互操作,用RSelenium可以模拟真实浏览器行为(需先安装对应浏览器驱动,比如ChromeDriver):
library(RSelenium) library(tidyverse) library(rvest) # 启动无头Chrome driver <- rsDriver(browser = "chrome", chromever = "latest", extraCapabilities = list( chromeOptions = list(args = list("--headless=new")) )) remDr <- driver[["client"]] # 打开目标页面,处理验证(根据实际页面调整选择器,比如点击同意按钮) remDr$navigate("https://burnsville.civicweb.net/filepro/documents/25657/") # 示例:若有同意按钮,取消注释下面一行 # remDr$findElement(using = "css selector", value = ".btn-accept")$clickElement() # 获取页面源码解析文件列表 page_source <- remDr$getPageSource()[[1]] %>% read_html() df <- tibble( names1 = page_source %>% html_nodes(".document-link") %>% html_text2() %>% str_remove_all("\\r") %>% str_squish(), links = page_source %>% html_nodes(".document-link") %>% html_attr("href") %>% paste0("https://burnsville.civicweb.net", .) ) # 循环下载,复用浏览器会话Cookie walk2(df$links, df$names1, function(link, name) { tryCatch({ request(link) %>% req_cookies(remDr$getAllCookies() %>% map_dfr(~list(name = .$name, value = .$value))) %>% req_perform(path = paste0(name, ".pdf")) Sys.sleep(1) # 避免请求过于频繁 }, error = function(e) { message(paste("下载失败:", name, "错误信息:", e$message)) }) }) # 关闭驱动 remDr$close() driver$server$stop()
3. 手动提取验证后的Cookie
如果验证是一次性的(比如登录后Cookie有效期较长),可以手动在浏览器中完成验证,再复制Cookie到代码中:
- 打开浏览器开发者工具(F12),切换到「网络」标签
- 完成验证后刷新页面,找到任意请求的Cookie内容
- 将Cookie添加到请求头,用
httr2发起下载请求
另外,你的原代码存在两个小问题:
map调用错误直接使用df$links和df$names1,应该用walk2配对链接与文件名for循环里的url变量未定义,需替换为循环变量i
内容的提问来源于stack exchange,提问作者scotiaboy
相关产品推荐
相关产品推荐

