【数据获取】爬虫利器Rvest包

【数据获取】爬虫利器Rvest包

说在前面

如果读过了上一篇文章,应该对Rcurl和XML包进行爬虫有了一定得了解。实际上,这个组合虽然功能强大,但是经常会出一点意想不到的小问题。这篇文章我将介绍更便捷的Rvest包真正的快速爬取想要的数据。

主要内容

还是以上篇文章的豆瓣图书 Top250为例,我们只需要以下几行代码就可以实现与上文一样的效果:

library(rvest)
web<-read_html("https://book.douban.com/top250?icn=index-book250-all",encoding="UTF-8")
position<-web %>% html_nodes("p.pl") %>% html_text()

逐行解读一下。

第一行是加载Rvest包。

第二行是用read_html函数读取网页信息(类似Rcurl里的getURL),在这个函数里只需写清楚网址和编码(一般就是UTF-8)即可。

第三行是获取节点信息。用%>%符号进行层级划分。web就是之前存储网页信息的变量,所以我们从这里开始,然后html_nodes()函数获取网页里的相应节点。在下面代码里我简单的重现了原网页里的一个层级结构。可以看到,实际上我们要爬取的信息在25个class属性为pl的<p>标签里的文本。


<p class=pl>
       [清] 曹雪芹 著 / 人民文学出版社 / 1996-12 / 59.70元    
</p>

而对于这样的结构,在htmlnodes()函数里的写法就是简单的 "p.pl",其中“.”表示class属性的值,如果是id属性则用“#”,如果大家学过CSS选择器就很好理解了,是完全一致的。

最后我们用html_text()函数表示获取文本信息,否则返回的是整个<p>标签。总体上用以下一行代码就可以实现:

position<-web %>% html_nodes("p.pl") %>% html_text()

比较与XML获取节点的方法(如下行代码),其实二者是异曲同工的,只不过将“/”分隔换为了“%>%”,同时个别写法有些许调整。

node<-getNodeSet(pagetree, "//p[@class='pl']/text()")

最终如果我们打印出这个变量的内容,就会发现和上篇文章中的爬取内容是一致的:

> position
 [1] "[美] 卡勒德·胡赛尼 / 李继宏 / 上海人民出版社 / 2006-5 / 29.00元"    
 [2] "[法] 圣埃克苏佩里 / 马振聘 / 人民文学出版社 / 2003-8 / 22.00元"     
 [3] "钱锺书 / 人民文学出版社 / 1991-2 / 19.00"                           
 [4] "余华 / 南海出版公司 / 1998-5 / 12.00元"                             
 [5] "[日] 东野圭吾 / 刘姿君 / 南海出版公司 / 2008-9 / 29.80元"           
 [6] "[日] 村上春树 / 林少华 / 上海译文出版社 / 2001-2 / 18.80元"         
 [7] "(日)东野圭吾 / 李盈春 / 南海出版公司 / 2014-5 / 39.50元"            
 [8] "[捷克] 米兰·昆德拉 / 许钧 / 上海译文出版社 / 2003-7 / 23.00元"      
 [9] "[清] 曹雪芹 著 / 人民文学出版社 / 1996-12 / 59.70元"                
[10] "刘慈欣 / 重庆出版社 / 2008-1 / 23.00"                               
[11] "郭敬明 / 春风文艺出版社 / 2003-11 / 20.00元"                        
[12] "[美] 丹·布朗 / 朱振武 / 上海人民出版社 / 2004-2 / 28.00元"          
[13] "[日] 东野圭吾 / 刘子倩 / 南海出版公司 / 2008-9 / 28.00"             
[14] "韩寒 / 国际文化出版公司 / 2010-9 / 25.00元"                         
[15] "柴静 / 广西师范大学出版社 / 2013-1-1 / 39.80元"                     
[16] "顾漫 / 朝华出版社 / 2007-4 / 15.00元"                               
[17] "[英] 夏洛蒂·勃朗特 / 世界图书出版公司 / 2003-11 / 18.00元"          
[18] "路遥 / 人民文学出版社 / 2005-1 / 64.00元"                           
[19] "[英] J. K. 罗琳 / 苏农 / 人民文学出版社 / 2000-9 / 19.50元"         
[20] "[哥伦比亚] 加西亚·马尔克斯 / 范晔 / 南海出版公司 / 2011-6 / 39.50元"
[21] "[美国] 玛格丽特·米切尔 / 李美华 / 译林出版社 / 2000-9 / 40.00元"    
[22] "李可 / 陕西师范大学出版社 / 2007-9 / 26.00元"                       
[23] "韩寒 / 作家出版社 / 2000-5 / 16.00"                                 
[24] "刘瑜 / 上海三联书店 / 2010-1 / 25.00元"                             
[25] "张爱玲 / 花城出版社 / 1997-3-1 / 11.00"      

