用R快速找到一个Xpath

时间:2014-04-27 21:13:23

标签: r xpath web-scraping

我正在抓取以下网站: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 ;.所以我的问题是:

  1. 如何更改R中的设置,以便R看到与我的Chrome浏览器相同的XPath?我相信它与http用户代理有关吗? This post提出了类似的问题,但答案并没有提供足够的细节。
  2. 如果无法做到这一点,我怎样才能使用XML包来快速识别正确的XPath,从而导致詹姆斯麦迪逊&#34;? ie&#34; // * [@ id =&#39; mw-content-text&#39;] / table [1] / tr [7] / td [2] / b / a &#34;
  3. 谢谢!

2 个答案:

答案 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')