R语言使用rvest爬取网页表格失败(疑似iframe问题)如何解决
你对问题成因的判断有误,目标站点的排行榜表格并非通过iframe嵌入,而是基于React框架在客户端通过JavaScript动态渲染生成。rvest的read_html()函数仅能抓取服务端初始返回的静态HTML源码,不会执行页面内的JavaScript逻辑,因此无法获取JS执行完成后才生成的表格节点。
可以通过简单操作验证:在浏览器中禁用JavaScript后访问目标页面,表格区域为空白,且页面源码中不存在对应iframe标签。
另外你原有代码存在CSS选择器书写错误:选择器.#stats-tables-container-ID属于非法写法,id选择器前不需要加类选择器标识.,即便静态页面存在对应节点,该选择器也无法匹配到目标元素。
方案1:通过支持JS渲染的工具抓取页面
使用可驱动无头浏览器、自动执行页面JS的R包获取渲染完成后的完整DOM,再用rvest解析即可,推荐用chromote包(不需要手动装Selenium环境,依赖更少)。
实现代码如下:
# 首次使用先安装依赖 install.packages(c("rvest", "tidyverse", "chromote")) # 加载包 library(rvest) library(tidyverse) library(chromote) # 初始化无头浏览器会话 chrome_session <- ChromoteSession$new() # 跳转至目标页面 chrome_session$Page$navigate("https://u.gg/lol/top-lane-tier-list?rank=iron") # 等待表格节点加载完成,超时时间设为10秒 chrome_session$waitFor(".ugg-table-2", timeout = 10000) # 提取渲染完成后的完整页面HTML rendered_html <- chrome_session$Runtime$evaluate( "document.documentElement.outerHTML" )$result$value %>% read_html() # 提取目标元素 patch <- html_node(rendered_html, "#stats-tables-container-ID > div.title-header > h1 > div") %>% html_text() rank <- html_node(rendered_html, ".rank-option") %>% html_text() # 提取目标表格 tier_table <- html_node(rendered_html, ".content-section.ReactTable.ugg-table-2.tier-list") %>% html_table()
方案2:直接调用站点后端API(效率更高)
u.gg的表格数据是页面加载后通过异步接口请求获取的结构化JSON数据,不需要解析HTML。你可以打开浏览器开发者工具,切换到「网络」面板,筛选XHR/ Fetch类型请求,找到返回英雄梯队数据的接口,直接用httr包构造请求获取JSON格式的原始数据,解析后即可直接使用,这种方法抓取速度更快,也不容易受前端页面结构变动影响。
如果后续爬取时确实遇到iframe嵌入的内容,不需要猜源地址:打开浏览器开发者工具的「元素」面板,全局搜索<iframe标签,查看标签上的src属性值即为嵌入页面的地址;如果src是相对路径,拼接主页面的域名即可得到完整可访问的URL。
内容的提问来源于stack exchange,提问作者Adrien Mierop

