嗯,主要问题是网站上的 HTML 设计不佳、不合规,该网站以在这方面实际上比其他人更聪明而自豪。
当你这样做时:
library(rvest)
library(purrr)
URL <- "http://alistapart.com/article/daemonskin"
read_html(URL) %>%
html_nodes("div.main-content[itemprop='articleBody'] a") %>%
html_attr("href") %>%
str()
## chr [1:74] "#comments" ...
底层libxml2
库正在“修复”轻微的 HTML (XML) 错误,并且有自己的处理方式。由于解析器“修复” HTML 的方式,这种方式会导致更多元素位于<div>
您所定位的特定元素下。
您可以看到与真实浏览器结果的差异,我们可以使用 selenium 进行模拟:
注意:我在 R 之外的 webdriver 模式下启动了 phantomjs
library(seleniumPipes)
rd <- remoteDr(browserName = "phantomjs", port = 8910)
rd %>% go(URL)
当你这样做时,它是 phantomjs(实际上是 webkit)将它自己的基于浏览器的 HTML 解析器修复方法应用到它接收到的 HTML(并且,它还根据页面加载时的任何 javascript 触发器添加或减去节点)。
当您使用等价物document.querySelectorAll()
检索节点时,您会得到 34 个(这也是我在开发者工具控制台中的 Chrome 中得到的):
rd %>%
findElements("css", "div.main-content[itemprop='articleBody'] a") %>%
map_chr(getElementAttribute, "href") %>%
str()
## chr [1:34] "http://alistapart.com/article/daemonskin#comments" ...
请注意,如果您决定做我通常做getPageSource()
的事情并用于通过rvest
/xml2
函数进行所有选择/提取,您将得到不同的结果,因为它从虚拟浏览器中提取当前 HTML 页面并将其传递给read_html()
应用libxml2
了一些对 webkit 理论上已经清理的内容的附加修复:
rd %>%
go(URL) %>%
getPageSource() %>%
html_nodes("div.main-content[itemprop='articleBody'] a") %>%
html_attr("href") %>%
str()
## chr [1:32] "#comments" ...