【问题标题】:Rvest is scraping something, but not what is on the websiteRvest 正在抓取一些东西,但不是网站上的内容
【发布时间】:2018-08-25 19:54:35
【问题描述】:

我正在尝试从包含世界少儿联赛数据的网页中抓取统计数据。该网站上只有一张桌子,所以我认为 .[[1]] 应该没问题。它确实抓取了一些数据,但这些名字都不是这个特定球队的运动员的名字,变量也被关闭了。这是我的代码

library(rvest)
West <- read_html("https://gc.com/t/summer-2018/west-5b3ad51e396a0500018e8513/stats")
West %>%
html_nodes("table") %>%
  .[[1]] %>%
  html_table

这就是我得到的:

    Batting AB R H RBI[?]
1 J Stevens  4 2 1      -
2 S Roberts  3 0 1      -
3 C Stevens  1 1 0      -
4   R Meier  4 1 2      -

这些都不是西部球队球员的名字。列也乱序或错误。我环顾四周,但找不到这是从哪里拉出来的。我是网络抓取的新手,因此我们将不胜感激。

【问题讨论】:

  • 该页面可能是由 js 或基于服务器的进程加载的。要刮掉它,您需要使用 RSelenium。
  • 不,你没有。

标签: r web-scraping rvest


【解决方案1】:

这个赛季已经过去了,所以 OP 可能不需要这个,但足够多的例子最终会导致这样的问题不会被问到。

那个网站确实通过 XHR 请求使用 javascript 来异步加载内容,但我们绝对不需要在图片中引入像 Selenium 这样的重量级依赖项来解决大多数这样的问题。

您可以在此处查看它异步 XHR 加载的 URL(开始使用浏览器开发者工具练习):

现在,该 URL 也是动态生成的(是的,令人费解的、次优的 Web 应用程序设计)。所以,我们需要变得聪明。我使用curlconverter 来查看该 URL 的格式(如下所示,这很讨厌)。但是,这是令人讨厌的统一。因此,您应该能够发布任何团队统计 URL(它必须与您显示的一样)作为参数并返回可爱的 javascript。以下是注释较少的函数:

get_team_stats <- function(team_stats_url) {

  suppressPackageStartupMessages({
    library(httr, warn.conflicts = FALSE, quietly = TRUE)
    library(jsonlite, warn.conflicts = FALSE, quietly = TRUE)
  })

  res <- httr::GET(team_stats_url) # to prime cookies
  httr::stop_for_status(res) # and also validate the team URL

  # extract the team id
  team_id <- gsub("^[[:alpha:]]+\\-", "", strsplit(team_stats_url, "/")[[1]][6])

  httr::GET(
    url = sprintf("https://gc.com/stats/team/%s/", team_id), # use the team id
    query = list(
      stats_requested = "[{\"category\":\"offense\",\"key\":\"GP\"},{\"category\":\"offense\",\"key\":\"PA\"},{\"category\":\"offense\",\"key\":\"AB\"},{\"category\":\"offense\",\"key\":\"H\"},{\"category\":\"offense\",\"key\":\"1B\"},{\"category\":\"offense\",\"key\":\"2B\"},{\"category\":\"offense\",\"key\":\"3B\"},{\"category\":\"offense\",\"key\":\"HR\"},{\"category\":\"offense\",\"key\":\"RBI\"},{\"category\":\"offense\",\"key\":\"R\"},{\"category\":\"offense\",\"key\":\"HBP\"},{\"category\":\"offense\",\"key\":\"ROE\"},{\"category\":\"offense\",\"key\":\"FC\"},{\"category\":\"offense\",\"key\":\"CI\"},{\"category\":\"offense\",\"key\":\"BB\"},{\"category\":\"offense\",\"key\":\"SO\"},{\"category\":\"offense\",\"key\":\"AVG\"},{\"category\":\"offense\",\"key\":\"OBP\"},{\"category\":\"offense\",\"key\":\"SLG\"},{\"category\":\"offense\",\"key\":\"OPS\"}]",
      qualifying_stat = "{\"key\":\"GP\",\"category\":\"offense\"}",
      game_filter = "All"
    )
  ) -> res

  httr::stop_for_status(res) # warn if anything goes wrong

  jsonlite::fromJSON(
    httr::content(res, as = "text", encoding = "UTF-8")
  )

}

让我们试一试:

team_stats <- get_team_stats("https://gc.com/t/summer-2018/west-5b3ad51e396a0500018e8513/stats")

str(team_stats, 1)
## List of 3
##  $ glossary:'data.frame': 20 obs. of  5 variables:
##  $ players :'data.frame': 14 obs. of  2 variables:
##  $ totals  :'data.frame': 1 obs. of  1 variable:

【讨论】:

    猜你喜欢
    • 2017-09-11
    • 1970-01-01
    • 1970-01-01
    • 2017-10-02
    • 2013-05-27
    • 1970-01-01
    • 2020-04-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多