r - 使用 RSelenium 和 RCurl 在 R 中抓取 Google Sheets 时出现问题

标签 r iframe web-scraping rcurl rselenium

我的最终目标是通过网络抓取 The Puzzled Pint排名页面。对于蒙特利尔

我认为我需要动态抓取(例如使用RSelenium),因为我感兴趣的表是一个JavaScript iframe - 一部分显示独立于其容器的内容的网页。

一些人建议直接从这些 iframes 的源中抓取是正确的方法。我在 firefox 浏览器中使用网络开发人员 Inspector 工具来查找 src=,它恰好是 Google Sheets .

enter image description here

首先,使用 robots.txt 确保我们可以从 Google 表格 中抓取它:

library(robotstxt)
paths_allowed("https://docs.google.com/spreadsheets/d/1o1PlLIQS8v-XSuEz1eqZB80kcJk9xg5lsbueB7mTg1U/pub?output=html&widget=true#gid=203220308")

现在我知道我有权限,我尝试了 RCurl 包。获取首页很简单:

library(RCurl)
sheet <- getForm("https://docs.google.com/spreadsheet/pub", hl = "en_US", key = "1o1PlLIQS8v-XSuEz1eqZB80kcJk9xg5lsbueB7mTg1U", output = "csv", .opts = list(followlocation = TRUE, verbose = TRUE, ssl.verifypeer = FALSE))
df <- read.csv(textConnection(sheet))
head(df)

但是,当您单击此 Google 表格 上的任何其他月/年 链接时,网址的 gid= 会发生变化。例如,2018 年 10 月现在是:

https://docs.google.com/spreadsheets/d/1o1PlLIQS8v-XSuEz1eqZB80kcJk9xg5lsbueB7mTg1U/pub?output=html&widget=true#gid=1367583807

我不确定是否可以使用RCurl抓取小部件?如果是的话,我很想听听如何。

所以看起来我很可能需要使用 RSelenium 来执行此操作。

library(RSelenium)
# connect to a running server
remDr <- remoteDriver(
  remoteServerAddr = "192.168.99.100",
  port = 4445L
)
remDr$open()
# navigate to the site of interest
remDr$navigate("https://docs.google.com/spreadsheets/d/1o1PlLIQS8v-XSuEz1eqZB80kcJk9xg5lsbueB7mTg1U/pub?output=html&widget=true#gid=203220308")

我的问题是尝试获取此页面上表格的 HTML,以下是 suggested on SO但对我不起作用(它不返回预期的输出,只是来自链接/元素的月/年元数据)?

library(XML)
doc <- htmlParse(remDr$getPageSource()[[1]])
readHTMLTable(doc)

我相信我需要导航到内部框架,但不确定如何执行此操作? 例如,当在 chrome 中使用 SelectorGadget 查找此表的 CSS 标记时,它会向我发出警告,表明它是一个 iframe,并且为了能够在其中进行选择,我需要单击链接。

enter image description here

当我将此链接与 readHTMLTable() 一起使用时,我得到了我想要的正确信息:

remDr$navigate("https://docs.google.com/spreadsheets/d/1o1PlLIQS8v-XSuEz1eqZB80kcJk9xg5lsbueB7mTg1U/pubhtml/sheet?headers=false&gid=203220308")
doc <- htmlParse(remDr$getPageSource()[[1]])
readHTMLTable(doc)

enter image description here

这提出了一个问题,因为我需要使用 RSelenium 来浏览上一个链接(iframe 小部件)的不同页面/表格:

remDr$navigate("https://docs.google.com/spreadsheets/d/1o1PlLIQS8v-XSuEz1eqZB80kcJk9xg5lsbueB7mTg1U/pub?output=html&widget=true#gid=203220308")

为了浏览不同的页面/表格,我使用 SelectorGadget找到 CSS 标签

# find all elements/links
webElems <- remDr$findElements(using = "css", ".switcherItem")
# Select the first link (October 2018)
webElem_01 <- webElems[[1]]

然后使用 TightVNC viewer我确认我突出显示了正确的元素,然后“单击”该元素(在本例中为 2018 年 10 月 链接)。

webElem_01$highlightElement()

enter image description here

webElem_01$clickElement()

由于我可以看到页面在 TightVNC 上发生了变化,我认为在此处捕获/抓取之前不需要更多步骤,但正如前面提到的,我需要一种以编程方式导航到内部 的方法每个页面的 iframe

