我的最终目标是通过网络抓取 The Puzzled Pint 的排名页面。对于蒙特利尔
。
我认为我需要动态抓取(例如使用RSelenium
),因为我感兴趣的表是一个JavaScript iframe
- 一部分显示独立于其容器的内容的网页。
一些人建议直接从这些 iframes
的源中抓取是正确的方法。我在 firefox
浏览器中使用网络开发人员 Inspector
工具来查找 src=
,它恰好是 Google Sheets
.
首先,使用 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,并且为了能够在其中进行选择,我需要单击链接。
当我将此链接与 readHTMLTable()
一起使用时,我得到了我想要的正确信息:
remDr$navigate("https://docs.google.com/spreadsheets/d/1o1PlLIQS8v-XSuEz1eqZB80kcJk9xg5lsbueB7mTg1U/pubhtml/sheet?headers=false&gid=203220308")
doc <- htmlParse(remDr$getPageSource()[[1]])
readHTMLTable(doc)
这提出了一个问题,因为我需要使用 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()
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/