使用R rvest爬取IMDB Top250时html_element返回NA的问题排查
问题分析与修正方案
核心错误点
容器选择范围过大:你用
html_elements(page, 'li')选中了页面所有<li>元素,但页面里大部分li不是电影条目,后续在这些无关元素上调用html_element自然找不到目标子节点,返回NA;用html_elements能得到结果只是巧合——刚好所有电影条目的h3被包含在收集到的所有h3里,但逻辑上是错误的。依赖动态类名:你用的
.sc-b0691f29-7 hrgukm cli-title-metadata是IMDB动态生成的随机类名,这类类名会频繁更换,导致选择器直接失效,无法定位到元数据容器。
修正后的代码
library(tidyverse) library(rvest) # 读取页面 page <- read_html('https://www.imdb.com/chart/top/?ref_=nv_mv_250') # 定位每个电影的条目容器(用稳定的语义化类,避免动态类名问题) movie_items <- html_elements(page, 'li.ipc-metadata-list-summary-item') # 提取电影标题:先定位到标题元素,再清理序号前缀 titles <- movie_items %>% html_element('h3.ipc-title__text') %>% html_text2() %>% str_remove('^[0-9]+\\. ') # 提取年份、时长、分级:先定位元数据容器,再拆分文本 metadata <- movie_items %>% html_element('div.ipc-title-metadata') %>% html_text2() %>% str_split_fixed('\\|', n = 3) %>% as_tibble() %>% rename(year = V1, runtime = V2, rating = V3) %>% mutate(across(everything(), str_trim)) # 合并成完整数据集 top250_movies <- tibble(title = titles) %>% bind_cols(metadata)
关键说明
- 优先用语义化选择器:选择
ipc-metadata-list-summary-item(电影条目容器)、ipc-title__text(标题)、ipc-title-metadata(元数据容器)这类描述功能的类名,它们比动态生成的随机类名稳定得多,不会轻易随页面更新失效。 - 精准定位容器:先找到每个电影对应的独立容器,再在容器内提取子元素,确保每一条数据都对应正确的电影,避免无关元素干扰。
内容的提问来源于stack exchange,提问作者Théodore Targerian
相关产品推荐
相关产品推荐

