【发布时间】:2019-04-26 23:14:51
【问题描述】:
我的最终目标是为Montreal 抓取The Puzzled Pint 的Standings 页面。
我认为我需要动态抓取(例如使用RSelenium),因为我感兴趣的表格是 JavaScript iframe - 网页的一部分,它显示的内容独立于其容器。
有些人建议直接从这些iframes 的源中抓取是要走的路。我在firefox 浏览器中使用网络开发人员Inspector 工具找到src=,恰好是Google Sheets。
首先,使用robots.txt 确保我们可以从Google Sheets 抓取它:
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 Sheet 上的任何其他Month/Year 链接时,网址的gid= 会发生变化。例如,对于 2018 年 10 月,现在是:
https://docs.google.com/spreadsheets/d/1o1PlLIQS8v-XSuEz1eqZB80kcJk9xg5lsbueB7mTg1U/pub?output=html&widget=true#gid=1367583807
我不确定是否可以用RCurl 抓取widget 的内容?如果是的话,我很想听听如何。
所以看起来我很可能需要使用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,但对我不起作用(它不会返回预期的输出,只是来自Month/Year 元数据链接/元素)?
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,我确认我突出显示了正确的元素,然后“单击”该元素(在本例中为October 2018 链接)。
webElem_01$highlightElement()
webElem_01$clickElement()
由于我可以看到页面在 TightVNC 上发生了变化,我认为在此处捕获/抓取之前不需要更多步骤,但如上所述,我需要一种以编程方式导航到每个页面的内部 iframe 的方法.
更新
好的,我知道如何使用remDr$switchToFrame() 命令导航到内框,但我似乎不知道如何导航回外框以“单击”下一个链接并重复该过程。我当前的 hacky 尝试将涉及我导航回主页并多次重复此过程:
# 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)
【问题讨论】:
-
您可以请求访问 Google 表格。大多数网站所有者都非常友好,如果你解释你的用例,你可能根本不需要做任何这种抓取。所有这些 URL 的非 HTML 视图都被锁定(我检查了:-),但所有内容都是 CCA-NCSA-3.0,因此它们不限制数据的使用。 feedback@puzzledpint.com 可能会比网络探索要快得多(尽管您已经完成了 ???????? 工作分类。
-
感谢您提出请求访问权限的建议。我同意这将是最简单的方法,但这也主要是为了我自己学习 RSelenium :)
标签: r iframe web-scraping rcurl rselenium