首页 > 解决方案 > 从 B3 iFrame 抓取网页

问题描述

我正在尝试从 BM&FBOVESPA 参考费率页面下载一些数据。里面有一个iframe,如下:

https://www2.bmf.com.br/pages/portal/bmfbovespa/lumis/lum-sistema-pregao-ptBR.asp?Data=23/09/2021&Mercadoria=DI1

这是我的代码,它只返回一个 DF NA

library(rvest)
library(stringr)

html_url <- "https://www2.bmf.com.br/pages/portal/bmfbovespa/lumis/lum-sistema-pregao-ptBR.asp?Data=23/09/2021&Mercadoria=DI1"

html <- read_html(html_url)

data <- html %>%
  html_nodes("td") %>%
  html_text() %>%
  str_replace(",", ".") %>%
  as.numeric()

如何从该页面下载数据?

标签: rweb-scrapingrvest

解决方案


这些表是由在浏览器中运行的 JavaScript 动态生成的。

查看页面源代码,人们可以得到足够的想法来编写一个正则表达式来仅提取定义感兴趣的表 html 的相关字符串。您可以将每个表的提取正则表达式匹配连接成单个字符串,对于每个表,使用 html 解析器进行解析,然后选择表。

这两个表需要从它们在页面源中出现的顺序颠倒过来,以匹配您在页面上看到的内容,并将列绑定在一起以创建单个 DataFrame。

网页上可见的第一列需要单独拉进来,不依赖html_table(),添加到DataFrame的前面。一个可能的重构可能会通过使用 css 选择器将此步骤合并到现有函数中)

library(rvest)
library(dplyr)
library(stringr)

get_table <- function(number, r) {
  pat <- sprintf("MercFut%i.*'(.*)?'", number)
  t <- read_html(paste0(stringr::str_match_all(r, pat)[[1]][, 2], collapse = "")) |>
    html_table()
  return(tibble(t[[1]]))
}

r <- read_html("https://www2.bmf.com.br/pages/portal/bmfbovespa/lumis/lum-sistema-pregao-ptBR.asp?Data=23/09/2021&Mercadoria=DI1") |>
  html_text()

tables <- lapply(c(2, 1), get_table, r)

df <- cbind(tables[[1]], tables[[2]])

first_col <- stringr::str_match_all(r, sprintf("MercFut%i.*'(.*)?'", 3))[[1]][, 2] |>
  paste0(collapse = "") |>
  read_html() |>
  html_elements("th, td") |>
  html_text()

df <- tibble::add_column(df, !!(first_col[1]) := first_col[-c(1)]) |>
  select(first_col[1], everything())

对于较旧的 R 版本,请替换 |>%>%.


推荐阅读