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

R语言网页爬取:批量填充统一字段与缺失值设为NA的实现

BJJ赛事数据爬取与DataFrame构建问题

我需要从指定页面爬取选手的组别、性别、腰带等级、体重等信息并整合成DataFrame,目前遇到两个技术问题:

  1. 组别、性别、腰带等级、体重仅在页面顶部出现一次,如何让这些信息自动填充到每位选手对应的DataFrame行中?
  2. 如何为缺失的日期、选手编号等信息填充NA值?当前因各爬取字段长度不一致,无法生成有效DataFrame。

现有代码如下:

library(rvest)
library(tidyverse)

MensUrl <- read_html('https://www.bjjcompsystem.com/tournaments/1869/categories/2053147')

## SCRAPE FIGHT INFO -------------------------------------------
ageDivision <- MensUrl %>% 
  html_nodes('.category-title__age-division') %>% 
  html_text()

gender <- MensUrl %>% 
  html_nodes('.category-title__age-division+ .category-title__label') %>% 
  html_text()

belt <- MensUrl %>% 
  html_nodes('.category-title__label:nth-child(3)') %>% 
  html_text()

weight <-  MensUrl %>% 
  html_nodes('.category-title__label:nth-child(4)') %>% 
  html_text()

fightAndMat <- MensUrl %>% 
  html_nodes('.bracket-match-header__where , .bracket-match-header__fight') %>% 
  html_text()

date = MensUrl %>% 
  html_nodes('.bracket-match-header__when') %>% 
  html_text()

CompetitorNo = MensUrl %>% 
  html_nodes('.match-card__competitor-n') %>% 
  html_text()

name = MensUrl %>% 
  html_nodes('.match-card__competitor-description div:nth-child(1)') %>% 
  html_text()

gym = MensUrl %>% 
  html_nodes('.match-card__club-name') %>% 
  html_text()

# create match df 
matches = data.frame('division' = ageDivision,
                     'gender' = gender,
                     'belt' = belt,
                     'weight' = weight,
                     'fightAndMat' = fightAndMat,
                     'date' = date,
                     'competitor' = CompetitorNo,
                     'name' = name,
                     'gym' = gym)

期望生成的DataFrame需包含每位选手对应的组别、性别等全局信息,缺失字段填充NA。


解决方案

1. 全局信息批量填充

页面顶部的组别、性别等是全局属性,只需将这些单值向量重复至与选手数量一致即可。以选手姓名的长度作为重复次数(每位选手必有姓名,长度最可靠),用rep()或rep_len()实现批量填充。

2. 字段长度对齐与NA填充

部分字段(如日期、选手编号)可能缺失,需确保所有向量长度一致,缺失位置自动补NA。用purrr::map_dfc()结合rep_len()可批量处理所有字段,统一长度并补全NA。

修改后的完整代码:

library(rvest)
library(tidyverse)

MensUrl <- read_html('https://www.bjjcompsystem.com/tournaments/1869/categories/2053147')

## 爬取全局信息(页面顶部)
ageDivision <- MensUrl %>% 
  html_nodes('.category-title__age-division') %>% 
  html_text()

gender <- MensUrl %>% 
  html_nodes('.category-title__age-division+ .category-title__label') %>% 
  html_text()

belt <- MensUrl %>% 
  html_nodes('.category-title__label:nth-child(3)') %>% 
  html_text()

weight <-  MensUrl %>% 
  html_nodes('.category-title__label:nth-child(4)') %>% 
  html_text()

## 爬取选手及赛事细节
fightAndMat <- MensUrl %>% 
  html_nodes('.bracket-match-header__where , .bracket-match-header__fight') %>% 
  html_text()

date <- MensUrl %>% 
  html_nodes('.bracket-match-header__when') %>% 
  html_text()

CompetitorNo <- MensUrl %>% 
  html_nodes('.match-card__competitor-n') %>% 
  html_text()

name <- MensUrl %>% 
  html_nodes('.match-card__competitor-description div:nth-child(1)') %>% 
  html_text()

gym <- MensUrl %>% 
  html_nodes('.match-card__club-name') %>% 
  html_text()

# 获取选手数量(以name的长度为准)
total_competitors <- length(name)

# 统一所有字段长度,自动填充NA
matches_df <- map_dfc(
  list(
    division = ageDivision,
    gender = gender,
    belt = belt,
    weight = weight,
    fight_and_mat = fightAndMat,
    date = date,
    competitor_no = CompetitorNo,
    name = name,
    gym = gym
  ),
  ~rep_len(.x, length.out = total_competitors)
) %>% 
  as.data.frame() # 可选:转为data.frame格式,如需tibble可去掉这行

代码说明

  • rep_len(.x, length.out = total_competitors):将每个向量调整为指定长度,不足部分自动补NA,解决字段长度不一致问题。
  • 全局信息(division、gender等)原本是单值,rep_len会自动重复至选手数量,实现每行填充。
  • map_dfc批量处理所有字段,避免逐个手动调整,代码更简洁易维护。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 15:45:42