使用rvest爬虫返回character(empty)的问题求助
问题排查:R语言rvest爬取Arbetsformedlingen统计文件失败
问题描述
更换目标URL与CSS选择器后,使用R语言rvest包爬取网站
https://arbetsformedlingen.se/statistik/statistik-om-varsel时,link对象返回character(empty),无法获取'Antal varsel och berörda personer'板块中'Tillfällig statistik per län och bransch, januari-april 2023'文件的下载链接。
当前使用的R代码:
library(tidyverse) library(stringr) library(rio) #import-function library(rvest) #read_html()-function # Link to target site url <- "https://arbetsformedlingen.se/statistik/statistik-om-varsel" ## Parsa HTML-innehållet doc <- read_html(url) ## Hitta data som du vill skrapa ### Select CSS locator link <- html_elements(doc, css = '#cardContainer > app-downloads:nth-child(3) > div > div:nth-child(3) > div > digi-link-internal > digi-link > a') %>% html_attr("href") # Create URL for file download url2 <- "https://arbetsformedlingen.se" full_link <- sprintf("%s%s", url2, link) # Get and save file locally td = tempdir() # skapa temporär mapp varsel_fil <- tempfile(tmpdir=td, fileext = ".xlsx") download.file(full_link, destfile = varsel_fil, mode = "wb") # Read file into a df df_imported <- import(varsel_fil, which=1) #which - välj 'sheet'-nr
此前使用的CSS选择器为:#svid12_142311c317a09e842af1a94 > div.sv-text-portlet-content > p:nth-child(20) > strong > a,新旧选择器结构差异大,无法定位目标元素。
问题原因
- 动态内容渲染限制:当前选择器包含
app-downloads、digi-link-internal这类自定义标签,属于前端框架(如Vue/React)生成的动态组件。rvest的read_html()仅能抓取服务器返回的静态HTML,无法识别JS动态加载渲染的DOM元素,因此找不到对应节点。 - CSS选择器依赖不稳定结构:旧选择器基于旧页面的静态DOM层级编写,新页面改用动态组件后,DOM结构完全重构,旧选择器直接失效;新选择器又因动态渲染无法被静态抓取识别。
解决方案
方案1:轻量文本匹配定位(推荐)
放弃依赖DOM结构的复杂选择器,通过目标文件名的文本匹配筛选链接,避免动态内容影响:
library(tidyverse) library(rvest) library(rio) # 目标网站URL url <- "https://arbetsformedlingen.se/statistik/statistik-om-varsel" # 读取静态HTML doc <- read_html(url) # 通过目标文件名文本匹配定位下载链接 target_file <- "Tillfällig statistik per län och bransch, januari-april 2023" link <- doc %>% html_elements("a") %>% filter(html_text(.) %>% str_detect(target_file)) %>% html_attr("href") # 拼接完整下载URL full_link <- paste0("https://arbetsformedlingen.se", link) # 下载并读取文件 td <- tempdir() varsel_fil <- tempfile(tmpdir = td, fileext = ".xlsx") download.file(full_link, destfile = varsel_fil, mode = "wb") df_imported <- import(varsel_fil, which = 1)
方案2:处理动态内容(RSelenium)
如果页面后续完全改为动态渲染,可使用RSelenium模拟浏览器加载动态内容:
library(tidyverse) library(RSelenium) library(rio) # 启动Chrome浏览器驱动(需提前安装对应版本的ChromeDriver) driver <- rsDriver(browser = "chrome", port = 4567L) remDr <- driver[["client"]] # 访问目标页面 remDr$navigate("https://arbetsformedlingen.se/statistik/statistik-om-varsel") # 等待动态内容加载后抓取链接 link <- remDr$findElement(using = "css selector", value = "#cardContainer > app-downloads:nth-child(3) > div > div:nth-child(3) > div > digi-link-internal > digi-link > a")$getElementAttribute("href")[[1]] # 关闭浏览器驱动 remDr$close() driver$server$stop() # 下载并读取文件 full_link <- paste0("https://arbetsformedlingen.se", link) td <- tempdir() varsel_fil <- tempfile(tmpdir = td, fileext = ".xlsx") download.file(full_link, destfile = varsel_fil, mode = "wb") df_imported <- import(varsel_fil, which = 1)
内容的提问来源于stack exchange,提问作者Christian
相关产品推荐
相关产品推荐

