使用 xml 和 r 解析元 name/content

parsing meta name/content using xml and r

关于以下问题的答案:how to get information within <meta name...> tag in html using htmlParse and xpathSApply

我的问题:

html <- htmlParse(domain, useInternalNodes=T);
names <- html['//meta/@name']
content <- html['//meta/@content']

cbind(names, content)

页面中的元标记是:

<meta name="description" content="blah, blah...." />
<meta name="keywords" content="keyword1, keyword2" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta name="google-site-verfication" content="1234jalsdkfjasdf928374-293423" />

我找到的是这样的:

 length(names)
[1] 3

length(content)
[1] 4

names                                     content
[1, ] "description"                       [1, ] "blah, blah...."
[2, ] "keywords"                          [2, ] "keyword1, keyword2"
[3, ] "google-site-verification"          [3, ] "text/html; charset=UTF-8"
[4, ] "description"                       [4, ] "1234jalsdkfjasdf928374-293423"

似乎解析器在 "http-equiv" 上出错并返回 next 代码行 "google-site-verification" 但仍然返回 "content" "http-equiv",然后因为没有更多的 "names",cbind 再次环绕到 "description" 以匹配最后一行内容,即实际的 "google-site-verification"。 似乎是一个简单的修复,到目前为止,我所做的任何条件都不起作用,我怎样才能做到这一点?

我知道你想出了你需要的东西(这与原来的 q 不匹配)但我们将以 whosebug.com 为例,因为我已经将它编码为我的补充原答案:

library(XML)

doc <- htmlParse("http://whosebug.com/", useInternalNodes=TRUE)

具有以下 <meta> 个标签:

<meta name="twitter:card" content="summary">
<meta name="twitter:domain" content="whosebug.com"/>
<meta property="og:type" content="website" />
<meta property="og:image" itemprop="image primaryImageOfPage" content="http://cdn.sstatic.net/Whosebug/img/apple-touch-icon@2.png?v=fde65a5a78c6" />
<meta name="twitter:title" property="og:title" itemprop="title name" content="Stack Overflow" />
<meta name="twitter:description" property="og:description" itemprop="description" content="Q&amp;A for professional and enthusiast programmers" />
<meta property="og:url" content="http://whosebug.com/"/>

并非每个标签都有 name 属性,实际上在 7 个标签中,只有 4 个:

length(doc["//meta/@property"])
## [1] 4

注意这与做的一样:

length(xpathSApply(doc, "//meta/@name"))
## [1] 4

这几乎就是幕后发生的事情。

它只会返回搜索中的真实信息。如果你这样做,你可以看到它的布局:

xpathSApply(doc, "//meta", xmlGetAttr, "name")

## [[1]]
## [1] "twitter:card"
## 
## [[2]]
## [1] "twitter:domain"
## 
## [[3]]
## NULL
## 
## [[4]]
## NULL
## 
## [[5]]
## [1] "twitter:title"
## 
## [[6]]
## [1] "twitter:description"
## 
## [[7]]
## NULL

由于 NULLs,该列表在转换为向量时会截断为 4 个条目。 rvest(原始答案在提取时只是 "smarter"。

原始答案

使用 rvest,您可以非常快速地将所有 <meta> 属性抓取到数据框中(如果这就是您想要做的):

library(rvest)
library(dplyr)

pg <- html("http://facebook.com/")

all_meta_attrs <- unique(unlist(lapply(lapply(pg %>% html_nodes("meta"), html_attrs), names)))

dat <- data.frame(lapply(all_meta_attrs, function(x) {
  pg %>% html_nodes("meta") %>% html_attr(x)
}))

colnames(dat) <- all_meta_attrs

glimpse(dat)

## Observations: 19
## Variables:
## $ charset    (fctr) utf-8, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA...
## $ http-equiv (fctr) NA, refresh, NA, NA, NA, NA, NA, NA, NA, NA, NA, ...
## $ content    (fctr) NA, 0; URL=/?_fb_noscript=1, default, Facebook, h...
## $ name       (fctr) NA, NA, referrer, NA, NA, NA, NA, NA, NA, NA, NA,...
## $ id         (fctr) NA, NA, meta_referrer, NA, NA, NA, NA, NA, NA, NA...
## $ property   (fctr) NA, NA, NA, og:site_name, og:url, og:image, og:lo...

但它也会可靠地为您提取属性:

pg %>% html_nodes("meta") %>% html_attr("http-equiv")

##  [1] NA                "refresh"         NA               
##  [4] NA                NA                NA               
##  [7] NA                NA                NA               
## [10] NA                NA                NA               
## [13] NA                NA                NA               
## [16] NA                NA                NA               
## [19] "X-Frame-Options"

所以我想通了,至少我想通了。最终我只需要提取 "keywords" 和 "descriptions"。需要更改的代码是:

这个……

html <- htmlParse(domain, useInternalNodes=T);
names <- html['//meta/@name']
content <- html['//meta/@content']

对此...

html <- htmlParse(domain, useInternalNodes=T);
**keywords <- html['//meta[@name="keywords"]/@content']
description <- html['//meta[@name="description"]/@content']**

干杯