R语言爬虫 rvest

米霖

2022-09-18

简介

随着互联网的出现,网络成为承载信息的一个巨大的载体。在这种情况下,数据的量级已经远远的超过了人脑能够承受的范围。如何有效的利用网络数据是一个巨大的挑战。从另外一个角度来讲,互联网的数据是一个巨大的包括,而掌握的爬虫技术,则能够总这宝库中获取巨大的价值。爬虫则是从网页中获取数据的一种方式,是按照一定规则,自动的抓取网页数据的程序或者脚本。其是R并不适合做一个专业的爬虫工具,如果想要开发爬虫软件或者其他相关的工作,R并不是一个好的选择。对于R用户而言,如果仅仅是想快速的获取网页上的某些信息,然后在R中进行分析,那么使用R来编写爬虫代码绝对是一个好的选择。本章节会介绍使用R语言爬取网页上的数据。使用到的包是rvest。

准备工作

  1. Google Chrome浏览器

要爬取网页上的数据,首先要知道的是,网页上的数据处于网页中的什么位置。那么如何去描述网页上的位置,有很多方式来描述数据在网页上面的位置,常用的是:Xpath和CSS Selector。 XPath 使用路径表达式来选取 XML 文档中的节点或节点集。节点是通过沿着路径 (path) 或者步 (steps) 来选取的。关于XPath语法可以参考这个链接:https://www.runoob.com/xpath/xpath-syntax.html

CSS选择器用于选择你想要的元素的样式的模式,关于Selector的语法可以参考:https://www.runoob.com/cssref/css-selectors.html

举一个简单的例子,Xpath和Selector是如何描述数据在网页中的位置,打开网址: https://www.runoob.com/cssref/css-selectors.html

然后获取CSS选择器 这个标题的路径:

selector :#content > h1 XPath://*[@id="content"]/h1

需要注意的是,并不是通过工具获取的路径就是对的,有时候需要手动进行修改。

  1. 安装rvest 包

rvest 简介

rvest是R用户使用率最多的爬虫包,它简洁的语法可以解决大部分的爬虫问题。其基本使用方法是:

  1. 使用read_html读取网页;
  2. 通过CSS或Xpath获取所需要的节点并使用html_nodes读取节点内容,再同html_text提取对应节点的文本
  3. 结合stringr包对数据进行清理。

rvest 常用函数

  1. read_html() 读取html文档的函数,其输入可以是线上的url,也可以是本地的html文件,甚至是包含html的字符串也可以。

  2. html_nodes() 选择提取文档中制定元素的部分。可以使用css selectors,例如html_nodes(doc, “table td”);也可以使用xpath selectors,例如html_nodes(doc, xpath = “//table//td”)。

  3. html_tag() 提取标签名称;html_text() 提取标签内的文本;html_attr() 提取指定属性的内容;html_attrs() 提取所有的属性名称及其内容;

  4. html_table() 解析网页数据表的数据到R的数据框中。

  5. html_form(),set_values()和submit_form() 分别表示提取、修改和提交表单。

  6. guess_encoding() 在中文网页中我们经常会遇到乱码的问题,这里提供了两个函数来解决:guess_encoding()用来探测文档的编码,方便我们在读入html文档时设置正确的编码格式,repair_encoding()用来修复html文档读入后的乱码问题。

  7. html_session() 还有一些函数,用来模拟网上的浏览行为,如html_session(),jump_to(),follow_link(),back(),forward(),submit_form()等等。

使用rvest 的基本步骤

  1. 加载Rvest包。
  2. 用read_html函数读取网页信息(类似Rcurl里的getURL),在这个函数里只需写清楚网址和编码(一般就是UTF-8)即可。
  3. 是获取节点信息。
  4. 获取数据
library(rvest)

web<-read_html("https://book.douban.com/top250?icn=index-book250-all",encoding="UTF-8")

# #content > div > div.article > div > table:nth-child(2) > tbody > tr > td:nth-child(2) > div.pl2 > a
title <-  web %>% html_nodes("div.pl2 > a") %>% html_text()
title

title <-  title %>% str_remove_all("\n") %>% str_trim() %>% str_remove_all(" ")

# #content > div > div.article > div > table:nth-child(2) > tbody > tr > td:nth-child(2) > p.pl
bookinfo <-  web %>% html_nodes("td:nth-child(2) > p.pl") %>% html_text()
bookinfo

# #content > div > div.article > div > table:nth-child(2) > tbody > tr > td:nth-child(2) > div.star.clearfix > span.rating_nums

rate <- web %>% html_nodes("span.rating_nums") %>% html_text()
rate

book <- data.frame(title=title,bookinfo=bookinfo,rate=rate)
book

读取多个页面数据。首先观察多个页面结构: 第1页: https://book.douban.com/top250?icn=index-book250-all

第2页 https://book.douban.com/top250?start=25

第3页 https://book.douban.com/top250?start=50

观察规律:只需要修改start=(页面数-1)*25

# url <- paste("https://book.douban.com/top250?start=",(i-1)*25,sep = "")

for(i in 2:10){
  url <- paste("https://book.douban.com/top250?start=",(i-1)*25,sep = "")
  web<-read_html(url,encoding="UTF-8")
  title <-  web %>% html_nodes("div.pl2 > a") %>% html_text()
 

title <-  title %>% str_remove_all("\n") %>% str_trim() %>% str_remove_all(" ")

# #content > div > div.article > div > table:nth-child(2) > tbody > tr > td:nth-child(2) > p.pl
bookinfo <-  web %>% html_nodes("td:nth-child(2) > p.pl") %>% html_text()
bookinfo

# #content > div > div.article > div > table:nth-child(2) > tbody > tr > td:nth-child(2) > div.star.clearfix > span.rating_nums

rate <- web %>% html_nodes("span.rating_nums") %>% html_text()
rate

book1 <- data.frame(title=title,bookinfo=bookinfo,rate=rate)
book <- book %>% rbind(book1)
  print(i)
}

第二个例子

什么是会话?会话的出现是为了跟踪 cookie,保证 cookie 长期有效,只有当会话被关闭时,cookie 便会失效。你可以把会话(Session)想象成在浏览器中打开的页面窗口,你之所以可以在这个窗口执行很多操作,这是因为服务器端知道你的 cookie 中存在有效的 SessionID,所以服务器会一直通过你的请求,把资源给你。

u <- "https://book.douban.com/"
session <- session(u)

session
什么是表单?HTML 中的表单被用来搜集用户的不同类型的输入。例如,登录表单、搜索框表单等。HTML 表单

包含表单元素,表单元素是指不同类型的 input 元素、复选框(box)、单选(radio)、提交按钮(submit)等。

处理表单有几个步骤:

  1. 提取出你所需要的表单:html_form( )
  2. 填写你的表单:html_form_set(form, name1=value1, name2=value2)
  3. 提交表单,发送给服务器:session_submit(session, form)
forms <- session %>% html_form()
forms
form <- forms[[1]] # forms 中的第一个列表是我们的目标列表
form

在上面的结果中,只有 ‘search_text’ :的冒号后为空,这表明 ‘search_text’ 还没有填充任何值,而我们的填充任务就是把它填上。例如我们要搜索小说。

filled_form <- html_form_set(form, search_text = "小说") # 填写表单
session2 <- session_submit(session, filled_form) # 提交
session$url # 查看初始 session 的 url
session2$url # 查看提交表单后,返回的新会话 session2 的 url

# iconv(URLdecode(session2$url), "UTF8") 将转换成为中文

下一步,我们可以读取对应网址的数据了。