You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

rvest循环爬取EDI数据集日期遇xml_find_all错误的解决方案

批量爬取EDI数据集起止日期的代码修正

问题背景

需要爬取EDI单个地点下147个数据集的起止日期,已能实现单个数据集的信息提取,但批量循环时抛出错误:

Error in UseMethod("xml_find_all") : no applicable method for 'xml_find_all' applied to an object of class "list"

错误原因

原循环存在两个核心问题:

  1. URL拼接时错误使用整个package_ids$PackageId向量,生成了所有URL的集合,再用map读取得到列表对象,但html_nodes仅支持单个HTML文档对象,无法直接处理列表。
  2. 日期提取的选择器未采用已验证的可靠写法。

修正后的代码

方式1:修正for循环

library(rvest)
library(dplyr)

# 读取搜索页面并提取PackageId
url <- "https://portal.edirepository.org/nis/simpleSearch?defType=edismax&q=*:*&fq=-scope:ecotrends&fq=-scope:lter-landsat*&fq=scope:(knb-lter-and)&fl=id,packageid,title,author,organization,pubdate,coordinates&debug=false&start=0&rows=150"
webpage <- read_html(url)

package_ids <- webpage %>%
  html_table() %>%
  .[[4]] %>%
  select(`Package Id  ▵▿`) %>%
  rename(PackageId = `Package Id  ▵▿`) %>%
  pull(PackageId) # 转为字符向量,方便循环

# 初始化结果列表
result_list <- list()

# 循环处理每个PackageId
for (pkg_id in package_ids) {
  # 拼接单个元数据页面URL
  metadata_url <- paste0("https://portal.edirepository.org/nis/metadataviewer?packageid=", pkg_id)
  
  # 读取元数据页面
  metadata_page <- read_html(metadata_url)
  
  # 提取日期(使用已验证的选择器)
  begin_date <- metadata_page %>%
    html_nodes("td:contains('Begin:') + td") %>%
    html_text2() %>% # html_text2自动处理空白
    trimws()
  
  end_date <- metadata_page %>%
    html_nodes("td:contains('End:') + td") %>%
    html_text2() %>%
    trimws()
  
  # 处理可能的缺失值(部分数据集可能无起止日期)
  begin_date <- ifelse(length(begin_date) == 0, NA_character_, begin_date)
  end_date <- ifelse(length(end_date) == 0, NA_character_, end_date)
  
  # 存入结果列表
  result_list[[pkg_id]] <- tibble(
    PackageId = pkg_id,
    Begin = begin_date,
    End = end_date
  )
}

# 合并为最终数据框
final_df <- bind_rows(result_list)
print(final_df)

方式2:使用purrr的map_df(更简洁的tidyverse风格)

library(rvest)
library(dplyr)
library(purrr)

# 读取搜索页面并提取PackageId
url <- "https://portal.edirepository.org/nis/simpleSearch?defType=edismax&q=*:*&fq=-scope:ecotrends&fq=-scope:lter-landsat*&fq=scope:(knb-lter-and)&fl=id,packageid,title,author,organization,pubdate,coordinates&debug=false&start=0&rows=150"
webpage <- read_html(url)

package_ids <- webpage %>%
  html_table() %>%
  .[[4]] %>%
  select(`Package Id  ▵▿`) %>%
  rename(PackageId = `Package Id  ▵▿`) %>%
  pull(PackageId)

# 定义单个PackageId的处理函数
fetch_metadata <- function(pkg_id) {
  metadata_url <- paste0("https://portal.edirepository.org/nis/metadataviewer?packageid=", pkg_id)
  metadata_page <- read_html(metadata_url)
  
  begin_date <- metadata_page %>%
    html_nodes("td:contains('Begin:') + td") %>%
    html_text2() %>%
    trimws() %>%
    {if (length(.) == 0) NA_character_ else .}
  
  end_date <- metadata_page %>%
    html_nodes("td:contains('End:') + td") %>%
    html_text2() %>%
    trimws() %>%
    {if (length(.) == 0) NA_character_ else .}
  
  tibble(
    PackageId = pkg_id,
    Begin = begin_date,
    End = end_date
  )
}

# 批量处理并合并结果
final_df <- map_df(package_ids, fetch_metadata)
print(final_df)

关键改进点

  • 循环时每次仅处理单个PackageId,生成单个URL并读取单个HTML页面,避免列表对象导致的错误。
  • 使用已验证的CSS选择器提取日期,保证提取准确性。
  • 增加缺失值处理逻辑,避免因部分数据集无日期导致的代码中断。
  • 采用tibble和bind_rows替代原生数据框操作,更符合tidyverse规范。

内容的提问来源于stack exchange,提问作者tassones

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 01:17:51