【问题标题】:Sublink not working in r webscraping - df comes up with blank cells网页链接在 r 网页抓取中不起作用 - 提出空白单元格
【发布时间】:2021-07-24 18:09:56
【问题描述】:

我有一个可以抓取网页及其初始嵌套链接的工作代码,但我想单击第二级以抓取更多内容,因此我根据第一级的成功编写了我认为正确的方法。我没有得到任何值,只有标题存在。对此我将不胜感激。

library(rvest)
library(dplyr)
library(purrr)

link = "http://ufcstats.com/statistics/events/completed?page=all"
page = read_html(link)

name = page %>% html_nodes(".b-link_style_black") %>% html_text()
name_links <- page %>% html_nodes(".b-link_style_black") %>% html_attr("href")

fight_info = function(name_link) {
  fight_page = read_html(name_link)
  tibble(
    date = fight %>% html_nodes(".b-list__box-list-item:nth-child(1)") %>% html_text(),
      fight_event = fight %>% html_nodes(".b-list__box-list-item:nth-child(1)") %>% html_attr("href"),
        Fighter1 = fight_page %>% html_nodes(".b-fight-details__person-status_style_green+ .b-fight-details__person-text .b-fight-details__person-link") %>% html_text(),
        Fighter2 = fight_page %>% html_nodes(".b-fight-details__person-status_style_gray+ .b-fight-details__person-text .b-fight-details__person-link") %>% html_text(),
        Referee = fight_page %>% html_nodes(".b-fight-details__label+ span") %>% html_text(),
        F1Control = fight_page %>% html_nodes(".b-fight-details__table-col:nth-child(10) .b-fight-details__table-text:nth-child(1)") %>% html_text(),
        F2Control = fight_page %>% html_nodes(".b-fight-details__table-col:nth-child(10) .b-fight-details__table-text+ .b-fight-details__table-text") %>% html_text(),
        F1ControlRD = fight_page %>% html_nodes(".b-fight-details__table-col:nth-child(10) .b-fight-details__table-text:nth-child(1)") %>% html_text(),
        F2ControlRD = fight_page %>% html_nodes(".b-fight-details__table-col:nth-child(10) .b-fight-details__table-text+ .b-fight-details__table-text") %>% html_text(),
        Weightclass = fight_page %>% html_nodes(".b-fight-details__fight-title") %>% html_text()
  ) -> t
  return(t)
}

df <- map_dfr(name_links, fight_info)

【问题讨论】:

  • 你在map_dfr中调用get_decisions,但你的函数被调用fight_info
  • 我刚刚修复了它,但收到了另一个错误,“UseMethod("xml_find_all") 中的错误:没有适用于 'xml_find_all' 的方法应用于“字符”类的对象调用:xml2:: xml_find_all(x, make_selector(css, xpath))"
  • ...fight 应该是fight_page
  • 嗯,我很感激。进行了更改,但随后收到了此错误,我不确定如何处理。 “错误:Tibble 列必须具有兼容的大小。* 大小 0:现有数据。* 大小 10:列 F1Control。ℹ 仅回收大小为 1 的值。运行 rlang::last_error() 以查看错误发生的位置。调用自:signal_abort (cnd)"

标签: r dataframe web-scraping


【解决方案1】:

除了我在 cmets 中已经提到的代码中的较小问题之外,使用稍微不同的方法实现所需结果的一个选项是通过 html_table 一次提取所有信息,然后进行一些数据清理:

棘手的部分是拆分像Fighter 这样的单元格,其中包含我使用string::str_split 的两行,并将这些行放入我使用tidyr::unnest_wider 的不同列中:

library(rvest)
library(dplyr)
library(purrr)
library(stringr)
library(tidyr)

link = "http://ufcstats.com/statistics/events/completed?page=all"
page = read_html(link)

name = page %>% html_nodes(".b-link_style_black") %>% html_text()
name_links <- page %>% html_nodes(".b-link_style_black") %>% html_attr("href")

