使用 XML / RCurl R 包解析 HTML 表,而不使用 readHTMLTable 函数
Posted
技术标签:
【中文标题】使用 XML / RCurl R 包解析 HTML 表,而不使用 readHTMLTable 函数【英文标题】:Parsing HTML tables using the XML / RCurl R packages, without using the readHTMLTable function 【发布时间】:2011-09-19 14:26:59 【问题描述】:我正在尝试从http://www.theplantlist.org/tpl/record/kew-419248 和许多非常相似的页面上的单个 html 表中抓取/提取数据。 我最初尝试使用以下函数来读取表格,但这并不理想,因为我想将每个物种名称分成其组成部分(属/物种/亚种/作者等)。
library(XML)
readHTMLTable("http://www.theplantlist.org/tpl/record/kew-419248")
我使用 SelectorGadget 为我要提取的每个表元素标识一个唯一的 XPATH(不一定是最短的):
对于属名: //[contains(concat( " ", @class, " " ), concat( " ", "Synonym", " " ))]// [包含(concat(“”,@class,“”),concat(“”,“属”,“”))]
对于物种名称: //[contains(concat( " ", @class, " " ), concat( " ", "Synonym", " " ))]//[contains( concat( " ", @class, " "), concat(" ", "species", " "))]
对于亚种等级: //*[contains(concat( " ", @class, " " ), concat( " ", "infraspr", " " ))]
对于基础物种名称: //*[contains(concat( " ", @class, " " ), concat( " ", "infraspe", " " ))]
对于置信度(图像): //[contains(concat( " ", @class, " " ), concat( " ", "synonyms", " " ))]//img 对于来源: //[contains(concat( " ", @class, " "), concat(" ", "source", " "))]//a
我现在想将信息提取到数据框/表格中。
我尝试使用 XML 包的 xpathSApply 函数来提取其中一些数据:
例如对于亚种等级
library(XML)
library(RCurl)
infraspeciesrank = htmlParse(getURL("http://www.theplantlist.org/tpl/record/kew-419248"))
path=' //*[contains(concat( " ", @class, " " ), concat( " ", "infraspr", " " ))]'
xpathSApply(infraspeciesrank, path)
但是,由于数据中的间隙,此方法存在问题(例如,表中只有某些行具有亚种等级,所以我返回的只是表中三个等级的列表,没有间隙)。数据输出也是我无法附加到数据框的类。
有谁知道从该表中提取信息到数据框中的更好方法?
任何帮助将不胜感激!
汤姆
【问题讨论】:
快速建议:将完整的 HTML 作为字符串读取,然后简单地应用正则表达式(根据我的经验,HTML 很容易受到这种影响)。先用表隔离部分,再做子结构... 【参考方案1】:这是另一种解决方案,它将每个物种名称拆分为其组成部分
library(XML)
library(plyr)
# read url into html tree
url = "http://www.theplantlist.org/tpl/record/kew-419248"
doc = htmlTreeParse(url, useInternalNodes = T)
# extract nodes containing desired information
xp_expr = "//table[@class= 'names synonyms']/tbody/tr"
nodes = getNodeSet(doc, xp_expr)
# function to extract desired fields from a given node
fields = list('genus', 'species', 'infraspe', 'authorship')
read_node = function(node)
dl = lapply(fields, function(x) xpathSApply(node,
paste(".//*[@class = ", "'", x, "'", "]", sep = ""), xmlValue))
tmp = rep(' ', length(dl))
tmp[sapply(dl, length) == 1] = unlist(dl)
confidence = xpathSApply(node, './/img', xmlGetAttr, 'alt')
return(c(tmp, confidence))
# apply function to all nodes and return data frame
df = ldply(nodes, read_node)
names(df) = c(fields, 'confidence')
它产生以下输出
genus species infraspe authorship confidence
1 Critesion chilense (Roem. & Schult.) Ã\u0081.Löve H
2 Hordeum chilense chilense L
3 Hordeum cylindricum Steud. H
4 Hordeum depauperatum Steud. H
5 Hordeum pratense brongniartii Macloskie L
6 Hordeum secalinum chilense Ã\u0089.Desv. L
【讨论】:
当我尝试运行此代码时,出现以下错误: UseMethod("xpathApply") 中的错误:没有适用于“XMLNodeSet”类对象的“xpathApply”方法 确保更新您的XML
和 plyr
软件包版本。我检查了代码,它仍然对我有用。【参考方案2】:
以下代码将您的表格解析为矩阵。
注意事项:
置信度列是空白的,因为这不是文本而是图像。如果这很重要,您应该能够检索图像位置并对其进行解析。 存在一些编码问题(UTF-8 字符在我的机器上被转换为 ASCII)。我还不知道如何解决这个问题。代码:
library(XML)
library(RCurl)
baseURL <- "http://www.theplantlist.org/tpl/record/kew-419248"
txt <- getURL(url=baseURL)
xmltext <- htmlParse(txt, asText=TRUE)
xmltable <- xpathApply(xmltext, "//table//tbody//tr")
t(sapply(xmltable, function(x)unname(xmlSApply(x, xmlValue))[c(1, 3, 5, 7)]))
结果:
[,1] [,2] [,3] [,4]
[1,] "Critesion chilense (Roem. & Schult.) Ã.Löve" "Synonym" "" "WCSP"
[2,] "Hordeum chilense var. chilense " "Synonym" "" "TRO"
[3,] "Hordeum cylindricum Steud. [Illegitimate]" "Synonym" "" "WCSP"
[4,] "Hordeum depauperatum Steud." "Synonym" "" "WCSP"
[5,] "Hordeum pratense var. brongniartii Macloskie" "Synonym" "" "WCSP"
[6,] "Hordeum secalinum var. chilense Ã.Desv." "Synonym" "" "WCSP"
【讨论】:
您好,非常感谢您的建议!理想情况下,我想将名称拆分为其每个组成部分,如下面的 Ramnath 示例,但很高兴看到另一种方法!以上是关于使用 XML / RCurl R 包解析 HTML 表,而不使用 readHTMLTable 函数的主要内容,如果未能解决你的问题,请参考以下文章