我不明白为什么这段代码
library(rvest)
u <- "http://alistapart.com/article/daemonskin"
h <- read_html(u)
html_nodes(h, "div.main-content[itemprop='articleBody'] a") %>%
html_attr("href")
匹配超出目标<div>
元素范围的许多网址。
如果您查看target page的HTML源代码:
<div>
符合我的查询。它从第177行开始。<div>
在第396行停止。html_nodes
返回的许多网址都是从该行<div>
之外的节点中提取的。 注意:您可能会注意到,在HTML的第242行,存在错误的</div
元素。但是,修复它似乎无法解决问题。
我想这个问题与xml2
(即libxml2
)解析代码的方式有关。
还有其他想法吗?
答案 0 :(得分:1)
嗯,主问题是网站上制作不当,不合规的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
库是&#34;修复&#34;轻微的HTML(XML)错误,并有自己的做事方式。由于解析器&#34;固定&#34;的方式,这种方式会导致更多元素置于特定<div>
您的目标之下。 HTML。
您可以看到真实浏览器的结果与我们可以用硒模拟的结果的区别:
注意:我在R
之外的webdriver模式下启动了phantomjslibrary(seleniumPipes)
rd <- remoteDr(browserName = "phantomjs", port = 8910)
rd %>% go(URL)
当你这样做时,它的幻像(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
已经rd %>%
go(URL) %>%
getPageSource() %>%
html_nodes("div.main-content[itemprop='articleBody'] a") %>%
html_attr("href") %>%
str()
## chr [1:32] "#comments" ...
对理论上已经清理过的webkit应用了一些额外的修复:
<!-- navbar-->
<nav class="navbar navbar-default">
<div class="container-fluid">
<a href="#" class="navbar-header navbar-brand">MYSITE</a>
<ul class="nav navbar-nav">
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Tags <span class="caret"></span></a>
<ul class="dropdown-menu">
<li><a href="#">menu1</a></li>
<li><a href="#">menu2</a></li>
<li><a href="#">menu3</a></li>
<li><a href="#">menu4</a></li>
<li><a href="#">menu5</a></li>
<li><a href="#">menu6</a></li>
<li><a href="#">menu7</a></li>
<li><a href="#">menu8</a></li>
<li><a href="#">menu9</a></li>
<li><a href="#">menu10</a></li>
<li><a href="#">menu11</a></li>
<li><a href="#">menu12</a></li>
<li><a href="#">menu13</a></li>
<li><a href="#">menu14</a></li>
<li><a href="#">menu15</a></li>
<li><a href="#">menu16</a></li>
<li><a href="#">menu17</a></li>
<li><a href="#">menu18</a></li>
<li><a href="#">menu19</a></li>
</ul>
</li>
</ul>
</div>
</nav>