Rvest用R轻松抓网页数据


课程背景

  1. R语言知识
  2. CSS网页知识


学完之后能够做什么


通过本课程知识的讲解,加上案例的分析,同学可以学会使用R语言快速的爬取网络上的数据


目录



什么是网络爬虫


网络爬虫(又被称为网页蜘蛛,网络机器人,在FOAF社区中间,更经常的称为网页追逐者),是一种按照一定的规则,自动地抓取万维网信息的程序或者脚本,将呈现在网页上以非结构格式(html)存储的数据转化为结构化数据的技术


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


非结构化数据

非结构化数据


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


结构化数据

结构化数据


为什么要爬取数据


  1. 数据是一种非常宝贵的资源

  2. 网络尚存在大量的免费资源

  3. 爬虫技术能帮助我们快速的获取网络上面的数据


准备工作


  1. 下载相关的包


` install.packages("rvest")`

` install.packages("tidyverse")`

`library(rvest)`

`library(tidyverse)`


  1. 安装 Google Chrome 浏览器


要爬取网页上的数据,首先要知道的是,网页上的数据处于网页中的什么位置。那么如何去描述网页上的位置,有很多方式来描述数据在网页上面的位置:

1.Xpath 2.selector


举一个例子: WEB DATA


CSS选择器 这个标题,在网页中的位置描述就是:


  1. selector: #main > h2 > font > font
  2. Xpath: //*[@id="main"]/h2/font/font


这个位置描述本质上可以通过观察网页的结构得出来,但是使用Google Chrome能够快速的获取数据的位置


Rvest 简介


rvestR用户使用率最多的爬虫包,它简洁的语法可以解决大部分的爬虫问题。


基本使用方法:



Rvest API介绍


读取与提取:


乱码处理:



行为模拟:


Rvest API 详解


  1. read_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_nodeshtml_node 参数:
网页

网页


比如我们想获取楼盘名称,“东原旭辉璞阅”这个位置的数据,利用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() 保存变量到本地
  11. sapply() 向量化调用函数
  12. iconv() 转化编码格式
  13. rbind() 合并行
  14. paste() 连接字符串,多用来生成有规律的链接地址


相关的 package


  1. stringr 字符串处理
  2. RSelenium 模拟网页操作,可抓取动态页面
  3. ggplot2 数据可视化
  4. magrittr 辅助rvest


