以下翻译自:rdom包github项目主页
R语言rdom包简介
在R中,通过调用phantomjs无头浏览器来渲染和解析DOM(文档对象模型)。
安装
rdom包的使用依赖于phantomjs,因此请保证已安装该浏览器(参考Selenium环境配置第5部分),并将存放路径添加到系统变量中。
stopifnot(Sys.which("phantomjs") != "")
# 检测系统路径中是否含有phantomjs,若未下载,或已下载但未添加系统路径都会导致报错
目前rdom包尚未在CRAN上发布,可以通过devtools包安装。
devtools::install_github("cpsievert/rdom")
简介
诸如XML、xml2及rvest等爬虫包能够帮助我们直接从url下载并解析HTML文件。但是这些包的工作原理中,缺少一个中介浏览器引擎对DOM进行渲染。为了展示这种差异,假设我们现在想要提取如下HTML页面中的表格:
XML::htmlParse()
和rvest::read_html()
返回的是HTML页面下的静态源代码,其中并不包括我们想要的<table>
元素(因为JavaScript会时刻改变DOM的状态):
XML::htmlParse("http://bl.ocks.org/cpsievert/raw/2a9fb8f504cd56e9e8e3/")
<!DOCTYPE html>
<html><body>
A Simple Table made with JavaScript
<p></p>
<script>
function tableCreate(){
var body = document.body,
tbl = document.createElement('table');
for(var i = 0; i < 3; i++){
var tr = tbl.insertRow();
for(var j = 0; j < 3; j++){
var td = tr.insertCell();
td.appendChild(document.createTextNode("Cell"));
}
}
body.appendChild(tbl);
}
tableCreate();
</script>
</body></html>
rdom包中最主要的函数是rdom()
,它通过调用phantomjs来渲染和解析DOM,得到HTML字符串。用户可以通过rdom()函数,设定一个CSS(路径)选择器用以提取某些元素,而不是将整个DOM以字符串的形式从phantomjs直接传回R。
tbl <- rdom::rdom("http://bl.ocks.org/cpsievert/raw/2a9fb8f504cd56e9e8e3/", css = "table")
tbl
<table>
<tbody>
<tr>
<td>Cell</td>
<td>Cell</td>
<td>Cell</td>
</tr>
<tr>
<td>Cell</td>
<td>Cell</td>
<td>Cell</td>
</tr>
<tr>
<td>Cell</td>
<td>Cell</td>
<td>Cell</td>
</tr>
</tbody>
</table>
在这种情况下,我们就可以用XML::readHTMLTable()
或rvest::html_table()
将<table>
节点转换为数据框形式。
XML::readHTMLTable(tbl)
V1 V2 V3
1 Cell Cell Cell
2 Cell Cell Cell
3 Cell Cell Cell
渲染shiny app
rdom包的另外一个有趣的示例是渲染(及测试)shiny app。
library(shiny)
runExample("01_hello")
Listening on http://127.0.0.1:4870
现在,在另一个R会话窗口中,将这个url传递给rdom()。在本案例中,我们仅返回app的标题。
header <- rdom::rdom("http://127.0.0.1:4870", "h2")
<h2>Hello Shiny!</h2>
如此一来,测试shiny app就变得轻而易举。
library("testthat")
expect_identical(XML::xmlValue(header), "Hello Shiny!")
使用CLI
rdom()实质上是对phantomjs命令行界面的封装。因此,如果你的任务无需用到R语言,那么使用CLI可能更加高效。
$ git clone https://github.com/cpsievert/rdom.git
$ cd rdom
$ phantomjs inst/rdomjs/rdom.js inst/jsTable/jsTable.html table false 1 table.html
$ vi table.html
rdom.js
脚本遵循如下四个参数:
url
: 网页的URL地址(必要参数)css
:CSS选择器all
:此参数决定从页面中抓取元素时,是采用querySelector还是采用querySelectorAlltimeout
: 下载和渲染页面的最长等待时间,以秒为单位filename
:将HTML字符串写入文件
每次调用rdom()时,都会启动phantomjs进程,phantomjs浏览器会打开并充分渲染指定站点。
致谢
感谢webshot包的开发者Winston Chang,启发了rdom包的设计。