更新

好吧,我想出了如何使用 remDr$switchToFrame() 命令导航到内部框架,但我似乎无法弄清楚如何导航回外部框架以便“单击”下一个链接并重复该过程。我当前的黑客尝试将涉及我导航回主页并多次重复此过程:

# navigate to the main page
remDr$navigate("https://docs.google.com/spreadsheets/d/1o1PlLIQS8v-XSuEz1eqZB80kcJk9xg5lsbueB7mTg1U/pub?output=html&widget=true#gid=690408156")
# look for table
tableElem <- remDr$findElement(using = "id", "pageswitcher-content")
# switch to table
remDr$switchToFrame(tableElem)
# parse html
doc <- htmlParse(remDr$getPageSource()[[1]])
readHTMLTable(doc)

# how do I switch back to the outer frame?
# the remDr$goBack() command doesn't seem to do this

# workaround is to navigate back to the main page then navigate back to the second page and repeat process
remDr$navigate("https://docs.google.com/spreadsheets/d/1o1PlLIQS8v-XSuEz1eqZB80kcJk9xg5lsbueB7mTg1U/pub?output=html&widget=true#gid=690408156")
webElems <- remDr$findElements(using = "css", ".switcherItem")
webElem_01 <- webElems[[1]]
webElem_01$clickElement()
tableElem <- remDr$findElement(using = "id", "pageswitcher-content")
# switch to table
remDr$switchToFrame(tableElem)
# parse html
doc2 <- htmlParse(remDr$getPageSource()[[1]])
readHTMLTable(doc2)

最佳答案

注意到我在评论中所做的事情,这适用于大约 19 个 URL:

library(googlesheets4)
library(rvest)

pg <- read_html("http://www.puzzledpint.com/standings/")

html_nodes(pg, xpath=".//iframe[contains(@src, 'sheet')]") %>% 
  html_attr("src") -> gsheet_urls

gsheet_urls[grepl("output=html", gsheet_urls, fixed=TRUE)] %>% 
  lapply(function(x) {
    read.csv(
      file =gsub("=true", "=false", gsub("=html", "=csv", x)),
      stringsAsFactors = FALSE
    )
  }) -> nineteen

str(nineteen, 1)
## List of 19
##  $ :'data.frame': 8 obs. of  6 variables:
##  $ :'data.frame': 37 obs. of  7 variables:
##  $ :'data.frame': 35 obs. of  6 variables:
##  $ :'data.frame': 62 obs. of  6 variables:
##  $ :'data.frame': 34 obs. of  6 variables:
##  $ :'data.frame': 30 obs. of  11 variables:
##  $ :'data.frame': 24 obs. of  6 variables:
##  $ :'data.frame': 11 obs. of  6 variables:
##  $ :'data.frame': 9 obs. of  6 variables:
##  $ :'data.frame': 13 obs. of  6 variables:
##  $ :'data.frame': 36 obs. of  6 variables:
##  $ :'data.frame': 9 obs. of  6 variables:
##  $ :'data.frame': 13 obs. of  6 variables:
##  $ :'data.frame': 29 obs. of  6 variables:
##  $ :'data.frame': 45 obs. of  6 variables:
##  $ :'data.frame': 34 obs. of  6 variables:
##  $ :'data.frame': 22 obs. of  6 variables:
##  $ :'data.frame': 3 obs. of  6 variables:
##  $ :'data.frame': 14 obs. of  6 variables:

所有 pubhtml 均未经许可明确拒绝 CSV 导出。

关于r - 使用 RSelenium 和 RCurl 在 R 中抓取 Google Sheets 时出现问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53461977/

相关文章:

r - 需要安装Go才能使用Academic Hugo主题的blogdown

r - 如何使用 ggplot 中的分组箱线图将 geom_text 标签放置在正确的位置

javascript - 你能在浏览器中执行包含的 JavaScript 吗?

javascript - iframe 中的页面顶部

javascript - 从 URL 存储产品详细信息

python - 在 python 中为多个变量设置 nosuchelementexception 的默认值

r - ggplot : Generate facet grid plot with multiple series

r - 如何按年份绘制 NetCDF 栅格图

javascript - iframe 加载是否会阻止 javascript 执行?

python - 尝试使用 BeautifulSoup 从没有 API 的站点获取数据