使用技巧


  1. 获取特定序位的html标签,用到了magrittr包里的extract2函数。下面两行代码都可以获得该网页中第一个<table>标签
    • ateam %>% html_nodes("table") %>% extract2(1) %>% html_nodes("img")
    • ateam %>% html_nodes("table") %>%[[(1) %>% html_nodes("img")
  2. %>%是管道操作符,意思是把左边的操作结果作为参数传递给右边的命令
  3. 需要换页的同类型页面的地址一般会有规律,找到规律后就可生成一系列地址
  4. 定位所需内容时,有时html_nodes+stringr更方便,不使用html_text
  5. 若爬取内容过多,可使用边爬边存或者分批处理等


案例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=

网页:

BOSS

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" class="search-job-list-wrap">\n<script>\n     ...
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     数据分析    中软国际 10k-15k             杭州  3-5年本科
## 2   数据分析师    同盾科技 10k-20k   杭州 余杭区 仓前3-5年硕士
## 3     数据分析        爱唯  6k-10k             杭州  1-3年大专
## 4     数据分析        边锋 13k-20k 杭州 西湖区 文一路3-5年本科
## 5     数据分析  银江研究院  8k-16k   杭州 西湖区 三墩1-3年本科
## 6 数据分析专家    网易杭州 10k-20k   杭州 滨江区 长河3-5年本科


爬取多网页信息


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

第一页的网址:

  • https://www.zhipin.com/job_detail/?query=%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90&scity=101210100&industry=&position=

第二页的网址:

  • 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     数据分析    中软国际 10k-15k             杭州  3-5年本科
## 2   数据分析师    同盾科技 10k-20k   杭州 余杭区 仓前3-5年硕士
## 3     数据分析        爱唯  6k-10k             杭州  1-3年大专
## 4     数据分析        边锋 13k-20k 杭州 西湖区 文一路3-5年本科
## 5     数据分析  银江研究院  8k-16k   杭州 西湖区 三墩1-3年本科
## 6 数据分析专家    网易杭州 10k-20k   杭州 滨江区 长河3-5年本科


简单数据分析


  1. 那些公司需要数据分析职位
require(tidyverse)
CN <- as.data.frame(table(Result$CompanyName)) %>% arrange(desc(Freq))
CN
##                    Var1 Freq
## 1          阿里巴巴集团   50
## 2              蚂蚁金服   40
## 3              宸帆电商   30
## 4                  爱唯   10
## 5               百e国际   10
## 6                  边锋   10
## 7  杭州雅未实业有限公司   10
## 8              嘉云数据   10
## 9              江苏达科   10
## 10             拉夏贝尔   10
## 11           尼尔森网联   10
## 12             同盾科技   10
## 13             网易杭州   10
## 14                 微店   10
## 15               小黑鱼   10
## 16             小泰科技   10
## 17               伊电园   10
## 18             壹米滴答   10
## 19           银江研究院   10
## 20             浙江执御   10
## 21             中软国际   10

案例2 – 模拟登陆


模拟登陆案例的网址如下:http://www.medscape.com/viewarticle/884676

模拟登陆

模拟登陆


首先要模拟对话


library(xml2)
library(rvest)

# 取地址,用html_session模拟会话
url <- 'http://www.medscape.com/viewarticle/884676'

pgsession <- html_session(url)

pgsession
## <session> https://login.medscape.com/login/sso/getlogin?urlCache=aHR0cHM6Ly93d3cubWVkc2NhcGUuY29tL3ZpZXdhcnRpY2xlLzg4NDY3Ng==&ac=401
##   Status: 200
##   Type:   text/html;charset=UTF-8
##   Size:   50574
# 使用html_form 来解析网页的表单

pgform <- html_form(pgsession) # 在这里找,列表的第几个元素包含了username,passward
pgform
## [[1]]
## <form> 'search-form-header' (GET javascript:subsearchheadertrack('en');)
##   <input hidden> 'searchSrc': news
##   <input text> 'q': 
##   <button submit> '<unnamed>
##   <button button> '<unnamed>
## 
## [[2]]
## <form> 'search-form-header' (GET javascript:subsearchheadertrack('en');)
##   <input hidden> 'searchSrc': news
##   <input text> 'q': 
##   <button submit> '<unnamed>
## 
## [[3]]
## <form> 'loginRequest' (POST /login/sso/login)
##   <input hidden> 'urlCache': aHR0cHM6Ly93d3cubWVkc2NhcGUuY29tL3ZpZXdhcnRpY2xlLzg4NDY3Ng==
##   <input hidden> 'spa': 
##   <input hidden> 'stepUp': false
##   <input hidden> 'facilitatedUrl': 
##   <input text> 'userId': 
##   <input password> 'password': 
##   <input hidden> 'remember': on
##   <input submit> 'loginbtn': Log In
pgform1 <- pgform[[3]] # 这里提取对应的列表,第三个


  1. 使用html_session,传入需要登陆的页面
  2. 使用html_form 来解析网页的表单
  3. 然后需要在解析的表单中找到username,paasward在解析结果的列表中位置
  4. 提取对应列表的解析结果


接下来就是填写账号与密码:

filled_form <- set_values(pgform1,
                          'userId'='15527504293@163.com',
                          'password'='h89paAybMt8ecku')
# 提交
sbmt <- submit_form(pgsession,filled_form)
## Submitting with 'loginbtn'
sbmt
## <session> https://www.medscape.com/viewarticle/884676
##   Status: 200
##   Type:   text/html;charset=UTF-8
##   Size:   102961


  1. set_values 来设置你的账号的和密码
  2. submit_form 来提交你的账号和密码


如果成功,就会看类似这样的登录状态: · http://www.medscape.com/viewarticle/884676 Status: 200 Type: text/html;charset=UTF-8 Size: 86339 ·

Status 200表示请求顺利

登陆之后就原url就会变成这样:

登陆成功之后的页面

登陆成功之后的页面

登陆之后,爬取其他数据就与我们之前讲解的一样,爬取文章:

Text <- sbmt%>%html_nodes('div.article-content-wrapper div p')%>%html_text(trim = T)

head(Text)
## [1] "Nothing seemed to help the patient — and hospice staff didn’t know why."                                                                                                                                                                                                                                                                                                                                                                                                            
## [2] "They sent home more painkillers for weeks. But the elderly woman, who had severe dementia and incurable breast cancer, kept calling out in pain."                                                                                                                                                                                                                                                                                                                                     
## [3] "The answer came when the woman’s daughter, who was taking care of her at home, showed up in the emergency room with a life-threatening overdose of morphine and oxycodone. It turned out she was high on her mother’s medications, stolen from the hospice-issued stash."                                                                                                                                                                                                           
## [4] "Dr. Leslie Blackhall handled that case and two others at the University of Virginia’s palliative care clinic, and uncovered a wider problem: As more people die at home on hospice, some of the powerful, addictive drugs they are prescribed are ending up in the wrong hands."                                                                                                                                                                                                     
## [5] "Hospices have largely been exempt from the national crackdown on opioid prescriptions because dying people may need high doses of opioids. But as the nation’s opioid epidemic continues, some experts say hospices aren’t doing enough to identify families and staff who might be stealing pills. And now, amid urgent cries for action over rising overdose deaths, several states have passed laws giving hospice staff the power to destroy leftover pills after patients die."
## [6] "Blackhall first sounded the alarm about drug diversion in 2013, when she found that most Virginia hospices she surveyed didn’t have mandatory training and policies on the misuse and theft of drugs. Her study spurred the Virginia Association for Hospices and Palliative Care to create new guidelines, and prompted national discussion."


备注


  1. 爬取的内容可能会随时间变化,因为网页会发生变化.同学们在自己操作的时候需要注意一下

需要联系我可以添加我的微信