我正在抓取以下网站:http://en.wikipedia.org/wiki/List_of_Presidents_of_the_United_States
让我们说我有兴趣刮掉第四任总统 - 我可以从桌子上看到它是詹姆斯·麦迪逊"。使用Chrome浏览器,我可以快速识别Xpath(Inspect元素,复制XPath)。这给了我:" // * [@ id =' mw-content-text'] / table [1] / tbody / tr [7] / td [2] / b / A &#34 ;.但是,这不适用于R:
library(XML)
url <- "http://en.wikipedia.org/wiki/List_of_Presidents_of_the_United_States"
html <- htmlTreeParse(url,useInternalNodes=T)
xpath <- paste("//*[@id='mw-content-text']/table[1]/tbody/tr[7]/td[2]/b/a",sep="")
xpathSApply(html, xpath, xmlValue)
返回NULL。这里使用的正确XPath是&#34; // * [@ id =&#39; mw-content-text&#39;] / table [1] / tr [7] / td [2] / b / A &#34 ;.所以我的问题是:
谢谢!
答案 0 :(得分:2)
事实证明 html中没有tbody
标记。这是由浏览器添加的。基本上,Chrome推荐的xpath是错误的。
library(httr)
grepl("table",content(GET(url),type="text"))
# [1] TRUE
grepl("tbody",content(GET(url),type="text"))
# [1] FALSE
注意::不建议使用正则表达式解析html !!!
问题出现是因为浏览器被设计为相对宽容不正确格式化的html。因此,如果标记明确丢失,浏览器会添加它(例如,如果您发送的页面没有正文标记,则无论如何都会呈现,因为浏览器在加载页面后将标记添加到DOM)。 htmlParse(...)
不起作用:它只是加载和解析服务器响应。 HTML 4规范中的表需要tbody标记,因此浏览器会添加它。有关说明,请参阅this post。
因此,以“半自动”方式处理此问题的一种方法是:
xpath <-paste("//*[@id='mw-content-text']/table[1]/tbody/tr[7]/td[2]/b/a",sep="")
if (length(html["//tbody"])==0) xpath <- gsub("/tbody","",xpath)
xpathSApply(html, xpath, xmlValue)
# [1] "James Madison"
答案 1 :(得分:1)
我建议使用selectr
包,它允许你使用CSS样式选择器而不是XPath,这有时会很痛苦。或者,由于您正在寻找一个表,我建议使用readHTMLTable
函数自动擦除页面的所有表。
library(XML)
library(selectr)
url <- "http://en.wikipedia.org/wiki/List_of_Presidents_of_the_United_States"
doc <- htmlParse(url)
tab <- querySelector(doc, 'table.wikitable')