如果把XML看作传统的关系数据库,那么XPath就是SQL。R语言中的XML包可用来解析处理XML或是HTML数据。在之前的文章中,我们了解到readHTMLTable函数,如果页面中的数据是一个规整的表格,用它是很方便的,但如果页面中是一些非结构化的数据,就要用到XML包中的其它函数了。其中最重要两个函数是xmlTreeParse()和getNodeSet(),前者负责抓取页面数据并形成树状结构,后者对抓取的数据根据XPath语法来选取特定的节点集合。下面用一个简单的例子来看一下这两个函数配合使用的效果。
这里是一个简单的XML文档,下面是一些简单的节点选取操作:
library(XML) # 解析XML文件 doc <- xmlParse('http://www.w3school.com.cn/example/xmle/books.xml') # 选取属于 bookstore 子元素的第一个 book 元素 getNodeSet(doc,'/bookstore/book[1]') # 选取属于 bookstore 子元素的最后一个 book 元素。 getNodeSet(doc,'/bookstore/book[last()]') # 选取最前面的两个属于 bookstore 元素的子元素的 book 元素 getNodeSet(doc,'/bookstore/book[position()<3]') # 选取所有拥有名为 lang 的属性的 title 元素。 getNodeSet(doc,'//title[@lang]') #选取所有 title 元素,且这些元素拥有值为 eng 的 lang 属性 getNodeSet(doc,"//title[@lang='eng']") # 选取 bookstore 元素的所有 book 元素,且其中的 price 元素的值须大于 35.00。 getNodeSet(doc,"/bookstore/book[price>35.00]") # 选取 bookstore 元素中的 book 元素的所有 title 元素,且 price 元素的值须大于 35.00。 getNodeSet(doc,"/bookstore/book[price>35.00]/title") # 选取 book 元素的所有 title 和 price 元素 getNodeSet(doc,"//book/title | //book/price") # 选取文档中的所有 title 和 price 元素 getNodeSet(doc,"//title | //price") # 选取 bookstore 元素的所有子元素 getNodeSet(doc,"/bookstore/*") # 选取所有带有属性的 title 元素 getNodeSet(doc,"//title[@*]") # 选择所有属性lang的值 unlist(getNodeSet(doc,"//title/@lang"),use.names = FALSE) # title结点下的所有文本 getNodeSet(doc,"//title/text()")
如果你比较习惯操作R,也可以用xmlToList转成list格式再说。如果说XML的结构比较简单,我们可以使用xmlToDataFrame直接将其转为R语言中的data.frame。下面再来看一个操作豆瓣API的例子和其它一些有用的函数。 # 豆瓣的例子 url <- 'http://api.douban.com/movie/subject/imdb/tt0111161' # 解析获得树结构数据 doc <- xmlTreeParse(url,useInternal=TRUE,encoding="UTF-8") # 获得根结点信息 top <- xmlRoot(doc) # 获取子节点 top[[5]] # 子节点名称 xmlName(top[[5]]) # 按名字取子节点 top[['author']] # 与上一命令相同 xmlChildren(top)[['author']] # 显示子节点数量 xmlSize(top) # 获取节点元素 xmlValue(top[['author']]) # 获取节点属性 xmlAttrs(top[[5]]) #获取节点属性值 xmlGetAttr(top[[5]],name='href') # 向量化操作,获取所有子结点的名字 sapply(xmlChildren(top), xmlName) # 使用专门的xmlSApply函数,等价于上一条 xmlSApply(top, xmlName) # 使用xpath语法进行XML查询 # 找出合乎条件的节点,例如找出所有主演的节点集合 (node <- getNodeSet(top, path="//db:attribute[@name='cast']")) # 然后取出其中的元素 sapply(node,xmlValue) # 也可以从根节点一步操作得到结果 (cast <- xpathSApply(top, path="//db:attribute[@name='cast']", xmlValue)) # 取出link节点中的属性和属性值 # 定义命名空间,再使用前述函数 namespaces <- c(ns='http://www.w3.org/2005/Atom') getNodeSet(top, "//ns:link", namespaces) xpathSApply(top, "//ns:link", fun=xmlAttrs, namespaces=namespaces) xpathApply(top, "//ns:link", fun=xmlGetAttr, 'href', namespaces=namespaces)
没有评论:
发表评论