查看原文
其他

R爬虫必备——rvest包的使用

YJY YJY技能修炼 2022-08-15
上一期R爬虫必备——静态网页+动态网页简单介绍了网页的类型。在实际R爬虫过程中,针对不同的网页,采取的爬虫方法也会有所不同。通常情况下,R爬虫涉及的R包主要有3个:rvest、Rcurl和httr。
  1. rvest抓取静态网页数据
所谓静态网页,就是你打开一个目标网页,在网页里可以直接看到想要抓取的数据,点击鼠标右键查看源代码后发现在HTML结构中可以在本地找到刚刚在网页里的目标数据,这就是静态网页。对于这样的网页,rvest可以提供一套较为完整的数据抓取方案,配上一些小工具,就可以快速实现爬虫。
  1. Rcurl/httr包实现对网页动态加载数据的抓取
对于网页动态加载的数据,继续使用rvest可能就不合适了。这时R提供了其他选择来实现相应的抓取目的。RCurl功能强大,但对初学者来说稍微有点难度。httr包相当于RCurl的精简版,相对轻巧易上手,功能虽不如RCurl那么齐全,但对于用户而言绝对友好。


今天呢,主要从最简单的静态网页抓取R包——rvest开始,这款R包抓取静态网页的逻辑非常清楚,初学者可以很快理解和上手。下面简单看一下rvest数据抓取的几个核心函数:

read_html():下载并解析网页html_nodes():定位并获取节点信息html_text():提取节点文本信息html_attr():提取节点属性信息

rvest的这些函数如何使用呢?下面我们来简单看个案例——rvest包爬取链家网二手房信息,包括房子名字,房子具体信息(房型、面积、楼层等信息),房子地址,房子总价,房子每平方米单价等信息。

简单点,只为演示作用, 仅爬取第一页:http://hz.lianjia.com/ershoufang/pg1。具体代码如下:

#加载所需的包:library("rvest")library("stringr")web <- read_html("http://hz.lianjia.com/ershoufang/pg1", encoding = "UTF-8")#提取房名信息:house_name <- web%>%html_nodes("div.info div.title a")%>%html_text()#提取房子详情链接:house_link <- web%>%html_nodes("div.info div.title a")%>%html_attrs("href")#提取房名基本信息并消除空格house_basic_inf <- web%>%html_nodes(".houseInfo")%>%html_text()house_basic_inf <- str_replace_all(house_basic_inf," ","")#提取二手房地址信息house_address <- web%>%html_nodes(".positionInfo a")%>%html_text()house_address <-house_address[seq(1,60,2)]#提取二手房总价信息house_totalprice <- web%>%html_nodes(".totalPrice")%>%html_text()#提取二手房单价信息house_unitprice <- web%>%html_nodes(".unitPrice span")%>%html_text()#创建数据框存储以上信息house<-data.frame(house_name,house_basic_inf,house_address,house_totalprice,house_unitprice)#将数据写入csv文档write.csv(house, file="../house.csv")

整个代码的逻辑关系是这样:read_html()获取整个网页信息;html_nodes()用来定位到相应节点;html_text()用于获取节点的文本内容;html_attrs()用于获取节点的属性值信息。如:

#read_html获取整个网页 web <- read_html("http://hz.lianjia.com/ershoufang/pg1", encoding = "UTF-8")#html_node获取包含房子名称的节点 tmp <- html_nodes(web,"div.info div.title a")#html_text获取该节点的文本信息house_name <- html_text(tmp)#html_attrs获取该节点的href属性信息house_link <- html_attr(tmp,"href")

为方便,信息的提取过程用“%>%”管道符加以连接,书写如下:

web <- read_html("http://hz.lianjia.com/ershoufang/pg1", encoding = "UTF-8")house_name <- web%>%html_nodes("div.info div.title a")%>%html_text()house_link <- web%>%html_nodes("div.info div.title a")%>%html_attr("href")


read_html()获取整个网页信息

如:web <- read_html("http://hz.lianjia.com/ershoufang/pg1", encoding = "UTF-8"),返回的就是网页源码信息。

web <- read_html("http://hz.lianjia.com/ershoufang/pg1", encoding = "UTF-8")web#{xml_document}#<html>#[1] <head>\n<meta http-equiv="Content-Type" content="text/html; charset=utf-8">\n< ...#[2] <body>\n<script type="application/ld+json">{"@context": "https://ziyuan.baidu. ...
  • 在read_html()函数使用中,输入要爬取的网址以及编码格式,前者相信大家都没有问题,第二个网页的编码格式该如何判断呢?打开相应网页,然后右击,审查元素,打开网页源码,在源码中找到head标签,点开他,查找“Content Type”这样的字眼,在其后往往会带有“charset=xxxxxx”这样的描述。如下图,charset=utf-8,这表示该网页采用的是UTF-8的编码格式。


