【发布时间】:2023-03-26 18:08:01
【问题描述】:
我已经成功地编写了两个可以正常工作的独立抓取功能,但我想通过使用 purrr 中的地图功能将它们组合成一个单独的抓取来继续我的学习。这两个刮痕甚至来自我称之为“url_final”的活动页面的索引。以下是该索引中的两个活动页面示例:
https://www.sports-reference.com/cbb/players/ken-tabaka-1.html
https://www.sports-reference.com/cbb/players/bobby-adair-1.html
我正在抓取球员的姓名、身高和他们参加的赛季(从表格中提取的赛季数据并占据第一列的所有数据)您会注意到在第二个链接中没有表格。这是一个罕见的情况,但我把它作为一个例子,因为这需要我使用另一个了不起的 SO 大师提供给我的 try catch 函数。
这是第一个使用大索引“url_final”作为 .x 的单独抓取函数:
library(rvest)
library(curl)
library(tidyverse)
name_age <- map_dfr(.x = url_final,
.f = function(x){Sys.sleep(.3); cat(1);
player <- read_html(curl(x, handle = curl::new_handle("useragent" = "Mozilla/5.0"))) %>%
html_nodes("#meta :nth-child(1)") %>%
html_text() %>%
.[[1]] %>%
as.data.frame()
})
这是第二次抓取,使用相同的 url 索引并从页面上的第一个表中获取季节,注意,您可以从上面的第一个 url 示例中看到它包含该表,但不包含第二个 URL。
player_seasons <- map_dfr(.x = url_final,
.f = function(x){Sys.sleep(.3); cat(1);
tryCatch({
fyr <- read_html(curl::curl(x,
handle = curl::new_handle("useragent" = "Mozilla/5.0"))) %>%
html_table() %>% .[[1]]
fyr <- fyr %>%
select(1) %>%
mutate(name = str_extract(string = x,
pattern = "(?<=cbb/players/).*?(?=-\\d\\.html)"))
}, error = function(e) message('Skipping url', x))
})
我尝试将这两者组合成一个地图功能,但无济于事。我猜解决方案很简单。我想找到一种方法将所有数据映射为单个 df。
重要提示
在大多数情况下,每个球员都会被淘汰多个赛季,我想这可能是我在解决这个问题时遇到问题的原因。理想情况下,我只需要表格显示的最近一年。例如,我提供的第一个 URL 示例(Ken Tabaka 个人资料页面)我真的只对保留“1970/71”1969-70 感兴趣,并且无论如何稍后都会被过滤掉。
谢谢大家!
【问题讨论】:
-
嗨 Jeff,你想以什么方式组合这两个函数的输出?
-
@Bas 理想情况下是数据框或小标题。如果有必要,一份清单至少也是可以接受的。
-
@Ronak 在下面提供了答案。一个小提示:你使用
html_nodes,然后用.[[1]]选择第一个元素,这可以通过使用html_node(单数)来缓解,它会自动选择第一个。 -
嗨,杰夫,下面的答案对我有用,在 R 4.0.0 上没有任何错误。和
dplyr1.0.0。我不确定您是否需要为此更新任何软件包。如果它仍然不起作用,请尝试几件事 1) 使用map而不是map_dfr。 2)使用list(first, second)而不是tibble(first, second)3)同时执行1和2。 -
@RonakShah 使用 Map 而不是 map_dfr 有效!我有 95k 的 url 最终将映射到一个列表中,但不确定这是可取的,但我认为 R 应该能够处理它。我不完全确定之后如何将列表的所有元素组合到一个数据框中,但我敢打赌我可以研究一下。一如既往地感谢你。你是最棒的罗纳克!
标签: r web-scraping rvest