想要学习更多,我们可以在Rstudio里的命令行输入如下代码查询html_nodes()函数的相关用法:

?html_nodes

Rvest这个包的说明文档里给出了一些其他例子:

ateam <- read_html("http://www.boxofficemojo.com/movies/?id=ateam.htm")

ateam %>% html_nodes("center") %>% html_nodes("td")
ateam %>% html_nodes("center") %>% html_nodes("font")

library(magrittr)
ateam %>% html_nodes("table") %>% extract2(1) %>% html_nodes("img")
ateam %>% html_nodes("table") %>% `[[`(1) %>% html_nodes("img")

ateam %>% html_nodes("table") %>% `[`(1:2) %>% html_nodes("img")
ateam %>% html_nodes("table") %>% extract(1:2) %>% html_nodes("img")

下面也一并讲解一下:

ateam <- read_html("http://www.boxofficemojo.com/movies/?id=ateam.htm")

首先,所有的例子都是基于同一个网站,我们把这个网站存储在ateam变量里。

然后下面两行代码分别获取了ateam这个网页里<center>标签里<td>的全部内容和<center>标签里<font>的全部内容

ateam %>% html_nodes("center") %>% html_nodes("td")
ateam %>% html_nodes("center") %>% html_nodes("font")

运行结果如下,可见<center>标签下有7个<td>标签,一个<font>标签:


{xml_nodeset (7)}
[1] <td align="center" colspan="2">\n  <font size="4">Domestic Total Gross: <b>$77,222, ...
[2] <td valign="top">Distributor: <b><a href="/studio/chart/?studio=fox.htm">Fox</a></b ...
[3] <td valign="top">Release Date: <b><nobr><a href="/schedule/?view=bydate&amp;release ...
[4] <td valign="top">Genre: <b>Action</b></td>
[5] <td valign="top">Runtime: <b>1 hrs. 57 min.</b></td>
[6] <td valign="top">MPAA Rating: <b>PG-13</b></td>
[7] <td valign="top">Production Budget: <b>$110 million</b></td>

{xml_nodeset (1)}
[1] <font size="4">Domestic Total Gross: <b>$77,222,099</b></font>

接着官方例子中还给出了获取特定序位的html标签的方法,用到了magrittr包里的extract2函数:

library(magrittr)
ateam %>% html_nodes("table") %>% extract2(1) %>% html_nodes("img")
ateam %>% html_nodes("table") %>% `[[`(1) %>% html_nodes("img")

上面两行代码都可以获得该网页中第一个<table>标签(由extract2(1)或`[[`(1)获取)中的所有<img>标签里的内容,运行结果如下:


{xml_nodeset (6)}
[1] <img src="https://images-na.ssl-images-amazon.com/images/M/MV5BMTc4ODc4NTQ1N15BMl5B ...
[2] <img src="http://www.assoc-amazon.com/e/ir?t=boxofficemojo-20&amp;l=as2&amp;o=1&amp ...
[3] <img src="http://www.assoc-amazon.com/e/ir?t=boxofficemojo-20&amp;l=as2&amp;o=1&amp ...
[4] <img src="/img/misc/bom_logo1.png" width="245" height="56" alt="Box Office Mojo"/>
[5] <img src="/img/misc/IMDbSm.png" width="34" height="16" alt="IMDb" valign="middle"/>
[6] <img src="http://b.scorecardresearch.com/p?c1=2&amp;c2=6034961&amp;cv=2.0&amp;cj=1"/>

同理我们也可以获得网页里前两个<table>标签储存的所有<img>标签里的内容:

ateam %>% html_nodes("table") %>% `[`(1:2) %>% html_nodes("img")
ateam %>% html_nodes("table") %>% extract(1:2) %>% html_nodes("img")

本篇文章就到此为止了,之后我将继续讲解关于正则以及R中stringr包的相关内容,对获取的字符串进行进一步的处理操作。

结语

更多内容请关注我的专栏:R语言与数据挖掘 - 知乎专栏

或关注我本人知乎主页:温如

编辑于 2016-11-17

文章被以下专栏收录