尝试使用RVest进行网络抓取时,如何解决'UseMethod(“ xml_find_all”)中的错误

时间:2019-08-27 11:23:12

标签: r xml web-scraping rstudio rvest

我是R的初学者,我正在尝试编写一个函数来从网站上某个歌手抓取所有歌曲歌词,并返回带有歌词和歌曲名称的小标题。我已经设法获得了所有歌曲的链接,但是我一直试图编写一个函数来实际获取歌词。

有问题的网站是:https://www.letras.mus.br/belchior/44457/

歌曲标题的选择器:#js-lyric-cnt > article > div.cnt-head.cnt-head--l > div.cnt-head_title > h1

歌曲歌词的选择器:#js-lyric-cnt > article > div.cnt-letra-trad.g-pr.g-sp > div.cnt-letra.p402_premium

我写了这个函数:

get_lyrics <- function(url){
  url %>% read_html() %>% 
    um <- html_nodes('#js-lyric-cnt > article > div.cnt-letra-trad.g-pr.g-sp > div.cnt-letra.p402_premium')  
    um %>% 
    lyrics <- html_text()
  url %>% read_html() %>%
    dois <- html_nodes('#js-lyric-cnt > article > div.cnt-head.cnt-head--l > div.cnt-head_title > h1') 
    dois %>% 
    title <- html_text()
  data_frame(title, lyrics)
}

但是当我尝试运行时,我得到了:

 get_lyrics('https://www.letras.mus.br/belchior/1391391/')
 Error in UseMethod("xml_find_all") : 
  no applicable method for 'xml_find_all' applied to an object of class "character" 

我不确定该如何解决,因此我感谢您的帮助。

2 个答案:

答案 0 :(得分:0)

您可以缩短选择器(通常更快,更稳定)。 read_html仅处理一次,然后使用检索到的内容。我假设(周)-您想要一个数据帧,标题有1个条目,而歌词有1个对应条目。歌词在p类的父元素的cnt-letra标签内;此外,各个歌词行用br标签分隔。为了在解析为单个字符串时保留原始歌词行间距的感觉,我添加了'\ n'来解决这些中断。

我从@rentrop here获得了br缺乏rvest处理的必要功能-尽管由于该问题已经很久了,也许我错过了添加功能?

在链接方法以确保流程符合预期时要小心使用顺序。

library(rvest)
library(magrittr)

html_text_collapse <- function(x, trim = FALSE, collapse = "\n"){
  UseMethod("html_text_collapse")
}

html_text_collapse.xml_nodeset <- function(x, trim = FALSE, collapse = "\n"){
  vapply(x, html_text_collapse.xml_node, character(1), trim = trim, collapse = collapse)
}

html_text_collapse.xml_node <- function(x, trim = FALSE, collapse = "\n"){
  paste(xml2::xml_find_all(x, ".//text()"), collapse = collapse)
}


get_lyrics <- function(url){
    page <- read_html(url)
    lyrics <- toString(page %>% html_nodes('.cnt-letra p') %>% html_text_collapse) 
    title <- page %>% html_node('.cnt-head_title') %>% html_text()
    return(data.frame(title, lyrics))
}

get_lyrics('https://www.letras.mus.br/belchior/44457/')

答案 1 :(得分:0)

如果目标只是获取歌词,则可以使用genius软件包。

genius::genius_lyrics("Belchior", "Na Hora do Almoco")将获取歌词。