使用RSelenium和rvest的Web抓取动态Javascript页面

使用RSelenium和rvest的Web抓取动态Javascript页面,javascript,r,rvest,rselenium,Javascript,R,Rvest,Rselenium,我试图创建一个包含颜色ID、描述和日期的数据框,它通过下拉菜单输入日期和月份,并返回动态JS生成的页面。我是新来的编码和认为这将是一个有趣的玩具项目。我想使用RSelenium来自动选择下拉列表,并使用rvest来抓取生成的内容。我希望的数据帧结构如下所示: description, date, meta "paragraph about birthday", Jun 01, "DAFFODIL PANTONE 17-1512 POWERFUL KNOWING EXPRESSIVE" 我试图首

我试图创建一个包含颜色ID、描述和日期的数据框,它通过下拉菜单输入日期和月份,并返回动态JS生成的页面。我是新来的编码和认为这将是一个有趣的玩具项目。我想使用RSelenium来自动选择下拉列表,并使用rvest来抓取生成的内容。我希望的数据帧结构如下所示:

description, date, meta
"paragraph about birthday", Jun 01, "DAFFODIL PANTONE 17-1512 POWERFUL KNOWING EXPRESSIVE"
我试图首先使用for循环,在一天内迭代一年中的每个月,然后逐步得到每个月的每一天

我一直坚持让循环每个月迭代一次,然后获取内容。我可以在任务的这一部分首先使用一些概念上的帮助,并感谢任何见解

library(RSelenium)
library(rvest)
library(tidyverse)
library(xml2)

## first run: docker run -d -p 4445:4444 selenium/standalone-chrome
## open a new connection to Chrome
remDr <- RSelenium::remoteDriver(remoteServerAddr = "localhost",
                                 port = 4445L,
                                 browserName = "chrome")

remDr$open()
remDr$navigate("https://www.pantone.com/pages/iphone/iphone_colorstrology.html#___1__") #Entering our URL gets the browser to navigate to the page
remDr$screenshot(display = TRUE) 

#### create list of month/days
 month_day<- read_html(remDr$getPageSource()[[1]])
 page_i <- month_day %>%
   html_nodes(".list") %>%
   html_children() %>% 
   html_text()

months <- page_i[1:12]
months <- (paste("'", months,"'", sep=''))
days <- page_i[13:43]
days <- as.numeric(days)


## create an object for month xpath elements
for (m in months){
  elements <- paste0("//option[contains(text(),",months,")]")
}

## attempt at loop

total <- data.frame()

for (e in elements){
remDr$navigate("https://www.pantone.com/pages/iphone/iphone_colorstrology.html#___1__") 
      print(e)
      month <- remDr$findElement(using = 'xpath', e)
      month$clickElement()
      day <- remDr$findElement(using = 'xpath', "//select[@id='lstDay']//option[5]") ## arbitrarily picking the 5th of each month
      day$clickElement()
      submit <- remDr$findElement(using = 'xpath', "/html[1]/body[1]/form[1]/div[1]/a[1]")
      submit$clickElement()
      html <- read_html(remDr$getPageSource()[[1]])
      description <- html %>%  html_nodes(xpath = "//tr//tr[2]//td[1]") %>% html_text() %>% gsub("^\\s+|\\s+$", "", .)
      meta <- html %>% html_nodes(xpath = "//td[@id='tdBg']") %>%  html_text() %>% gsub("^\\s+|\\s+$", "", .) 
      date <- html %>% html_nodes(xpath = "//td[@id='bgHeaderDate']//div") %>%  html_text() %>% gsub("^\\s+|\\s+$", "", .)
      df <- data.frame(cbind(description,meta,date))
      total <- rbind(total, df)
}

库(RSelenium)
图书馆(rvest)
图书馆(tidyverse)
库(xml2)
##第一次运行:docker运行-d-p 4445:4444 selenium/standalone chrome
##打开与Chrome的新连接
remDr%
html_text()

几个月后我会回来更新这篇文章,听取我的建议。导航到该页面,然后使用F12在浏览器(比如Chrome)中打开开发工具,然后转到网络选项卡。然后,选择一个月和日期,点击查看现在。您将在“网络”选项卡中看到流量。页面发出POST xhr请求,以获取单击视图图标后看到的内容

