请求实现R语言下《Die Gartenlaube》全年份期刊内容的批量抓取方案
请求实现R语言下《Die Gartenlaube》全年份期刊内容的批量抓取方案
嘿Marco!你已经把单一年份的抓取逻辑跑通了,这一步超棒!现在要把这个能力扩展到所有年份对吧?我帮你把代码重构了一下,封装成可复用的函数,再加上批量处理的逻辑,这样就能轻松拿到所有年份的year-issue-title-text数据啦。
第一步:准备年份与期数的映射数据
首先把你提供的年份-期数表格先定义好,我们后面要用到它来对应每个年份的总期数:
# 定义年份与对应期数的数据框 year_issues <- structure( list( Year = c(1853, 1854, 1855, 1856, 1857, 1858, 1859, 1860, 1861, 1862, 1863, 1864, 1865, 1866, 1867, 1868, 1869, 1870, 1871, 1872, 1873, 1874, 1875, 1876, 1877, 1878, 1879, 1880, 1881, 1882, 1883, 1884, 1885, 1886, 1887, 1888, 1889, 1890, 1891, 1892, 1893, 1894, 1895, 1896, 1897, 1898, 1899), count = c(52L, 52L, 52L, 52L, 52L, 52L, 52L, 52L, 52L, 52L, 49L, 52L, 52L, 51L, 52L, 52L, 52L, 52L, 52L, 52L, 52L, 52L, 52L, 52L, 52L, 52L, 52L, 52L, 53L, 52L, 52L, 52L, 52L, 52L, 53L, 52L, 52L, 28L, 52L, 28L, 52L, 52L, 52L, 52L, 53L, 28L, 28L) ), class = c("tbl_df", "tbl", "data.frame"), row.names = c(NA, -47L) )
第二步:封装单年份抓取函数
我把你原来的单年份抓取逻辑封装成了一个函数,这样不管哪个年份,只要传入年份和期数就能直接调用,还加了边界处理避免报错:
library(rvest) library(dplyr) library(tibble) # 定义抓取单一年份期刊的函数 scrape_gartenlaube_year <- function(target_year, num_issues) { # 初始化存储列表 year_data <- list() for(i in 1:num_issues){ # 构造当期URL url <- paste0("https://de.wikisource.org/wiki/Die_Gartenlaube_(", target_year, ")/Heft_", i) # 读取HTML文档 html_document <- read_html(url) # 提取标题(去掉第一个无关标题) title <- html_document %>% html_nodes("h2") %>% html_text() %>% .[-1] # 提取对应标题的正文内容 text <- character() # 处理标题数量不足的边界情况,避免循环报错 if(length(title) >= 2){ for(j in 1:(length(title)-2)){ # 用XPath定位两个标题之间的段落 txt <- html_document %>% html_nodes(xpath = paste0("//p[preceding-sibling::h2[. = '", title[j], "'] and following-sibling::h2[. = '", title[j+1], "']]")) %>% html_text() # 合并段落文本 text[j] <- paste(txt, collapse = '') } } # 对齐标题和文本长度(处理长度不一致的情况) n <- max(length(title), length(text)) length(title) <- n length(text) <- n # 组合当期数据,添加期数列 issue_df <- tibble(title = title, text = text, issue = i) year_data[[i]] <- issue_df } # 合并全年数据,添加年份列 year_full_df <- bind_rows(year_data) %>% mutate(year = target_year) return(year_full_df) }
第三步:批量抓取所有年份
这里给你两种方案,选你习惯的就行:
方案1:传统for循环(直观易调试)
all_gartenlaube_data <- tibble() for(row in 1:nrow(year_issues)){ current_year <- year_issues$Year[row] current_num_issues <- year_issues$count[row] # 打印抓取进度,方便追踪 cat("正在抓取", current_year, "年的内容,共", current_num_issues, "期...\n") year_df <- scrape_gartenlaube_year(current_year, current_num_issues) all_gartenlaube_data <- bind_rows(all_gartenlaube_data, year_df) }
方案2:函数式写法(更简洁)
用purrr包的map2_dfr函数,直接把年份和期数配对传入函数,自动合并结果:
library(purrr) all_gartenlaube_data <- map2_dfr( .x = year_issues$Year, .y = year_issues$count, .f = ~{ cat("正在抓取", .x, "年的内容,共", .y, "期...\n") scrape_gartenlaube_year(.x, .y) } )
最后验证结果
跑完之后,all_gartenlaube_data就是你想要的完整数据框啦,包含year、issue、title、text四个字段,和你1853年的结果格式完全一致,只是覆盖了所有年份。
备注:内容来源于stack exchange,提问作者Marco
相关产品推荐
相关产品推荐

