【问题标题】:Rvest scraping child nodes but filling missing values with NARvest 刮取子节点但用 NA 填充缺失值
【发布时间】:2022-01-24 19:32:08
【问题描述】:

我正在尝试从 sec 网站上抓取一些数据。每个父节点都有包含感兴趣文本的子节点。但是,在某些情况下,特定的子节点不存在。因此,例如在此链接中:

urll <- "https://www.sec.gov/Archives/edgar/data/1002784/000139834421003391/fp0061633_13fhr-table.xml"

有 728 个父节点。每个父节点都有许多条目,这些条目是具有特定标签的子节点。以下是一个完整条目的示例(728 个):

<infoTable>
<nameOfIssuer>APPLE INC</nameOfIssuer>
<titleOfClass>COM</titleOfClass>
<cusip>037833100</cusip>
<value>1486</value>
<shrsOrPrnAmt>
<sshPrnamt>11200</sshPrnamt>
<sshPrnamtType>SH</sshPrnamtType>
</shrsOrPrnAmt>
<putCall>Put</putCall>
<investmentDiscretion>SOLE</investmentDiscretion>
<votingAuthority>
<Sole>11200</Sole>
<Shared>0</Shared>
<None>0</None>
</votingAuthority>
</infoTable>

在这个例子中,“putCall”标签可能存在也可能不存在。当它存在时,我希望能够获得相关文本,因此在这种情况下“放置”。然而对于这个链接,728 个父节点中只有 8 个具有“putCall”节点。我想用 NA 填充没有“putCall”节点的节点,以便我始终拥有可以强制转换为数据框的每个标签的 728 个条目。因此,例如,这是我迄今为止在Inputting NA where there are missing values when scraping with rvest 的启发下尝试过的。

library(polite)
library(rvest)
library(purrr)
library(tidyverse)
library(httr)


session <- bow("https://www.sec.gov/")

urll <- "https://www.sec.gov/Archives/edgar/data/1002784/000139834421003391/fp0061633_13fhr-table.xml"

test <- session %>%
  nod(urll) %>%
  scrape(verbose = FALSE) %>%
  html_elements(xpath = "//*[local-name()='infoTable']") %>% # select enclosing nodes
  # iterate over each parent node, pulling out desired parts and coerce to data.frame
  # not the complete list
  map_df(
    ~ list(
      name_of_issuer = html_elements(.x, xpath = "//*[local-name()='nameOfIssuer']") %>%
        html_text() %>%
        {
          if (length(.) == 0)
            NA
          else
            .
        },
      title_of_class = html_elements(.x, xpath = "//*[local-name()='titleOfClass']") %>%
        html_text() %>%
        {
          if (length(.) == 0)
            NA
          else
            .
        },
      put_or_call = html_elements(.x, xpath = "//*[local-name()='putCall']") %>%
        html_text() %>%
        {
          if (length(.) == 0)
            NA
          else
            .
        }))

这失败并显示错误消息:

Error: Can't recycle `name_of_issuer` (size 728) to match `put_or_call` (size 8).

似乎 NA 填充不适用于“putCall”节点,它只返回 8 个条目的列表。

关于我做错了什么以及如何解决它的任何建议?

非常感谢!

【问题讨论】:

  • 我看到Client error: (403) Forbidden https://www.sec.gov/Archives/edgar/data/1002784/000139834421003391/fp0061633_13fhr-table.xml 即使session &lt;- bow("https://www.sec.gov/", user_agent = "polite R package - https://github.com/dmi3kno/polite") 仍然存在

标签: r web-scraping purrr rvest


【解决方案1】:

如果我只是使用 httr,那么我可以传入一个有效的 UA 标头并重写您的代码,以使用 data.frame 调用而不是列表,这样我可以在不存在值的地方返回 N/A。

html_elements 替换为html_element

您还需要修改 xpath 以避免每行重复第一个节点值。

library(tidyverse)
library(httr)

headers <- c("User-Agent" = "Safari/537.36")

r <- httr::GET(url = "https://www.sec.gov/Archives/edgar/data/1002784/000139834421003391/fp0061633_13fhr-table.xml", httr::add_headers(.headers = headers))

r %>%
  content() %>%
  html_elements(xpath = "//*[local-name()='infoTable']") %>% # select enclosing nodes
  # iterate over each parent node, pulling out desired parts and coerce to data.frame
  # not the complete list
  map_df(
    ~ data.frame(
      name_of_issuer = html_element(.x, xpath = ".//*[local-name()='nameOfIssuer']") %>%
        html_text(),
      title_of_class = html_element(.x, xpath = ".//*[local-name()='titleOfClass']") %>%
        html_text(),
      put_or_call = html_element(.x, xpath = ".//*[local-name()='putCall']") %>%
        html_text()
    )
  )

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-25
    相关资源
    最近更新 更多