get_fight_info = function(name_link) {
  fight_page <- read_html(name_link) 
  
  fight_info <- fight_page %>% html_table() %>% .[[1]]
  fight_info$date <- fight_page %>% html_node(".b-list__box-list-item:nth-child(1)") %>% html_text()
  fight_info$event <- fight_page %>% html_node(".b-list__box-list-item:nth-child(2)") %>% html_text()
  
  fight_info <- fight_info %>% 
    mutate(across(c("Fighter", "Str", "Method"), ~ str_split(.x, "\\n\\n\\s+\\n")),
           date = str_remove(date, "^\\s+Date:\\s+"),
           event = str_remove(event, "^\\s+Location:\\s+"))
  
  fight_info %>% 
    unnest_wider(Fighter, names_sep = "") %>% 
    unnest_wider(Str, names_sep = "") %>% 
    unnest_wider(Method, names_sep = "") %>% 
    mutate(across(everything(), ~ str_remove_all(.x, "\\n") %>% str_trim()))
}

fight_info <- map_dfr(name_links[1:3], get_fight_info)

fight_info
#> # A tibble: 35 x 15
#>    `W/L` Fighter1  Fighter2 Kd    Str1  Str2  Td    Sub   `Weight class` Method1
#>    <chr> <chr>     <chr>    <chr> <chr> <chr> <chr> <chr> <chr>          <chr>  
#>  1 win   Islam Ma… Thiago … 0   … 61    13    3   … 1   … Lightweight    SUB    
#>  2 win   Miesha T… Marion … 0   … 65    25    3   … 0   … Women's Banta… KO/TKO 
#>  3 win   Mateusz … Jeremy … 0   … 1     0     1   … 1   … Lightweight    SUB    
#>  4 win   Rodolfo … Dustin … 0   … 49    67    3   … 1   … Middleweight   SUB    
#>  5 win   Billy Qu… Gabriel… 1   … 100   57    3   … 1   … Featherweight  KO/TKO 
#>  6 win   Daniel R… Preston… 0   … 45    23    0   … 0   … Welterweight   KO/TKO 
#>  7 win   Amanda L… Montser… 1   … 7     3     0   … 0   … Women's Straw… KO/TKO 
#>  8 win   Sergey M… Khalid … 0   … 50    33    6   … 0   … Bantamweight   U-DEC  
#>  9 win   Malcolm … Francis… 0   … 46    28    2   … 0   … Flyweight      U-DEC  
#> 10 win   Rodrigo … Alan Ba… 0   … 49    60    0   … 0   … Heavyweight    KO/TKO 
#> # … with 25 more rows, and 5 more variables: Method2 <chr>, Round <chr>,
#> #   Time <chr>, date <chr>, event <chr>

【讨论】:

  • 谢谢你,感谢你为创建这个所做的努力。我只是在理解 [1:3] 和 mutate(across(c("Fighter", "Str", "Method"), ~ str_split(.x, "\\ n\\n\\s+\\n"))。我尝试添加一些行以获得更具体的统计信息,并收到此错误,这就是我试图了解这些更改的原因:“错误:mutate() 输入有问题..1.ℹ..1 = across(...).x 不能对不存在的列进行子集化。x 列 Total_SigStrike 不存在。"
  • 第一。当通过 html_table 抓取具有两条数据的单元格内容时,例如战斗机名称作为连接字符串返回。因此,我查看了如何将此字符串拆分为两部分,并发现正则表达式 "\\n\\n\\s+\\n" 做得相当好。我建议注释掉数据清理部分,以便自己查看返回的原始数据。第二。如果您想添加包含其他信息的列,那么我建议您在单独的步骤中执行此操作。
  • 好吧,我想我明白了,但是我很好奇如何复制这个函数,name_links % html_nodes(".b-link_style_black") %>% html_attr(" href") 转到此的子页面。当这个字符串拉出原始页面的子链接时,我想单击这些子页面中的每个事件,并且我在 '.b-link_style_black' 中有一个共同字符,我是否只需缩进并粘贴具有相关值的相同脚本?
猜你喜欢
  • 1970-01-01
  • 2018-08-01
  • 1970-01-01
  • 2021-05-03
  • 2020-08-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多