R 爬虫-Rvest
Rvest用R轻松抓网页数据
课程背景:本课程需要一点R语言基础,以及了解一点CSS选择器的知识,不过没有相关的知识同样也不需要担心,所有的背景知识都很简单
学完之后能够做什么:通过本课程知识的讲解,加上案例的分析,同学可以学会使用R语言快速的爬取网络上的数据
目录
-
什么是网络爬虫
-
为什么要爬取数据
-
准备工作
-
如何使用Rvest爬取网页
-
Rvest简介
-
Rvest API 介绍
-
Rvest API 详解
-
补充知识
-
完整案例
什么是网络爬虫
网络爬虫是将呈现在网页上以非结构格式(html)存储的数据转化为结构化数据的技术
非结构化的数据通过查看网页的源代码就可以看到:
![](https://img.haomeiwen.com/i2562595/b25b3f32dd1a8a95.png)
结构化的数据通常就是,由行和列组成的数据,行代表观测,列代表特征或变量:
![](https://img.haomeiwen.com/i2562595/1dab939b193e6af8.jpeg)
结构化数据
准备工作
下载相关的包
install.packages("rvest")
install.packages("tidyverse")
library(rvest)
library(tidyverse)
安装 Google Chrome 浏览器
要爬取网页上的数据,首先要知道的是,网页上的数据处于网页中的什么位置。那么如何去描述网页上的位置,可以通过 Xpath 和 selector
举一个例子:
![](https://img.haomeiwen.com/i2562595/2dd2981e04f2654e.png)
CSS选择器 这个标题,在网页中的位置描述就是:
selector: #main > h2 > font > font
Xpath: //*[@id="main"]/h2/font/font
这个位置描述本质上可以通过观察网页的结构得出来,但是使用Google Chrome能够快速的获取数据的位置
Rvest 简介
rvest是R用户使用率最多的爬虫包,它简洁的语法可以解决大部分的爬虫问题。
基本使用方法:
- 使用read_html读取网页;
- 通过CSS或Xpath获取所需要的节点并使用html_nodes读取节点内容;
- 结合stringr包对数据进行清理。
Rvest API介绍
读取与提取:
- read_html() 读取html文档的函数
- html_nodes() 选择提取文档中指定元素的部分
- html_name() 提取标签名称;
- html_text() 提取标签内的文本;
- html_attr() 提取指定属性的内容;
- html_attrs() 提取所有的属性名称及其内容;
- html_table() 解析网页数据表的数据到R的数据框中;
- html_form() 提取表单。
乱码处理:
-
guess_encoding() 用来探测文档的编码,方便我们在读入html文档时设置正确的编码格式
-
repair_encoding() 用来修复html文档读入后的乱码问题
行为模拟: -
set_values() 修改表单
-
submit_form() 提交表单
-
html_session() 模拟HTML浏览器会话
-
jump_to() 得到相对或绝对链接
-
follow_link() 通过表达式找到当前页面下的链接
-
session_history() 历史记录导航工具
Rvest API 详解
- read_html 参数:
x 可以是url,本地路径,包含html的字符串,或者来自httr的请求如果x是URL参数就传递给GET()
encoding 文档的编码形式,查看iconvlist()有完整列表,他如果不能正确确定encoding方式可以尝试stri_enc_detect 使用这个函数来获取html数据
require(rvest)
HTML <- read_html(x = "https://hz.fang.anjuke.com/?from=navigation")
HTML
## {xml_document}
## <html>
## [1] <head>\n<meta http-equiv="Content-Type" content="text/html; charset= ...
## [2] <body>\n<div id="header">\n <div class="top-banner">\n ...
以上就获取了猎聘网的html网页数据
- html_nodes 与html_node 参数:
x 一个xml_document数据
css, xpath 要收集的节点。传入XPath和selector,也可以使用浏览器Google Chrome辅助
![](https://img.haomeiwen.com/i2562595/b1e278c1087eacdb.png)
网页
比如我们想获取楼盘名称,“东原旭辉璞阅”这个位置的数据,利用html_node
NAME <- HTML %>% html_nodes("#container > div.list-contents > div.list-results > div.key-list.imglazyload > div:nth-child(1) > div > a.lp-name > h3 > span")
NAME
## {xml_nodeset (1)}
## [1] <span class="items-name">绿都鉴未来</span>
这样我们就获得了对应位置的节点,想要得到对应节点的数据,使用html_text函数
NAME %>% html_text()
## [1] "绿都鉴未来"
到这里,就可以使用Rvest爬取简单的数据了
补充知识
包外API
-
head() 检查数据
-
as.numeric() 转化为数值型
-
gsub() 移除" “,”“,”“等
-
as.factor() 转化为因子
-
data.frame() 合并为数据框
-
trycatch() 错误处理
-
write.csv() 输出csv文件
-
file.download() 下载网络文件
-
read.table() 读取本地文件
10.save() 保存变量到本地 -
sapply() 向量化调用函数
12.iconv() 转化编码格式
13.rbind() 合并行
14.paste() 连接字符串,多用来生成有规律的链接地址
相关的 package -
stringr 字符串处理
-
RSelenium 模拟网页操作,可抓取动态页面
17.ggplot2 数据可视化
18.magrittr 辅助rvest
使用技巧
获取特定序位的html标签,用到了magrittr包里的extract2函数。下面两行代码都可以获得该网页中第一个<table>标签
ateam %>% html_nodes("table") %>% extract2(1) %>% html_nodes("img")
ateam %>% html_nodes("table") %>%[[(1) %>% html_nodes("img")
%>%是管道操作符,意思是把左边的操作结果作为参数传递给右边的命令
需要换页的同类型页面的地址一般会有规律,找到规律后就可生成一系列地址
定位所需内容时,有时html_nodes+stringr更方便,不使用html_text
若爬取内容过多,可使用边爬边存或者分批处理等
案例1 – 爬取BOSS直聘请杭州,数据分析职位的数据
网页:
![](https://img.haomeiwen.com/i2562595/d428404593574593.png)
BOSS
主要爬取四个字段:
- 职位名称
- 公司名称
- 薪资范围
- 地址,年限等信息
爬取此网页的信息
网页网址
url <- "https://www.zhipin.com/job_detail/?query=%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90&scity=101210100&industry=&position="
# 获取网址
HTML <- read_html(url)
HTML
## {xml_document}
## <html class="standard">
## [1] <head>\n<meta http-equiv="Content-Type" content="text/html; charset= ...
## [2] <body>\n<div id="wrap">\n \n \n\n\n\n\n\n\n<script>\n var s ...
JobName <- HTML %>% html_nodes('#main > div > div.job-list > ul > li > div > div.info-primary > h3 > a > div.job-title') %>% html_text()
CompanyName <- HTML %>% html_nodes('#main > div > div.job-list > ul > li > div > div.info-company > div > h3 > a') %>% html_text()
Salary <- HTML %>% html_nodes('#main > div > div.job-list > ul > li > div > div.info-primary > h3 > a > span') %>% html_text()
Description <- HTML %>% html_nodes('#main > div > div.job-list > ul > li > div > div.info-primary > p') %>% html_text()
Result <- data.frame(JobName,CompanyName,Salary,Description)
head(Result)
## JobName CompanyName Salary Description
## 1 数据分析师 阿里巴巴集团 30k-60k 杭州 余杭区 仓前3-5年本科
## 2 数据分析专员 云车金融 10k-20k 杭州 萧山区 宁围1-3年本科
## 3 数据分析 爱唯 6k-10k 杭州 下城区 1-3年大专
## 4 数据分析主管 浙江上佰 7k-12k 杭州 西湖区 古墩路3-5年本科
## 5 数据分析师 吉利集团 10k-20k 杭州 滨江区 西兴5-10年大专
## 6 数据分析师 海康威视 12k-18k 杭州 滨江区 西兴1-3年硕士
爬取多网页信息
其次,爬取翻页后的其他数据,这个时候就需要观察,翻页之后网址的变化:
第一页的网址:
-
https://www.zhipin.com/c101210100/?query=%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90&page=2&ka=page-next
观察发现,只需要修改page = ,修改成不同的页码就对应相应的页面。于是,写一个循环,修改页码即可
for (i in 2:10) {
url <- paste('https://www.zhipin.com/c101210100/?query=%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90&page=',i,'&ka=page-next',sep = "")
url <- "https://www.zhipin.com/job_detail/?query=%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90&scity=101210100&industry=&position="
HTML <- read_html(url)
HTML
JobName <- HTML %>% html_nodes('#main > div > div.job-list > ul > li > div > div.info-primary > h3 > a > div.job-title') %>% html_text()
CompanyName <- HTML %>% html_nodes('#main > div > div.job-list > ul > li > div > div.info-company > div > h3 > a') %>% html_text()
Salary <- HTML %>% html_nodes('#main > div > div.job-list > ul > li > div > div.info-primary > h3 > a > span') %>% html_text()
Description <- HTML %>% html_nodes('#main > div > div.job-list > ul > li > div > div.info-primary > p') %>% html_text()
Result1 <- data.frame(JobName,CompanyName,Salary,Description)
Result <- rbind(Result,Result1)
}
dim(Result)
## [1] 300 4
head(Result)
## JobName CompanyName Salary Description
## 1 数据分析师 阿里巴巴集团 30k-60k 杭州 余杭区 仓前3-5年本科
## 2 数据分析专员 云车金融 10k-20k 杭州 萧山区 宁围1-3年本科
## 3 数据分析 爱唯 6k-10k 杭州 下城区 1-3年大专
## 4 数据分析主管 浙江上佰 7k-12k 杭州 西湖区 古墩路3-5年本科
## 5 数据分析师 吉利集团 10k-20k 杭州 滨江区 西兴5-10年大专
## 6 数据分析师 海康威视 12k-18k 杭州 滨江区 西兴1-3年硕士