【问题标题】:What is the right xpath to scrape this web page?抓取此网页的正确 xpath 是什么?
【发布时间】:2013-11-26 00:13:31
【问题描述】:

我试图在this page 中获取选择器列表:

$("#Lastname"),$(".intro"),....

这是我使用xpathSApply的尝试:

library(XML)
library(RCurl)
a <- getURL('http://www.w3schools.com/jquery/trysel.asp')
doc <- htmlParse(a)
xpathSApply(doc,'//*[@id="selectorOptions"]') ## I can't get the right xpath

我也尝试过,但没有成功:

xpathSApply(doc,'//*[@id="selectorOptions"]/div[i]')

编辑我添加 python 标签,因为我也接受 python 解决方案。

【问题讨论】:

  • Javascript 正在此页面上运行以创建您正在寻找的内容。例如var w3SelDescriptions = []; w3SelDescriptions.push('The element with id="Lastname"'); 您需要从浏览器或类似的东西获取页面发布 javascript。
  • @jdharrison 恐怕我不明白你的意思。你的意思是选择器是由这个调用创建的:onload="w3jQuerySelectorLoad()?.
  • 选择器列表由一段 javascript 代码创建
  • xpathSApply(doc,'//*/script')[[6]] 可能是创建您正在寻找的内容的 javascript 块。
  • 在本例中,正如 jdharrison 所指出的,您可以通过查找相关脚本并进行一些解析来获取选项列表,因为所有选项都在那里。不过,在更一般的情况下,您需要使用将执行 JS 并进行所需 DOM 更改的客户端访问页面。我不认为有一个简单的方法可以用 R 来做到这一点。虽然我之前通过 Python 使用过 Selenium(我认为 Selenium 启动了一个你可以访问的服务器通过 R)。

标签: r curl xpath web-scraping


【解决方案1】:

以下是访问此类 javascript 页面的 R 方法。您将需要使用@Peyton 所述的浏览器。 Selenium 服务器是控制浏览器的一种好方法。我已经为硒服务器的 R 编写了一些绑定 https://github.com/johndharrison/RSelenium

以下内容将允许访问帖子 javascript 源:

require(devtools)
devtools::install_github("RSelenium", "johndharrison")
library(RSelenium)
library(RJSONIO)

# one needs to have an active server running
# the following commented out lines source the latest java binary
# RSelenium::checkForServer()
# RSelenium::startServer()
# a selenium server is assummed to be running now

remDR <- remoteDriver$new()
remDR$open() # opens a browser usually firefox with default settings
remDR$navigate('http://www.w3schools.com/jquery/trysel.asp') # navigate to your page
webElem <- remDR$findElements(value = "//*[@id='selectorOptions']") # find your elememts

# display the appropriate quantities
cat(fromJSON(webElem[[1]]$getElementText())$value)
> cat(fromJSON(webElem[[1]]$getElementText())$value)
$("#Lastname")
$(".intro")
$(".intro, #Lastname")
$("h1")
$("h1, p")
$("p:first")
$("p:last")
$("tr:even")
$("tr:odd")
$("p:first-child")
$("p:first-of-type")
$("p:last-child")
$("p:last-of-typ
.....................

更新:

在这种情况下访问信息的一种更简单的方法是使用executeScript 方法

library(RSelenium)
RSelenium:startServer()
remDr$open()
remDR$navigate('http://www.w3schools.com/jquery/trysel.asp')
remDr$executeScript("return w3Sels;")[[1]]

> remDr$executeScript("return w3Sels;")[[1]]
 [1] "#Lastname"              ".intro"                
 [3] ".intro, #Lastname"      "h1"                    
 [5] "h1, p"                  "p:first"               
 [7] "p:last"                 "tr:even"               
 [9] "tr:odd"                 "p:first-child"         
[11] "p:first-of-type"        "p:last-child"          
[13] "p:last-of-type"         "li:nth-child(1)"       
[15] "li:nth-last-child(1)"   "li:nth-of-type(2)"     
[17] "li:nth-last-of-type(2)" "b:only-child"          
[19] "h3:only-of-type"        "div > p"               
[21] "div p"                  "ul + h3"               
[23] "ul ~ table"             "ul li:eq(0)"           
[25] "ul li:gt(0)"            "ul li:lt(2)"           
[27] ":header"                ":header:not(h1)"       
[29] ":animated"              ":focus"                
[31] ":contains(Duck)"        "div:has(p)"            
[33] ":empty"                 ":parent"               
[35] "p:hidden"               "table:visible"         
[37] ":root"                  "p:lang(it)"            
[39] "[id]"                   "[id=my-Address]"       
[41] "p[id!=my-Address]"      "[id$=ess]"             
[43] "[id|=my]"               "[id^=L]"               
[45] "[title~=beautiful]"     "[id*=s]"               
[47] ":input"                 ":text"                 
[49] ":password"              ":radio"                
[51] ":checkbox"              ":submit"               
[53] ":reset"                 ":button"               
[55] ":image"                 ":file"                 
[57] ":enabled"               ":disabled"             
[59] ":selected"              ":checked"              
[61] "*"

【讨论】:

  • 谢谢!我以前没有听说过硒!但我收到错误Error in function (type, msg, asError = TRUE) : couldn't connect to host。可能是因为 firefox 不是我的默认浏览器?
  • 您是否在运行服务器。您需要运行# RSelenium::checkForServer() # RSelenium::startServer()。我将这些行注释掉,因为包括我自己在内的许多人都不喜欢从 R 下载和运行外部二进制文件。这将从code.google.com/p/selenium 下载二进制文件。 startServer 将运行此二进制文件。如果您不想使用包中的内置命令,您可以前往该页面并自行下载服务器并确保它正在运行。
  • Python 具有运行 Selenium 的能力,我相信它已得到官方支持,因此如果您习惯使用 Python,这将是一个不错的选择。
  • 不知道 Selenium 有 R 绑定。酷!
【解决方案2】:

感谢 jdharrison 的评论,我解析了 javascript 代码以提取所有选择器。正如 Peyton 所提到的,这在这种特殊情况下有效,因为所有选择器都在代码中。

capture.output(xpathSApply(doc,'//*/script')[[6]],
               file='test.js')
ll <- readLines('test.js')
ll <- ll[grepl('w3Sels.push',ll)]
ll <- unlist(regmatches(ll, gregexpr("(?<=\\().*?(?=\\))", ll, perl=T)))

 cat(head(ll))
"#Lastname" ".intro" ".intro, #Lastname" "h1" "h1, p" "p:first"

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-26
    • 1970-01-01
    • 1970-01-01
    • 2021-02-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多