当网页中 javascript-rendered 内容时使用 R 和 rvest 进行网页抓取
Web scraping with R and rvest when javascript-rendered content in the web page
我正在尝试抓取网页 https://www.filmweb.no/kinotoppen/ 以获取每部电影下的标题和其他信息。对于其他网页,我已经很好地 运行 使用 html_nodes() 和 html_text() 使用 SelectorGadget 选择 CSS 选择器来获得不同的东西我想要这样:
html <- read_html("https://www.filmweb.no/kinotoppen/")
title <- html %>%
html_nodes(".Kinotoppen_MovieTitle__2MFbT") %>%
html_text()
但是,当 运行在该网页上使用这些行时,我只得到一个空字符向量。进一步检查网页后,我发现它正在调用 javascripts。
我尝试将 html_nodes("script") 与 v8 库一起用于 运行 javascripts,但无济于事。我也不确定要 运行 哪些脚本,所以我都这样尝试了:
ct <- v8()
ct$eval(scripts[3])
一般来说,有没有一种更简单的方法可以将网页变成我可以只使用 rvest 的表单?
我对 javascript.
一无所知
这是使用 RSelenium 加载页面的样子。
library(rvest)
library(RSelenium)
remDr <- rsDriver(browser='chrome', port=4444L)
brow <- remDr[["client"]]
brow$open()
brow$navigate("https://www.filmweb.no/kinotoppen/")
h <- brow$getPageSource()
h <- read_html(h[[1]])
h %>% html_nodes(".Kinotoppen_MovieTitle__2MFbT") %>%
html_text()
# [1] "Spider-Man: No Way Home" "Clifford: Den store røde hunden" "Lise & Snøpels - Venner for alltid"
# [4] "Familien Voff - alle trenger en venn" "Nightmare Alley" "Snødronningen"
# [7] "Scream" "Bergman Island" "Trøffeljegerne fra Piemonte"
# [10] "Encanto"
数据是从 graphql 查询中动态检索的。您可以复制该查询以获得包含所有所需数据的 JSON 响应。
在这种情况下,我选择查看使用 httr2 and the newish pipe operator (R 4.1.0)
关于如何通过管道传输 headers 向量,我查看了 @MrFlick here 给出的解决方案。
library(httr2)
headers = c(
'Accept' = 'application/json',
'Referer' = 'https://www.filmweb.no/',
'Content-Type' = 'application/json',
'User-Agent' = 'Mozilla/5.0'
)
params = list(
'query' = 'query($date:String,$chartType:String,$max:Int){movieQuery{getMovieChart(date:$date,chartType:$chartType,max:$max){chartType periodStart periodEnd movieChartItem{pos posPrev admissions admissionsPrev admissionsToDate weeksOnList movie{title mainVersionId premiere poster{name versions{width height url}}}}}}}',
'variables' = '{"date":"2022-02-04","chartType":"weekend","max":1000}'
)
data <- request("https://skynet.filmweb.no/MovieInfoQs/graphql/") |>
(\(x) req_headers(x, !!!headers))() |>
req_url_query(!!!params) |>
req_perform() |>
resp_body_json()
我正在尝试抓取网页 https://www.filmweb.no/kinotoppen/ 以获取每部电影下的标题和其他信息。对于其他网页,我已经很好地 运行 使用 html_nodes() 和 html_text() 使用 SelectorGadget 选择 CSS 选择器来获得不同的东西我想要这样:
html <- read_html("https://www.filmweb.no/kinotoppen/")
title <- html %>%
html_nodes(".Kinotoppen_MovieTitle__2MFbT") %>%
html_text()
但是,当 运行在该网页上使用这些行时,我只得到一个空字符向量。进一步检查网页后,我发现它正在调用 javascripts。 我尝试将 html_nodes("script") 与 v8 库一起用于 运行 javascripts,但无济于事。我也不确定要 运行 哪些脚本,所以我都这样尝试了:
ct <- v8()
ct$eval(scripts[3])
一般来说,有没有一种更简单的方法可以将网页变成我可以只使用 rvest 的表单? 我对 javascript.
一无所知这是使用 RSelenium 加载页面的样子。
library(rvest)
library(RSelenium)
remDr <- rsDriver(browser='chrome', port=4444L)
brow <- remDr[["client"]]
brow$open()
brow$navigate("https://www.filmweb.no/kinotoppen/")
h <- brow$getPageSource()
h <- read_html(h[[1]])
h %>% html_nodes(".Kinotoppen_MovieTitle__2MFbT") %>%
html_text()
# [1] "Spider-Man: No Way Home" "Clifford: Den store røde hunden" "Lise & Snøpels - Venner for alltid"
# [4] "Familien Voff - alle trenger en venn" "Nightmare Alley" "Snødronningen"
# [7] "Scream" "Bergman Island" "Trøffeljegerne fra Piemonte"
# [10] "Encanto"
数据是从 graphql 查询中动态检索的。您可以复制该查询以获得包含所有所需数据的 JSON 响应。
在这种情况下,我选择查看使用 httr2 and the newish pipe operator (R 4.1.0)
关于如何通过管道传输 headers 向量,我查看了 @MrFlick here 给出的解决方案。
library(httr2)
headers = c(
'Accept' = 'application/json',
'Referer' = 'https://www.filmweb.no/',
'Content-Type' = 'application/json',
'User-Agent' = 'Mozilla/5.0'
)
params = list(
'query' = 'query($date:String,$chartType:String,$max:Int){movieQuery{getMovieChart(date:$date,chartType:$chartType,max:$max){chartType periodStart periodEnd movieChartItem{pos posPrev admissions admissionsPrev admissionsToDate weeksOnList movie{title mainVersionId premiere poster{name versions{width height url}}}}}}}',
'variables' = '{"date":"2022-02-04","chartType":"weekend","max":1000}'
)
data <- request("https://skynet.filmweb.no/MovieInfoQs/graphql/") |>
(\(x) req_headers(x, !!!headers))() |>
req_url_query(!!!params) |>
req_perform() |>
resp_body_json()