上一期R爬虫必备——静态网页+动态网页简单介绍了网页的类型。在实际R爬虫过程中,针对不同的网页,采取的爬虫方法也会有所不同。通常情况下,R爬虫涉及的R包主要有3个:rvest、Rcurl和httr。
- rvest抓取静态网页数据****
所谓静态网页,就是你打开一个目标网页,在网页里可以直接看到想要抓取的数据,点击鼠标右键查看源代码后发现在HTML结构中可以在本地找到刚刚在网页里的目标数据,这就是静态网页。对于这样的网页,rvest可以提供一套较为完整的数据抓取方案,配上一些小工具,就可以快速实现爬虫。
- Rcurl/httr包实现对网页动态加载数据的抓取
对于网页动态加载的数据,继续使用rvest可能就不合适了。这时R提供了其他选择来实现相应的抓取目的。RCurl功能强大,但对初学者来说稍微有点难度。httr包相当于RCurl的精简版,相对轻巧易上手,功能虽不如RCurl那么齐全,但对于用户而言绝对友好。
今天呢,主要从最简单的静态网页抓取R包——rvest开始,这款R包抓取静态网页的逻辑非常清楚,初学者可以很快理解和上手。下面简单看一下rvest数据抓取的几个核心函数:
read_html():下载并解析网页
html_nodes():定位并获取节点信息
html_text():提取节点文本信息
html_attr():提取节点属性信息
rvest的这些函数如何使用呢?下面我们来简单看个案例——rvest包爬取链家网二手房信息,包括房子名字,房子具体信息(房型、面积、楼层等信息),房子地址,房子总价,房子每平方米单价等信息。
image简单点,只为演示作用, 仅爬取第一页: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表达式,这部分内容在下一期做详细介绍!
更多内容可关注公共号“YJY技能修炼”~~~
网友评论