POST请求本身非常简单,其正文(表格)由您选择的月份和日期组成:

因此,您可以模拟POST请求,然后解析响应。您提到的日期示例如下:

library(rvest)

body <- list('month' = 6,'day' = 1)
url <- 'https://www.pantone.com/pages/iphone/iphone_colorstrology_results.aspx'
page <- html_session(url) %>%
  rvest:::request_POST(url, body = body, encode = "form") %>%
  read_html()

date <- page %>% html_node('table table td') %>% html_text() %>% 
  gsub('^\\s+|\\s+$|[\r\n\t]', '', .)
description <- page %>% html_node('tr:nth-of-type(2) div') %>% html_text() %>% 
  gsub('^\\s+|\\s+$|[\r\n\t]', '', .)
meta <- page %>% html_nodes('#tdBg span') %>% html_text()

df <- data.frame(date, description, meta)
库(rvest)
正文%html\u text()%>%
gsub('^\\s+|\\s+$|[\r\n\t]',''..)
说明%html\u节点('tr:n类型(2)div')%%>%html\u文本()%%>%
gsub('^\\s+|\\s+$|[\r\n\t]',''..)
元%html_节点('#tdBg span')%>%html_文本()

df找到了一个合理的解决方案!这并不完美,但它比以前更接近我。最后,我按照@QHarr的建议编写了一个函数,并使用了他们的rvest模式:

library(rvest)

colorstrology <- function(i,j){

  body <- list('month' = i,'day' = j)
  url <- 'https://www.pantone.com/pages/iphone/iphone_colorstrology_results.aspx'
  page <- html_session(url) %>%
    rvest:::request_POST(url, body = body, encode = "form") %>%
    read_html()

  date <- page %>% html_node('table table td') %>% html_text() %>% 
    gsub('^\\s+|\\s+$|[\r\n\t]', '', .)
  description <- page %>% html_node('tr:nth-of-type(2) div') %>% html_text() %>% 
    gsub('^\\s+|\\s+$|[\r\n\t]', '', .)
  meta <- page %>% html_nodes('#tdBg span') %>% html_text()

  df <- data.frame(date, description, meta)
}



months <- c(1:12)
days <- c(1:31)

df <- data.frame(date, description, meta)
for (m in months){
  for (d in days){
    temp <- colorstrology(m,d)
    df <- rbind(temp, df)
}
}



库(rvest)
色彩学%
gsub('^\\s+|\\s+$|[\r\n\t]',''..)
说明%html\u节点('tr:n类型(2)div')%%>%html\u文本()%%>%
gsub('^\\s+|\\s+$|[\r\n\t]',''..)
元%html_节点('#tdBg span')%>%html_文本()

df是否必须与硒一起使用?(我知道这是一个供您学习的项目)绝对不必是selenium。如果有纯R或tidyverse解决方案,我洗耳恭听。谢谢你的建议。我喜欢干净的rvest模式和推荐。避免xpath也是一种很好的方法。我仍在努力理解如何格式化月/日组合和实际循环。我会继续努力的。我还没做完呢。只是我需要教自己如何在R中做下一步。我可以用其他语言做。我想我已经掌握了主要部分。日-月组合已经可以正确地在循环中传递帖子了。我只需要完成顶部位到一个可以与会话一起工作的函数的转换。
library(rvest)

colorstrology <- function(i,j){

  body <- list('month' = i,'day' = j)
  url <- 'https://www.pantone.com/pages/iphone/iphone_colorstrology_results.aspx'
  page <- html_session(url) %>%
    rvest:::request_POST(url, body = body, encode = "form") %>%
    read_html()

  date <- page %>% html_node('table table td') %>% html_text() %>% 
    gsub('^\\s+|\\s+$|[\r\n\t]', '', .)
  description <- page %>% html_node('tr:nth-of-type(2) div') %>% html_text() %>% 
    gsub('^\\s+|\\s+$|[\r\n\t]', '', .)
  meta <- page %>% html_nodes('#tdBg span') %>% html_text()

  df <- data.frame(date, description, meta)
}



months <- c(1:12)
days <- c(1:31)

df <- data.frame(date, description, meta)
for (m in months){
  for (d in days){
    temp <- colorstrology(m,d)
    df <- rbind(temp, df)
}
}