R 爬虫-Rvest

Rvest用R轻松抓网页数据

课程背景:本课程需要一点R语言基础,以及了解一点CSS选择器的知识,不过没有相关的知识同样也不需要担心,所有的背景知识都很简单

学完之后能够做什么:通过本课程知识的讲解,加上案例的分析,同学可以学会使用R语言快速的爬取网络上的数据

目录

  • 什么是网络爬虫

  • 为什么要爬取数据

  • 准备工作

  • 如何使用Rvest爬取网页

  • Rvest简介

  • Rvest API 介绍

  • Rvest API 详解

  • 补充知识

  • 完整案例

什么是网络爬虫

网络爬虫是将呈现在网页上以非结构格式(html)存储的数据转化为结构化数据的技术

非结构化的数据通过查看网页的源代码就可以看到:

image.png

结构化的数据通常就是,由行和列组成的数据,行代表观测,列代表特征或变量:

image.jpeg

结构化数据

准备工作

下载相关的包

install.packages("rvest")

install.packages("tidyverse")

library(rvest)

library(tidyverse)

安装 Google Chrome 浏览器
要爬取网页上的数据,首先要知道的是,网页上的数据处于网页中的什么位置。那么如何去描述网页上的位置,可以通过 Xpath 和 selector

举一个例子:


image.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 详解

  1. 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网页数据

  1. html_nodes 与html_node 参数:
    x 一个xml_document数据
    css, xpath 要收集的节点。传入XPath和selector,也可以使用浏览器Google Chrome辅助
image.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

  1. head() 检查数据

  2. as.numeric() 转化为数值型

  3. gsub() 移除" “,”“,”“等

  4. as.factor() 转化为因子

  5. data.frame() 合并为数据框

  6. trycatch() 错误处理

  7. write.csv() 输出csv文件

  8. file.download() 下载网络文件

  9. read.table() 读取本地文件
    10.save() 保存变量到本地

  10. sapply() 向量化调用函数
    12.iconv() 转化编码格式
    13.rbind() 合并行
    14.paste() 连接字符串,多用来生成有规律的链接地址
    相关的 package

  11. stringr 字符串处理

  12. 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://www.zhipin.com/job_detail/?query=%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90&scity=101210100&industry=&position=

网页:


image.png

BOSS

主要爬取四个字段:

  1. 职位名称
  2. 公司名称
  3. 薪资范围
  4. 地址,年限等信息

爬取此网页的信息

网页网址

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年硕士

爬取多网页信息
其次,爬取翻页后的其他数据,这个时候就需要观察,翻页之后网址的变化:

第一页的网址:

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年硕士
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,921评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,635评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,393评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,836评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,833评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,685评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,043评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,694评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,671评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,670评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,779评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,424评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,027评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,984评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,214评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,108评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,517评论 2 343

推荐阅读更多精彩内容