如何用rvest抓取IMDB动态加载列表的全部内容?
解决IMDB动态加载内容的抓取问题
你遇到的核心问题是:IMDB的“50 more”按钮通过JavaScript异步加载内容,而rvest只能抓取页面初始的静态HTML,重新运行代码只会再次请求初始页面,自然拿不到动态加载的后续内容。下面提供两种可行的解决方案:
方法一:构造分页URL(推荐,高效无浏览器依赖)
IMDB搜索页面支持通过start参数指定起始条目位置,每次默认加载50条内容。可以通过循环构造不同start值的URL,批量抓取所有内容。
代码实现
library(rvest) library(dplyr) # 基础URL模板,%d用于替换起始条目数 base_url <- "https://www.imdb.com/search/title/?title_type=feature&genres=crime&start=%d&ref_=adv_nxt" # 先获取总条目数(避免硬编码失效) initial_page <- read_html("https://www.imdb.com/search/title/?title_type=feature&genres=crime") total_items_text <- initial_page |> html_nodes(".ipc-title__subtext") |> html_text() total_items <- as.numeric(gsub("[^0-9]", "", total_items_text)) # 提取数字 items_per_page <- 50 # 初始化结果容器 all_titles <- c() all_links <- c() # 循环抓取每一页 for (start in seq(1, total_items, by = items_per_page)) { current_url <- sprintf(base_url, start) page <- read_html(current_url) # 抓取标题和链接 titles <- page |> html_nodes(".ipc-title__text") |> html_text() links <- page |> html_nodes(".ipc-title-link-wrapper") |> html_attr("href") |> paste0("https://www.imdb.com", .) # 补全为绝对URL # 如果当前页无内容,提前终止循环 if (length(titles) == 0) break # 追加到结果 all_titles <- c(all_titles, titles) all_links <- c(all_links, links) # 延迟2秒,避免触发反爬机制 Sys.sleep(2) cat(sprintf("已抓取第 %d-%d 条内容\n", start, min(start + items_per_page - 1, total_items))) } # 整理为数据框 result_df <- tibble(标题 = all_titles, 链接 = all_links)
方法二:模拟浏览器点击加载(适合无分页参数的场景)
如果IMDB后续修改URL规则,无法通过参数分页,可以用RSelenium模拟真实浏览器操作,自动点击“50 more”按钮直到加载完所有内容。
代码实现
library(RSelenium) library(rvest) # 启动Chrome浏览器(需提前安装ChromeDriver并配置环境变量) driver <- rsDriver(browser = "chrome", port = 4567L) remDr <- driver[["client"]] # 打开目标页面 remDr$navigate("https://www.imdb.com/search/title/?title_type=feature&genres=crime") # 循环点击加载更多按钮 while(TRUE) { tryCatch({ # 定位“50 more”按钮(CSS选择器可能随IMDB页面更新变化,需按需调整) more_button <- remDr$findElement(using = "css selector", value = ".ipc-btn--primary.ipc-btn--single-padding.ipc-btn--center-align-content.ipc-btn--default-height.ipc-btn--core-base.ipc-btn--theme-base.ipc-btn--on-accent2") more_button$clickElement() Sys.sleep(3) # 等待内容加载完成 cat("已加载更多内容\n") }, error = function(e) { # 按钮不存在时,说明所有内容已加载完成 cat("所有内容加载完毕\n") break }) } # 获取完整页面源码并解析 page_source <- remDr$getPageSource()[[1]] page <- read_html(page_source) titles <- page |> html_nodes(".ipc-title__text") |> html_text() links <- page |> html_nodes(".ipc-title-link-wrapper") |> html_attr("href") |> paste0("https://www.imdb.com", .) # 关闭浏览器 remDr$close() driver$server$stop() # 整理为数据框 result_df <- tibble(标题 = titles, 链接 = links)
注意事项
- 反爬规避:IMDB会检测异常请求,务必添加
Sys.sleep()延迟,避免短时间内大量请求导致IP被封禁。 - 元素选择器更新:IMDB页面的CSS类名可能会更新,如果代码报错无法定位元素,需要用浏览器开发者工具重新获取最新的选择器。
- 验证码处理:如果使用模拟浏览器方法,遇到验证码时需要手动完成验证,再继续运行代码。
内容的提问来源于stack exchange,提问作者TomTe
相关产品推荐
相关产品推荐

