【问题标题】:Trouble using rvest on nested tables在嵌套表上使用 rvest 时遇到问题
【发布时间】:2018-04-23 04:00:23
【问题描述】:

我在尝试从 Freeride World Tour 网站获取排名时遇到问题。

我首先尝试在 Chrome 中使用 selectorGadget 获取 rvest 的 CSS 代码,但只能获取车手及其总分。我感兴趣的是获得骑手在每次预赛中得分。我是网络抓取和 CSS/HTML 的新手,所以请和我一起坚持下去。

# Get the website url
url <- read_html("https://www.freerideworldtour.com/rankings-detailed?season=165&competition=2&discipline=38")

从页面下载所有内容,

(all_text <- url %>% 
                html_nodes("div") %>% 
                html_text())

然后寻找 Kristofer Turdell 的第一个 2500 分得分。 grep("2500 pts.", all_text) 但我发现……什么都没有?

当我右键单击 2500 点时。在网站上选择“Inspect”可以看到该部分的html代码是:

<div class="field__item even">2500 pts.</div>

所以我尝试使用div class

url %>%
     html_nodes(".field__item.even:) %>%
     html_text()

这仅返回参与者的总分(例如 Kristofer Turdell 7870 分)。

接下来,我尝试使用右键单击选项从“Inspect”中保存 Xpath。

url %>%
      html_nodes(xpath = "//*[@id="page-content"]/div/div/div[2]/div/div/div/div[1]/div[2]/div/div/div[1]/div/div[4]/div/div/div") %>%
      html_text()

我在这方面没有任何运气,所以非常感谢您的帮助。

【问题讨论】:

  • 当您单击展开每个数据时,似乎正在使用 JavaScript 加载数据。即使它被隐藏,它也可能仍然可用,但否则您需要使用可以以编程方式为您单击按钮的东西,例如 splashr 或 RSelenium。
  • 获取单个玩家的网址并从那里抓取可能更容易。例如url &lt;- read_html("https://www.freerideworldtour.com/rider/kristofer-turdell"),然后是url %&gt;% html_node("div") %&gt;% html_text() %&gt;% gsub("\\s*\\n+\\s*",";",.) %&gt;% gsub("pts.", "\n", .) %&gt;% read.table(text = ., fill = T, sep = ";", row.names = NULL, col.names = c("Drop", "Ranking", "FWT", "Events", "Points")) %&gt;% subset(select=2:5) %&gt;% dplyr::filter(!is.na(as.numeric(as.character(Ranking)))),遵循@Onyambu 的风格。
  • 谢谢@Kim。如果我为 Rider riders &lt;- c("kristofer-turdell", "markus-eder", "mickael-bimboes") 创建一个向量,并为 url url_base &lt;- "https://www.freerideworldtour.com/rider/" 创建一个前缀,我应该可以使用 bind_rows() 创建一个 for 循环,但是我只能打印到控制台 for (i in riders) { read_html(paste0(url_base, i)) %&gt;% html_node("div") %&gt;% ... mutate(name = i) %&gt;% print() }... 代表我省略的代码部分。

标签: html css r web-scraping rvest


【解决方案1】:
url %>%
   html_node("div.panel-second")%>%
   html_text() %>%
   gsub("\\s*\\n+\\s*",";",.)%>%
   gsub("pts.","\n",.)%>%
   read.table(text=.,fill=T,sep=";",row.names = NULL)%>%
   subset(select=3:4)%>%na.omit()
                     V3   V4
1     Kristofer Turdell 7870
2           Markus Eder 7320
3       Mickael Bimboes 6930
4   Loic Collomb-Patton 6660
5           Yann Rausis 6290
6    Berkeley Patterson 5860
7           Leo Slemett 5835
8         Ivan Malakhov 5800
9          Craig Murray 5705
10         Logan Pehota 5655
11       Reine Barkered 5470
12        Grifen Moller 4765
13              Sam Lee 4580
14            Ryan Faye 3210
15         Conor Pelton 3185
16        George Rodney 3115
17     Taisuke Kusunoki 3060
18          Trace Cooke 2905
19        Aymar Navarro 2855
20        Felix Wiemers 2655
21         Fabio Studer 2305
22         Stefan Hausl 2240
23           Drew Tabke 1880
24 Carl Regnér Eriksson 1310

【讨论】:

  • 整洁的代码,但不是作者要求的,我认为。
  • 感谢 Onyambu,这是一个很好的代码(尤其是 gsub 的),用于获得整体骑手得分。但是,我想要的是每个事件的个人分数。 Kim 的回答更接近我所寻找的。如果能以更自动化的方式做到这一点,那就太好了。 for循环是我目前能想到的最好的方式;但是,如果我想从中获取内容的网站有 1000 多个条目会怎样?我想我需要研究像splashrRSelenium 这样可以以编程方式单击按钮(打开新网址)的东西?
【解决方案2】:

在 cmets 中编写这么多代码太糟糕了,所以就这样吧。您可以将抓取的数据存储到数据框中,而不仅限于将其打印到控制台:

library(tidyverse)
library(magrittr)
library(rvest)

url_base <- "https://www.freerideworldtour.com/rider/"
riders <- c("kristofer-turdell", "markus-eder", "mickael-bimboes")

output <- data_frame()
for (i in riders) { 
  temp <- read_html(paste0(url_base, i)) %>% 
    html_node("div") %>% 
    html_text() %>% 
    gsub("\\s*\\n+\\s*", ";", .) %>% 
    gsub("pts.", "\n", .) %>% 
    read.table(text = ., fill = T, sep = ";", row.names = NULL, 
               col.names = c("Drop", "Ranking", "FWT", "Events", "Points")) %>%
    subset(select = 2:5) %>% 
    dplyr::filter(
      !is.na(as.numeric(as.character(Ranking))) & 
        as.character(Points) != ""
    ) %>%
    dplyr::mutate(name = i)
  output <- bind_rows(output, temp)
}

我输入了诸如as.character(Points) != "" 之类的部分来排除分数的总和(例如 Mickael Bimboe 的 6930 分),而不是单个分数。

尽管如此,@Onyambu 还是有很多功劳,他的回答借用了很多台词。

【讨论】:

    猜你喜欢
    • 2020-10-05
    • 1970-01-01
    • 2014-05-07
    • 2020-10-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-31
    • 2013-02-16
    相关资源
    最近更新 更多