使用R语言批量下载SSOAR平台PDF时遇下载失败问题
批量下载SSOAR资源库PDF文件失败问题
问题描述
- 需求:从SSOAR资源库的筛选结果中,批量下载约1200个2000-2022年《Historical Social Research》期刊的PDF文件
- 现有代码问题:要么无法下载文件,要么每次仅下载一篇且覆盖之前的文件
- 运行警告:出现50+条警告,提示URL对应的目标文件名包含无效参数、无法打开文件,且下载存在非零退出状态
原代码如下:
library(tidyverse) library(rvest) url <- "https://www.ssoar.info/ssoar/discover?scope=/&sort_by=score&order=desc&rpp=100&filtertype_0=dateIssued&filter_relational_operator_0=equals&filter_0=%5B2000+TO+2022%5D&filtertype=journal&filter_relational_operator=equals&filter=Historical+Social+Research" page <- read_html(url) urls_pdf <- page %>% html_elements("a") %>% html_attr("href") %>% str_subset("\\.pdf") urls_pdf[1:100] %>% walk2(basename(.), download.file, mode = "wb") dir(pattern = "\\.pdf")
解决方案
1. 核心问题分析
- 文件名非法:
basename(urls_pdf)会保留URL中的查询参数(比如?sequence=1),这些参数包含?等系统不允许的文件名字符,导致无法创建文件 - 未处理分页:原代码仅爬取第一页的100条链接,无法获取全部1200个文件的URL
- 无错误处理:单个下载失败会抛出警告,且可能中断后续任务
2. 修改后的代码
library(tidyverse) library(rvest) # 基础URL模板,替换page参数实现分页 base_url <- "https://www.ssoar.info/ssoar/discover?scope=/&sort_by=score&order=desc&rpp=100&filtertype_0=dateIssued&filter_relational_operator_0=equals&filter_0=%5B2000+TO+2022%5D&filtertype=journal&filter_relational_operator=equals&filter=Historical+Social+Research&page=" # 定义获取单页PDF链接的函数 get_page_pdf_urls <- function(page_num) { page_url <- paste0(base_url, page_num) page <- read_html(page_url) page %>% html_elements("a[href$='.pdf']") %>% # 更精准匹配PDF链接 html_attr("href") %>% str_remove("\\?.*$") %>% # 移除URL中?及之后的查询参数 str_replace("^/", "https://www.ssoar.info/") # 补全相对URL为绝对URL } # 获取所有分页的PDF链接(1200个文件需要12页) all_pdf_urls <- map(1:12, get_page_pdf_urls) %>% flatten_chr() # 生成合法的唯一文件名 pdf_filenames <- all_pdf_urls %>% basename() %>% # 处理可能的重复文件名,添加序号后缀 make.unique(sep = "_") # 定义带错误处理的下载函数 safe_download <- possibly(function(url, filename) { download.file(url, filename, mode = "wb", quiet = TRUE) }, otherwise = NULL) # 批量下载 walk2(all_pdf_urls, pdf_filenames, safe_download) # 查看已下载的PDF文件 dir(pattern = "\\.pdf")
3. 关键改进点
- 清理文件名:用
str_remove("\\?.*$")删掉URL中的查询参数,确保文件名合法 - 分页遍历:通过
base_url拼接page参数,遍历1-12页获取全部链接 - 补全绝对URL:原页面的PDF链接是相对路径,用
str_replace补全为完整URL - 错误处理:
possibly()函数让单个下载失败时不中断整个批量任务 - 避免覆盖:
make.unique()给重复文件名添加序号后缀,防止文件被覆盖
内容的提问来源于stack exchange,提问作者Bryan
相关产品推荐
相关产品推荐