html_nodes()定位到相应节点

如:tmp <- html_nodes(web, "div.info div.title a") ,返回值是"div.info div.title a"这个节点的信息,这个节点包含有房子的名字和详情链接信息。

tmp <- html_nodes(web, "div.info div.title a")tmp# {xml_nodeset (30)}# [1] <a class="" href="https://hz.lianjia.com/ershoufang/103109543956.html" target ...# [2] <a class="" href="https://hz.lianjia.com/ershoufang/103109306746.html" target ...# [3] <a class="" href="https://hz.lianjia.com/ershoufang/103108174516.html" target ...# [4] <a class="" href="https://hz.lianjia.com/ershoufang/103109219801.html" target ...# [5] <a class="" href="https://hz.lianjia.com/ershoufang/103107527889.html" target ...# [6] <a class="" href="https://hz.lianjia.com/ershoufang/103109328178.html" target ...# [7] <a class="" href="https://hz.lianjia.com/ershoufang/103109405297.html" target ...# [8] <a class="" href="https://hz.lianjia.com/ershoufang/103109234723.html" target ...# [9] <a class="" href="https://hz.lianjia.com/ershoufang/103109496556.html" target ...# [10] <a class="" href="https://hz.lianjia.com/ershoufang/103109299194.html" target ...# [11] <a class="" href="https://hz.lianjia.com/ershoufang/103108655599.html" target ...# [12] <a class="" href="https://hz.lianjia.com/ershoufang/103108551516.html" target ...# [13] <a class="" href="https://hz.lianjia.com/ershoufang/103109485194.html" target ...# [14] <a class="" href="https://hz.lianjia.com/ershoufang/103108968651.html" target ...# [15] <a class="" href="https://hz.lianjia.com/ershoufang/103109357513.html" target ...# [16] <a class="" href="https://hz.lianjia.com/ershoufang/103109578551.html" target ...# [17] <a class="" href="https://hz.lianjia.com/ershoufang/103109454329.html" target ...# [18] <a class="" href="https://hz.lianjia.com/ershoufang/103108832328.html" target ...# [19] <a class="" href="https://hz.lianjia.com/ershoufang/103109578729.html" target ...# [20] <a class="" href="https://hz.lianjia.com/ershoufang/103109450043.html" target ...# ...
  • html_nodes()这步是关键,可以得到待抓取数据的节点信息。html_nodes这个函数的输入值:一个是read_html函数获取的整个网页信息web,另一个是定位节点表达式:可以是CSS选择器表达式,或者XPath表达式。我们这里"div.info div.title a"采用的CSS选择器表达式,那如何构建CSS选择器表达式呢?下一期会具体介绍。


html_text()获取节点的文本内容

如:house_name <- html_text(tmp),获取节点下的文本信息,该文本信息就是房子的名称。

house_name <- html_text(tmp)house_name# [1] "新出!景溪北苑,精装好房,看房 方便," # [2] "精装修三房,满五年且唯一,看房方便,房东诚售" # [3] "滨江宝龙旁 精装修单身公寓 拎包入住 房东诚心出售" # [4] "满两年自住精装 边套大客厅 房东诚心出售" # [5] "房子满五年,精装修,边套,两房加开放式书房" # [6] "视野开阔,采光好,适合居住,小区新,D铁近,教育好" # [7] "此房视野开阔,一房朝南一房朝北,总价低,交通方便。"# [8] "临平山北 野风启城 房东诚心出售 中装修 价格实惠" # [9] "满2年,自住精装修,看房方便,诚心卖" # [10] "龙湖品质 地铁口 精装四房二卫 三阳台 诚心出售" # [11] "小区位置好楼层采光好,视野开阔,自住装修。" # [12] "国际城满两年刚需三房,双地铁,诚心卖可随时签约" # [13] "投/资和过度首/选,小面积、低总价、地铁口" # [14] "赞成林风标准三房,标准的3房2卫2阳台户型" # [15] "采光好 房东诚心卖 小区环境户型好通透,一眼即中." # [16] "荷塘极少户型, 本房满2,无增值税,户型方正," # [17] "融创品质 南北通透大阳台 中间楼层 诚心出售看房方便" # [18] "中间楼层 南面无楼幢 视野好 阳光足 装修清爽" # [19] "次新房、户型好、业主自住精装,随时看房,近地铁" # [20] "此房房东自住精装,拎包入住,夹边套经典户型" # [21] "税费少,总价低,刚需改善皆可。" # [22] "香樟名苑 三室二厅二卫一厨 有车库 价格面谈 带书房"# [23] "新出!房东诚心出售。价格可谈,看房随时" # [24] "房子 精装修 满俩年 带露台 阿里巴巴" # [25] "开发商精装修.未住人.户型通透.带小露台.拎包即住" # [26] "交通方便,南北通畅,配套设施齐全!" # [27] "此房视野开阔,一房朝南一房朝北,总价低,交通方便。"# [28] "梅堰小区 2室1厅 128万" # [29] "双地铁次新小区满二中间楼层.总共软装花了18万" # [30] "精装小户型,满二年,朝阳,70年产权,成熟地段。"
  • html_text()这步已经到了具体的信息抓取过程,但针对的是标签的文本内容。html_nodes这个函数的输入值:read_node函数获取的节点信息。连贯起来理解house_name <- web%>%html_nodes("div.info div.title a")%>%html_text(),就是先获取整个页面信息,然后定位到所需信息所在的节点,再在返回的节点中提取文本内容。


