如何用R循环抓取IMDB多页动作电影数据并整合为Data Frame
批量抓取IMDB动作电影数据(多页合并)
问题背景
已经能用R代码抓取IMDB动作电影第一页的50条数据,现在要改成循环抓取指定页数(比如200页),并把所有数据合并成一个Data Frame。
解决步骤
1. 封装单页抓取逻辑成函数
把原来的单页抓取代码改成接受start参数的函数——IMDB每页固定显示50条,第k页的start参数值是(k-1)*50 + 1,这样每次调用只需传入对应页的起始位置即可。
2. 生成待抓取的起始位置序列
比如要抓200页,起始位置就是1、51、101……一直到9951(计算方式:(200-1)*50 +1 = 9951)。
3. 批量抓取并合并数据
用purrr::map_dfr批量调用抓取函数,它会自动把所有页的结果合并成一个Data Frame。另外要加延迟(比如每次抓完等1-2秒),避免触发IMDB的反爬机制。
4. 异常处理(可选但推荐)
用purrr::possibly包装抓取函数,遇到个别页面抓取失败时,返回空数据框而非直接中断整个流程。
完整代码示例
library(rvest) library(purrr) library(dplyr) library(glue) # 封装单页抓取函数 scrape_imdb_page <- function(start) { # 构造目标页面URL url <- glue("https://www.imdb.com/search/title/?title_type=feature&num_votes=25000,&genres=action&sort=user_rating,desc&start={start}&ref_=adv_nxt") # 抓取页面内容 page <- read_html(url) # 提取数据并返回数据框 page %>% html_elements(".lister-item-content") %>% map_dfr(~ tibble( title = .x %>% html_element(".lister-item-header a") %>% html_text2(), year = .x %>% html_element(".text-muted.unbold") %>% html_text2(), certificate = .x %>% html_element(".certificate") %>% html_text2(), runtime = .x %>% html_element(".runtime") %>% html_text2(), genre = .x %>% html_element(".genre") %>% html_text2(), rating = .x %>% html_element(".ratings-imdb-rating strong") %>% html_text2(), metascore = .x %>% html_element(".ratings-metascore") %>% html_text2(), synopsis = .x %>% html_element(".ratings-bar+ .text-muted") %>% html_text2(), director = .x %>% html_element(".text-muted+ p a:nth-child(1)") %>% html_text2(), votes = .x %>% html_element(".sort-num_votes-visible span:nth-child(2)") %>% html_text2(), gross = .x %>% html_element(".ghost~ .text-muted+ span") %>% html_text2(), cast1 = .x %>% html_element('a[href*="adv_li_st_0"]') %>% html_text2(), cast2 = .x %>% html_element('a[href*="adv_li_st_1"]') %>% html_text2(), cast3 = .x %>% html_element('a[href*="adv_li_st_2"]') %>% html_text2(), cast4 = .x %>% html_element('a[href*="adv_li_st_3"]') %>% html_text2() )) } # 生成200页对应的起始位置序列 start_positions <- seq(from = 1, to = (200-1)*50 +1, by = 50) # 包装函数,添加异常容错 safe_scrape <- possibly(scrape_imdb_page, otherwise = tibble()) # 批量抓取数据,带进度提示和延迟 all_movies <- map_dfr(start_positions, function(pos) { cat("正在抓取起始位置:", pos, "\n") # 打印当前进度 result <- safe_scrape(pos) Sys.sleep(1) # 延迟1秒,降低被反爬拦截的概率 result }) # 查看最终数据情况 dim(all_movies) head(all_movies)
注意事项
- 先安装所需依赖包:
install.packages(c("rvest", "purrr", "dplyr", "glue")) - 延迟时间可根据实际情况调整,比如改成2秒会更稳妥
- 如果出现大量页面抓取失败,大概率是被IMDB限制了,可以尝试增加延迟或更换网络环境
内容的提问来源于stack exchange,提问作者Shashivydyula
相关产品推荐
相关产品推荐

