使用RVest爬取网页数据返回空变量的问题求助
问题根因
你写的所有选择器返回空结果,和URL查询参数没有关系,核心问题有两个:
- 这个Vanguard的产品页是JavaScript前端动态渲染的,
rvest::read_html()只能拿到服务器初始返回的静态HTML源码,你在浏览器开发者工具Elements面板看到的<ukd-app>、<ukd-distributions>这类自定义组件标签,都是前端框架跑完JS之后才生成的,初始静态源码里根本不存在这些节点,选择器当然匹配不到内容。 - 你用的从
/html根节点一路写到底的绝对XPath是浏览器自动生成的,本身容错性极差,哪怕是静态页面,只要DOM层级有一点变动(比如加个广告位、改个布局)就会直接失效,完全不推荐在爬虫里用这种写法。
可落地的解决方法
方案1:直接调用页面前端拉数据的后端接口(最稳、速度最快)
所有前端渲染的页面对应的数据,本质都是前端从后端接口拉取的,直接抓接口比解析HTML简单很多:
- 打开目标页面按F12调出开发者工具,切到Network面板,筛选「Fetch/XHR」类型的请求
- 刷新页面,在请求列表里找名称带
distributions、fund-data、quote的请求,挨个看响应内容,就能找到返回收益率、分红数据的接口,返回的一般是结构化JSON - 直接用
httr2调用这个接口,解析JSON就能直接拿到你要的收益率值,不需要写任何HTML选择器。
参考代码:
library(httr2) # 替换成你在Network面板找到的实际接口地址 fund_api <- "页面实际调用的后端数据接口路径" data_resp <- request(fund_api) %>% # 加常规请求头模拟普通浏览器访问,避免被反爬拦截 req_headers( `User-Agent` = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36", Referer = "目标站点首页地址" ) %>% req_perform() # 解析JSON,按接口返回的结构提取对应收益率字段即可 fund_info <- data_resp %>% resp_body_json() yield_val <- fund_info$对应字段路径
方案2:用支持JS渲染的工具拿到完整渲染后的DOM
如果找不到对应接口,可以用chromote包调用本地的Chrome浏览器,等页面把所有DOM都渲染完成之后再提取内容,这时候选择器就能正常匹配到节点。
参考代码:
library(rvest) library(chromote) # 启动无头Chrome会话 chrome_session <- ChromoteSession$new() # 跳转目标页面,等待渲染完成 chrome_session$Page$navigate("目标页面地址") Sys.sleep(3) # 预留3秒加载时间,也可以用等待指定元素出现的方法替代固定等待 # 拿到渲染完成后的完整HTML源码 rendered_html <- chrome_session$Runtime$evaluate("document.documentElement.outerHTML")$result$value page <- read_html(rendered_html) # 用相对路径+文本匹配的方式写选择器,容错性更高 yield_val <- page %>% html_element(xpath = "//*[contains(normalize-space(text()), 'Yield As at close')]/following-sibling::*[contains(@class, 'data')]") %>% html_text2()
额外提示
- 写选择器尽量用文本匹配、相对定位的写法,不要用浏览器生成的全路径绝对XPath
- 如果接口请求被拦截,适当补全请求头、控制请求频率即可,不需要加特殊的查询参数
- 爬取时注意遵守目标站点的访问规则,不要高频请求给服务器造成压力
内容的提问来源于stack exchange,提问作者Robbo
相关产品推荐
相关产品推荐