html_attr()获取节点的属性信息

如:house_link <- html_attr(tmp,"href"),获取节点下的href这个属性值,该属性值就是房子的详情链接。

house_link <- html_attrs(tmp,"href")house_link# [1] "https://hz.lianjia.com/ershoufang/103109543956.html"# [2] "https://hz.lianjia.com/ershoufang/103109306746.html"# [3] "https://hz.lianjia.com/ershoufang/103108174516.html"# [4] "https://hz.lianjia.com/ershoufang/103109219801.html"# [5] "https://hz.lianjia.com/ershoufang/103107527889.html"# [6] "https://hz.lianjia.com/ershoufang/103109328178.html"# [7] "https://hz.lianjia.com/ershoufang/103109405297.html"# [8] "https://hz.lianjia.com/ershoufang/103109234723.html"# [9] "https://hz.lianjia.com/ershoufang/103109496556.html"# [10] "https://hz.lianjia.com/ershoufang/103109299194.html"# [11] "https://hz.lianjia.com/ershoufang/103108655599.html"# [12] "https://hz.lianjia.com/ershoufang/103108551516.html"# [13] "https://hz.lianjia.com/ershoufang/103109485194.html"# [14] "https://hz.lianjia.com/ershoufang/103108968651.html"# [15] "https://hz.lianjia.com/ershoufang/103109357513.html"# [16] "https://hz.lianjia.com/ershoufang/103109578551.html"# [17] "https://hz.lianjia.com/ershoufang/103109454329.html"# [18] "https://hz.lianjia.com/ershoufang/103108832328.html"# [19] "https://hz.lianjia.com/ershoufang/103109578729.html"# [20] "https://hz.lianjia.com/ershoufang/103109450043.html"# [21] "https://hz.lianjia.com/ershoufang/103105364860.html"# [22] "https://hz.lianjia.com/ershoufang/103109300256.html"# [23] "https://hz.lianjia.com/ershoufang/103108452618.html"# [24] "https://hz.lianjia.com/ershoufang/103107750847.html"# [25] "https://hz.lianjia.com/ershoufang/103108517042.html"# [26] "https://hz.lianjia.com/ershoufang/103109088590.html"# [27] "https://hz.lianjia.com/ershoufang/103109554013.html"# [28] "https://hz.lianjia.com/ershoufang/103109603726.html"# [29] "https://hz.lianjia.com/ershoufang/103109415991.html"# [30] "https://hz.lianjia.com/ershoufang/103109101369.html"
  • html_attr()这步也是具体的信息抓取过程,但是针对属性进行提取。html_attr这个函数的输入值:一个是read_node函数获取的节点信息,另一个是属性标签(位于其实标签内)。连贯起来理解house_link <- web%>%html_nodes("div.info div.title a")%>%html_attr("href"),就是先获取整个页面信息,然后定位到所需信息所在的节点,再在返回的节点中提取href这个属性值。


以上就是rvest的基本用法,具体可以查看R包的说明文档。学会以上几个函数,基本上就可以抓取简单的静态网页了,其中稍有难度的就是html_node()函数中构建节点表达式:CSS选择器表达式XPath表达式,这部分内容在下一期做详细介绍!


往期回顾

R爬虫系列|工作需要衍生的笔记

R爬虫必备基础——HTML和CSS初识

R爬虫必备基础——静态网页+动态网页


长按识别二维码,关注"YJY技能修炼"

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存