R语言 | 网页数据爬取rvest包学习

从零开始学习rvest网络爬虫抓数据-Stone.Hou

大神 Hadley rvest in GitHub
参考資料
rvest + CSS Selector 网页数据抓取的最佳选择-戴申
R爬虫实战1(学习)—基于RVEST包

rvest包简介

rvest包是hadley大神的又一力作,使用它能更方便地提取网页上的信息,包括文本、数字、表格等,本文对rvest包的运用做一个详细介绍,希望能够帮助你在网页抓取的武器库中新添一把利器。

rvest安装

从CRAN上安装发行版:

install.packages("rvest")

也可以从github上安装开发版本:

install.packages("devtools")
devtools::install_github("hadley/rvest")

rvest用法简介

下面对rvest包中的主要函数的功能做一下说明:

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

html_nodes() 选择提取文档中制定元素的部分。可以使用css selectors,例如html_nodes(doc, "table td");也可以使用xpath selectors,例如html_nodes(doc, xpath = "//table//td")。本文后面的示例主要采用css selectors来提取html文档中我们想要的部分。

html_tag() 提取标签名称;
html_text() 提取标签内的文本;
html_attr() 提取指定属性的内容;
html_attrs() 提取所有的属性名称及其内容;
html_table() 解析网页数据表的数据到R的数据框中。
html_form(),set_values()和submit_form() 分别表示提取、修改和提交表单。

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

还有一些函数,用来模拟网上的浏览行为,如html_session(),jump_to(),follow_link(),back(),forward(),submit_form()等等,这部分的工作还在进行中,相信rvest也会越来越强大。

以上就是rvest包的主要功能函数,下面我们来尝试用rvest包中的函数抓取新赛季NBA常规赛首日的新浪NBA首页的新闻消息。

rvest抓取示例1

网页抓取的一般步骤我总结有如下三步:

  1. 首先,明确所要抓取的内容
  2. 然后,通过html的标签名称、属性以及id等确切的描述定位到该内容的位置
  3. 最后,提取相关的内容信息,必要时再做一些数据处理

载入rvest包,读取新浪NBA官网网页

library(rvest) # 载入rvest包
library(stringr)
library(XML)
library(xml2)

url='[http://sports.sina.com.cn/nba/'](http://sports.sina.com.cn/nba/') 
web=read_html(url)

抓取最新的NBA新闻消息列表

html_nodes(web,".news-list-b a")%>%html_text
#html_text()提取标签内的文本;
# [1] "保罗仅13分快船出局"
# [2] "数据展望马刺VS火箭"
# ...
# [32] "未战先奶!北境双枪改叫双头巨兽 骑士掌门略毒"
# [33] "NBA正版授权页游 虚拟季后赛火热进行"
# [34] "马刺火箭结果已出!小炮预测就是这么牛!"
# [35] "APP"

抓取NBA新闻热点

html_nodes(web,".txt-a-hilight")%>%html_text
## [1] "卡哇伊35分阿杜27+10 马刺大胜勇士29分"
## [2] "詹皇三双骑士大胜尼克斯"
## [3] "升冠军旗詹皇含泪"
## [4] "利拉德39+9开拓者力克爵士"
## [5] "50大第1星:詹姆斯"
## [6] "詹皇联手甜瓜?"
## [7] "KD羡慕猛龙双枪友情:和威少之间未有过"

抓取NBA新闻头条

html_nodes(web,"#__liveLayoutContainer :nth-child(2) .txt-a-hilight")%>%html_text
## [1] "卡哇伊35分阿杜27+10 马刺大胜勇士29分"

可以看到,如果想要准确的提取相关新闻消息,需要用css选择器准确地描述消息所处的位置,如.news-list-b a、.txt-a-hilight等。如果你熟悉css选择器,你将会很容易通过查看html的源代码来定位所要提取内容的位置。如果你不太熟悉,这个我们的大神也考虑到了,你可以直接使用一个基于JS的小工具来实现定位,插件的使用参见vignette("selectorgadget")。

以上提取的主要是文本信息,对于网页中表格中的数据可以直接采用html_table()来获取,这部分示例详见微信公众号中案例数据的代码。一些复杂的模拟网上浏览行为的函数待rvest版本更新升级后我再做进一步的介绍。

特别说明

该示例结果为2016年10月26日下午5点运行得出,该演示代码及结果具有一定的时效性。

示例2 读取简书中的一篇文章的标题-2017/5/1 by Stone.Hou

library(rvest) # 载入rvest包
library(stringr)
library(XML)
library(xml2)

url='[http://www.jianshu.com/p/3cb5c6f2421c/'](http://www.jianshu.com/p/3cb5c6f2421c/') 
web=read_html(url)
h2title <- html_nodes(web,".show-content h2")%>%html_text
for (i in 1:length(h2title)) {
cat("这篇简书的第", i, "个标题的名称是:", h2title[i], "\n")
}

示例3 爬一下我爱豆五月天阿信的博文标题-安涵,IS girl

library(rvest)
library(stringr)
library(XML)
library(xml2)

html <- read_html("[http://blog.sina.com.cn/s/articlelist_1265020392_0_1.html](http://blog.sina.com.cn/s/articlelist_1265020392_0_1.html)",encoding="UTF-8")

title <- str_trim(
html %>% html_nodes("span.atc_title") %>%
html_text(),side='both')
#str_trim过滤两边的空格

for (i in 1:length(title)) {
cat("五月天阿信的第", i, "个博文标题是:", title[i], "\n")
}
#五月天阿信的第 1 个博文标题是: 五月天.自傳 | Mayday.h…
#五月天阿信的第 2 个博文标题是: 後來的我們
#五月天阿信的第 3 个博文标题是: 勇敢
#...

rvest抓取示例--豆瓣图书Top250

參考: 数据获取 爬虫利器Rvest包

# 加载Rvest包
library(rvest)
library(stringr)
library(XML)
library(xml2)

# 用read_html函数读取网页信息
web<-read_html("[https://book.douban.com/top250?icn=index-book250-all](https://book.douban.com/top250?icn=index-book250-all)",encoding="UTF-8")
position<-web %>% html_nodes("p.pl") %>% html_text()

获取节点信息

%>% 符号进行层级划分。web就是之前存储网页信息的变量,所以我们从这里开始,然后html_nodes()函数获取网页里的相应节点。在下面代码里我简单的重现了原网页里的一个层级结构。可以看到,实际上我们要爬取的信息在25个class属性为pl的<p>标签里的文本。

# <p class=pl>
# [清] 曹雪芹 著 / 人民文学出版社 / 1996-12 / 59.70元
# </p>

而对于这样的结构,在htmlnodes()函数里的写法就是简单的 "p.pl",其中“.”表示class属性的值,如果是id属性则用“#”,如果大家学过CSS选择器就很好理解了,是完全一致的。

最后我们用html_text()函数表示获取文本信息,否则返回的是整个<p>标签。 总体上用以下一行代码就可以实现:

position<-web %>% html_nodes("p.pl") %>% html_text()
position

想要学习更多,我们可以在Rstudio里的命令行输入如下代码查询html_nodes()函数的相关用法:

?html_nodes

Rvest这个包的说明文档里给出了一些其他例子

library(rvest)
library(stringr)
library(xml2)

ateam <- read_html("[http://www.boxofficemojo.com/movies/?id=ateam.htm](http://www.boxofficemojo.com/movies/?id=ateam.htm)")

# 然后下面代码分别获取了ateam这个网页里<center>标签里<td>的全部内容
ateam %>% html_nodes("center") %>% html_nodes("td")
# {xml_nodeset (7)}
# [1] <td align="center" colspan="2"><font size="4">Domestic Tot ...
# [2] <td valign="top">Distributor: <b><a href="/studio/chart/?s ...
# [3] <td valign="top">Release Date: <b><nobr><a href="/schedule ...
# [4] <td valign="top">Genre: <b>Action</b>\n</td>\n
# [5] <td valign="top">Runtime: <b>1 hrs. 57 min.</b>\n</td>
# [6] <td valign="top">MPAA Rating: <b>PG-13</b>\n</td>\n
# [7] <td valign="top">Production Budget: <b>$110 million</b>\n< ...

# 获取了ateam这个网页里<center>标签里<font>的全部内容
ateam %>% html_nodes("center") %>% html_nodes("font")
#[1] <font size="4">Domestic Total Gross: <b>$77,222,099</b></font>

# 接着官方例子中还给出了获取特定序位的html标签的方法,用到了magrittr包里的extract2函数:
library(magrittr)
#下面两行代码都可以获得该网页中第一个<table>标签(由extract2(1)或`[[`(1)获取)中的所有<img>标签里的内容,
ateam %>% html_nodes("table") %>% extract2(1) %>% html_nodes("img")
ateam %>% html_nodes("table") %>% `[[`(1) %>% html_nodes("img")

# 运行结果如下:
# {xml_nodeset (6)}
# [1] <img src="[https://images-na.ssl-images-amazon.com/images/M/MV5BMTc4ODc4NTQ1N15BMl5B](https://images-na.ssl-images-amazon.com/images/M/MV5BMTc4ODc4NTQ1N15BMl5B) ...
# [2] <img src="[http://www.assoc-amazon.com/e/ir?t=boxofficemojo-20&amp](http://www.assoc-amazon.com/e/ir?t=boxofficemojo-20&amp);l=as2&o=1&amp ...
# [3] <img src="[http://www.assoc-amazon.com/e/ir?t=boxofficemojo-20&amp](http://www.assoc-amazon.com/e/ir?t=boxofficemojo-20&amp);l=as2&o=1&amp ...
# [4] ![](/img/misc/bom_logo1.png)
# [5] ![](/img/misc/IMDbSm.png)
# [6] ![]([http://b.scorecardresearch.com/p?c1=2&amp](http://b.scorecardresearch.com/p?c1=2&amp);c2=6034961&cv=2.0&cj=1)

#同理我们也可以获得网页里前两个<table>标签储存的所有<img>标签里的内容:
ateam %>% html_nodes("table") %>% `[`(1:2) %>% html_nodes("img")
ateam %>% html_nodes("table") %>% extract(1:2) %>% html_nodes("img")

rvest抓取豆瓣网电影数据例

library(rvest)

url = '[http://movie.douban.com/top250?format=text'](https://movie.douban.com/top250?format=text%27)
web = html(url,encoding="UTF-8")

score = html_text(web %>% html_nodes("span") %>% html_nodes("em"))

year = web %>% html_nodes("p")
year = html_text(year[seq(1,50,2)])

gy = gregexpr('[0-9]{4}',year)
gd = gregexpr("导演",year)
gz = gregexpr("主演",year)

time = sapply(1:length(gy),function(i) substr(year[i],gy[[i]],gy[[i]]+attr(gy[[i]],'match.length')-1))
direct = sapply(1:length(gy),function(i) substr(year[i],gd[[i]] + 4,gz[[i]] - 4))
actor = sapply(1:length(gy),function(i) substr(year[i],gz[[i]] + 4,gy[[i]] - 4))
ga = gregexpr('\n',actor)
actor = sapply(1:length(gy),function(i) substr(actor[i],1,ga[[i]] - 1))

names = web %>% html_nodes("img") %>% html_attr("alt")
names = iconv(names,"utf-8","gbk")

rates = html_text(web %>% html_nodes("span"))
rates = rates[grep("人评价",rates)]
rates = gsub("人评价","",rates)

movie = data.frame(电影 = names,时间 = time,得分 = score,评价人数 = rates,导演 = direct,主演 = actor)
head(movie)

用rvest包抓取宝贝数据

library(rvest)
gurl <- "[https://list.tmall.com/search_product.htm?q=%C9%AD%B1%C8%B0%C2&type=p&vmarket=&spm=875.7931836%2FB.a2227oh.d100&from=mallfp..pc_1_searchbutton](https://list.tmall.com/search_product.htm?q=%C9%AD%B1%C8%B0%C2&type=p&vmarket=&spm=875.7931836%2FB.a2227oh.d100&from=mallfp..pc_1_searchbutton)"

md <- gurl %>%
read_html(encoding="GBK") %>% # 读取gurl的链接,指定编码为gbk
html_nodes("div.product-iWrap") # 筛选出所有包含在<div class="product-iWrap">...</div>块的内容

# 从对象md继续筛选,获卖家名称等数据。
# html_attr("data-nick") 是从html_nodes()筛选出的标签中,查找data-nick属性的值。
# gsub()是字符串查找替换的函数,pattern是指定用来查找的正则表达式。
# html_nodes("p.productTitle>a[title]"),”>"指定的筛选条件的父级标签。
# html_text() 只抓取<标签>内容</标签>中的内容部分。

# 抓取卖家昵称和ID
sellerNick <- md %>% html_nodes("p.productStatus>span[class]") %>%
html_attr("data-nick")
sellerId <- md %>% html_nodes("p.productStatus>span[data-atp]") %>%
html_attr("data-atp") %>%
gsub(pattern="^.*,",replacement="")
# 抓取宝贝名称等数据
itemTitle <- md %>% html_nodes("p.productTitle>a[title]") %>%
html_attr("title")
itemId <- md %>% html_nodes("p.productStatus>span[class]") %>%
html_attr("data-item")
price <- md %>% html_nodes("em[title]") %>%
html_attr("title") %>%
as.numeric
volume <- md %>% html_nodes("span>em") %>%
html_text
# 最后保存成数据框对象并存盘备用,以及写入csv文件
options(stringsAsFactors = FALSE) # 设置字符串不自动识别为因子
itemData <- data.frame(sellerNick=sellerNick,
sellerId=sellerId,itemTitle=itemTitle,
itemId=itemId,
price=price,
volume=volume)
save(itemData,file="F:/mydata/itemData.rData")
write.csv(itemData,file="F:/mydata/itemData.csv")

用rvest从赶集网抓取二手房单页面数据

getData <- function(gurl){
# 抓取赶集网二手房源单页的数据
library(rvest)
# 赶集网首页筛选长沙-雨花区-砂子塘的二手房源,获得链接,o1为页数
# gurl <- "[http://cs.ganji.com/fang5/yuhuashazitang/o1/](http://cs.ganji.com/fang5/yuhuashazitang/o1/)"
tmp <- gurl %>% html_session %>%
read_html(encoding="utf-8") %>%
html_nodes("div.f-main-list>div>div")

# 单个房源的puid
puid <- tmp %>% html_attr("id")
# 单个房源的链接
itemURL <-tmp %>% html_attr("href") %>%
gsub(pattern="/fang5",replacement="[http://cs.ganji.com/fang5](http://cs.ganji.com/fang5)")
# 缩略图链接
smallImg <- tmp %>% html_nodes("dl>dt>div>a>img") %>% html_attr("src")
# 标题
iTitle <- tmp %>% html_nodes("dl>dd>a") %>% html_attr("title")
# 户型
iLayout <- tmp %>% html_nodes("dl>dd[data-huxing]") %>% html_attr("data-huxing")
# 面积
iArea <- tmp %>% html_nodes("dl>dd[data-huxing]") %>%
html_attr("data-area") %>%
gsub(pattern="[^0-9]",replacement="")
# 筛选朝向等数据
iTmp <- tmp %>% html_nodes("dl>dd[data-huxing]>span") %>% html_text
iOrientation <- iTmp[seq(from=5,to=length(iTmp),by=9)] # 提取朝向
iFloor <- iTmp[seq(from=7,to=length(iTmp),by=9)] %>% # 提取楼层
gsub(pattern="\n",replacement="")
iDecoration <- iTmp[seq(from=9,to=length(iTmp),by=9)] # 提取装修
# 提取地址
iAddr <- tmp %>% html_nodes("dl>dd>span.area") %>% html_text %>%
gsub(pattern="\n",replacement=" ") %>%
gsub(pattern=" ",replacement="")
# 提取价格
iPrice <- tmp %>% html_nodes("dl>dd>div.price>span:first-child") %>% html_text
# 提取单价
iTime <- tmp %>% html_nodes("dl>dd>div.time") %>% html_text %>%
gsub(pattern="[^0-9]",replacement="") %>% as.numeric
# 合并数据框
iData <- data.frame(puid=puid,
iLayout=iLayout,
iArea=iArea,
iPrice=iPrice,
iTime=iTime,
iDecoration=iDecoration,
iFloor=iFloor,
iOrientation=iOrientation,
itemURL=itemURL,
smallImg=smallImg,
iTitle=iTitle,
iAddr=iAddr,
stringsAsFactors=FALSE)
# 返回数据框
return(iData)
}

如何用rvest包爬取豆瓣图书250的数据-例2

用R中的rvest包爬取豆瓣top250图书的基本信息(包括书名、评分、作者、译者、出版社、出版时间已经价格),然后根据出版社和出版时间进行进一步的分析

#加载所需的包
library("rvest");
library("dplyr");
library("stringr");

#批量爬取豆瓣图书top250数据
ind <-c(0,25,50,75,100,125,150,175,200,225)
book_inf <-data.frame()

#使用for循环进行批量数据爬取(发现url的规律,写for循环语句)
for (i in1:length(ind)){
web<-read_html(str_c("[https://book.douban.com/top250?start=](https://book.douban.com/top250?start=)",ind[i]),encoding="UTF-8")

#爬取图书的作者、出版社、出版时间、价格
p <-web%>%html_nodes("p.pl")%>%html_text()

#爬取图书的name
q <-web%>%html_nodes(".pl2 a")%>%html_text()

#爬取图书的rate
r <- web%>%html_nodes(".rating_nums")%>%html_text()

#消除图书的name q中的空格
q <-str_replace_all(q," ","")
q <-str_replace_all(q,"\n","")

#赋值图书书名和评分
name <- q
rate <- r

#对p进行处理
#提取作者名字
p1 <-str_split_fixed(p,"/",2)
author <- p1[,1];

#提取翻译者名字
p2 <-str_split_fixed(p1[,2],"/",2)
a <-str_detect(p2[,1],"出版")
b <- str_detect(p2[,1],"书店")
interpre <-p2[,1]
interpre[a|b] <-"NA"

#提取出版商
p3 <-str_split_fixed(p2[,2],"/",2)
publisher <-p3[,1]
publisher[a] <-p2[a,1]
publisher[b] <-p2[b,1]

#提取出版时间
p4 <-str_split_fixed(p3[,2],"/",2)
publish_time <-p4[,1]
publish_time[a]<- p3[a,1]
publish_time[b]<- p3[b,1]
publish_time <- str_replace(publish_time,"年","-")
publish_time <- str_replace(publish_time,"月","-")

#提取价格
p5 <-str_split_fixed(p4[,2],"/",2)
price <- p5[,1]
price[a] <-p4[a,1]
price[b] <-p4[b,1]

#创建数据框存储以上信息
book <-data_frame(name,rate,author,interpre,publisher,publish_time,price)
book_inf <-rbind(book_inf,book)
}

#对于少数不合规则的数据进行处理
book_inf[52,5:7] <- book_inf[52,4:6]
book_inf[52,4] <-"NA"
book_inf[136,5:7]<- book_inf[136,4:6]
book_inf[136,4]<- "NA"

#根据出版社进行分析
a <-summarise(group_by(book_inf,publisher),count = n())
arrange(a,desc(count))
# 根据图书出版的出版社进行分析,希望得到哪些出版社更容易出版好书
由于出版社有80个,因此,此处只截取出版好书数量大于等于5本的出版社进行分析

#根据出版时间进行分析
b<-str_split_fixed(book_inf$publish_time,"-",2)
b <- b[,1]
table(b)
# 根据图书出版时间进行分析,希望得到好书出版时间的规律:从图中可以看出,2007年出版的好书最多,且1997年至2011年,出版的好书都高于平均值(8本),除了2006年。

爬取了戴申在科学网博客

library(rvest)
library(sqldf)
library(gsubfn)
library(proto)
#creat a function
extrafun <- function(i,non_pn_url){
url <- paste0(non_pn_url,i)
web <- html(url)
papername<- web %>% html_nodes("dl.bbda dt.xs2 a") %>% html_text()%>% .[c(seq(2,20,2))] %>% as.character()
paperlink<-gsub("\\?source\\=search","",web %>% html_nodes("dl.bbda dt.xs2 a") %>% html_attr("href"))%>% .[c(seq(2,20,2))]
paperlink <- paste0("[http://blog.sciencenet.cn/](http://blog.sciencenet.cn/)",paperlink) %>% as.character()
posttime <- web %>% html_nodes("dl.bbda dd span.xg1") %>% html_text() %>% as.Date()#这里取每篇文章的发布时间
count_of_read <- web %>% html_nodes("dl.bbda dd.xg1 a") %>% html_text()
count_of_read <- as.data.frame(count_of_read)
count_of_read <- sqldf("select * from count_of_read where count_of_read like '%次阅读'")
data.frame(papername,posttime,count_of_read,paperlink)
}
#crawl data
final <- data.frame()
url <- '[http://blog.sciencenet.cn/home.php?mod=space&uid=556556&do=blog&view=me&page='](http://blog.sciencenet.cn/home.php?mod=space&uid=556556&do=blog&view=me&page=%27)
for(i in 1:40){
extrafun(i,url)
final <- rbind(final,extrafun(i,url))
}
dim(final)
#[1] 400 4

head(final)
# papername
# 1 此均值非彼均值
# 2 [转载]孔丘、孔子、孔老二,它究竟是一只什么鸟?
# 3 大数据分析之——k-means聚类中的坑
# 4 大数据分析之——足彩数据趴取
# 5 [转载]老王这次要摊事了,当年他主管的部门是事被重新抖出来。
# 6 [转载]党卫军是这样抓人的。
# posttime count_of_read
# 1 2015-03-08 216 次阅读
# 2 2015-02-10 190 次阅读
# 3 2015-01-18 380 次阅读
# 4 2015-01-10 437 次阅读
# 5 2015-01-05 480 次阅读
# 6 2015-01-05 398 次阅读
# paperlink
# 1 [http://blog.sciencenet.cn/blog-556556-872813.html](http://blog.sciencenet.cn/blog-556556-872813.html)
# 2 [http://blog.sciencenet.cn/blog-556556-866932.html](http://blog.sciencenet.cn/blog-556556-866932.html)
# 3 [http://blog.sciencenet.cn/blog-556556-860647.html](http://blog.sciencenet.cn/blog-556556-860647.html)
# 4 [http://blog.sciencenet.cn/blog-556556-858171.html](http://blog.sciencenet.cn/blog-556556-858171.html)
# 5 [http://blog.sciencenet.cn/blog-556556-856705.html](http://blog.sciencenet.cn/blog-556556-856705.html)
# 6 [http://blog.sciencenet.cn/blog-556556-856640.html](http://blog.sciencenet.cn/blog-556556-856640.html)

write.table(final,"final.csv",fileEncoding="GB2312")
#抓取的数据需要在Excel进一步加工,加工后读取进来,进一步做分析
a <- read.table("dai_shen_blog_0326.csv",header=TRUE,sep=";",fileEncoding="GB2312")#Mac OS 环境下,要sep=";"
a$posttime <- as.Date(a$posttime)
a$paperlink <- as.character(a$paperlink)
a$papername <- as.character(a$papername)
a$count_of_read_NO. <- as.numeric(a$count_of_read_NO.)
library(ggplot2)
qplot(posttime,count_of_read_NO.,data=a,geom="point",colour=repost,size=6)

爬取了NBA 2014-2015常规赛技术统计排行 - 得分榜

#Crawl NBA player statistics from sina
#web [http://nba.sports.sina.com.cn/playerstats.php?s=0&e=49&key=1&t=1](http://nba.sports.sina.com.cn/playerstats.php?s=0&e=49&key=1&t=1)
library(rvest)
library(stringr)
library(sqldf)
rm(NBAdata)
start <- seq(0,250,50)
end <- seq(49,299,50)
getdata <- function(i){
url <- paste0('[http://nba.sports.sina.com.cn/playerstats.php?s=',start](http://nba.sports.sina.com.cn/playerstats.php?s=%27,start)[i],'&e=',end[i],'&key=1&t=1')
rank <- url %>% html_session() %>% html_nodes("table") %>% .[[2]] %>% html_nodes("td:nth-child(1)") %>% html_text()%>%.[-1]%>%as.numeric()
player <- url %>% html_session() %>% html_nodes("table") %>% .[[2]] %>% html_nodes("td:nth-child(2)") %>% html_text()%>%.[-1]%>%str_sub(9,100)%>%as.character()
team <- url %>% html_session() %>% html_nodes("table") %>% .[[2]] %>% html_nodes("td:nth-child(3)") %>% html_text()%>%.[-1]%>%str_sub(9,100)%>%as.character()
avg_score <- url %>% html_session() %>% html_nodes("table") %>% .[[2]] %>% html_nodes("td:nth-child(4)") %>% html_text()%>%.[-1]
total_score <- url %>% html_session() %>% html_nodes("table") %>% .[[2]] %>% html_nodes("td:nth-child(5)") %>% html_text()%>%.[-1]
total_shoot <- url %>% html_session() %>% html_nodes("table") %>% .[[2]] %>% html_nodes("td:nth-child(6)") %>% html_text()%>%.[-1]
three_point <- url %>% html_session() %>% html_nodes("table") %>% .[[2]] %>% html_nodes("td:nth-child(7)") %>% html_text()%>%.[-1]
punish_point <- url %>% html_session() %>% html_nodes("table") %>% .[[2]] %>% html_nodes("td:nth-child(8)") %>% html_text()%>%.[-1]
avg_time <- url %>% html_session() %>% html_nodes("table") %>% .[[2]] %>% html_nodes("td:nth-child(9)") %>% html_text()%>%.[-1]
total_involve <- url %>% html_session() %>% html_nodes("table") %>% .[[2]] %>% html_nodes("td:nth-child(10)") %>% html_text()%>%.[-1]
data.frame(rank,player,team,avg_score,total_score,total_shoot,three_point,punish_point,avg_time,total_involve)
}
NBAdata <- data.frame()
for(i in 1:6){
NBAdata <- rbind(NBAdata,getdata(i))
}
NBAdata <- sqldf("select distinct * from NBAdata")
write.table(NBAdata,"NBAdata.csv",sep=",",fileEncoding="GB2312")

head(NBAdata)
# rank player team avg_score total_score
# 1 1 拉塞尔-威斯布鲁克 雷霆 27.3 1556
# 2 2 詹姆斯-哈登 火箭 27.1 1900
# 3 3 勒布朗-詹姆斯 骑士 25.8 1600
# 4 4 安东尼-戴维斯 鹈鹕 24.6 1403
# 5 5 德马库斯-考辛斯 国王 23.8 1308
# 6 6 斯蒂芬-库里 勇士 23.4 1618
# total_shoot three_point punish_point avg_time
# 1 42.7% 30.1% 84.6% 33.8
# 2 44% 36.8% 86.6% 36.8
# 3 49.2% 35.4% 71.9% 36.2
# 4 54.5% 10% 81.4% 36.2
# 5 46.5% 28.6% 80.2% 33.7
# 6 47.9% 42.2% 91.4% 32.9
# total_involve
# 1 57
# 2 70
# 3 62
# 4 57
# 5 55
# 6 69

拉勾网爬了一下,例子

library(rvest)
lagou <- "[http://www.lagou.com/jobs/list_%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90?kd=%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90&spc=2&pl=&gj=&xl=&yx=&gx=&st=&labelWords=&lc](http://www.lagou.com/jobs/list_%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90?kd=%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90&spc=2&pl=&gj=&xl=&yx=&gx=&st=&labelWords=&lc)
=&workAddress=&city=%E6%B7%B1%E5%9C%B3&requestId=&pn=3"
web<-html(lagou,encoding="UTF-8") #读取数据,规定编码
#之前我是用关键字搜索,阅读html代码,获得html_nodes里需要什么属性,不过许多浏览器有开发者工具,可以直接获得层级信息。如遨游
position<-web %>% html_nodes("li div.hot_pos_l a") %>% html_text()
#上面就是直接读取数据,获得位置信息
#不过在后面做其他网站时发现,有时候信息储存在同类数据里(如div没有class等等),建议是找一个大的分类,先获得表格信息,再做数据
list_lagou<-web %>% html_nodes("li.clearfix")
#这里正确找准正确的划分点很重要。有<li class="odd clearfix">,其实用li.clearfix一样可以取(对于空格二选一,如"li.odd"或者"li.clearfix")
#接下来的company/position照选即可,因为事先已经分好了list,所以每一个出多少心里有数。。

在讲完原理之后,现在开始尝试写代码,因为里面涉及太多的选取数据工作。为了避免出现太多变量,我最后是编了一个函数,输出数据库。

#下面开始写代码,首先写一个函数getdata,会输出一个数据框
getdata<-function(page,urlwithoutpage){
url=paste0(urlwithoutpage,page) #这里输入拉勾网没有页码的url
web<-html(url,encoding="UTF-8") #读取数据,规定编码,access用
list_lagou<-web %>% html_nodes("li.clearfix") #获得一个清单,15个职位
title<-list_lagou %>% html_nodes("div.hot_pos_l div.mb10 a")%>%html_text()
company<-list_lagou %>% html_nodes("div.hot_pos_r div.mb10 a")%>%html_text()
link<-gsub("\\?source\\=search","",list_lagou %>% html_nodes("div.hot_pos_l div.mb10 a")%>%html_attr("href"))
#接下来的由于数据都存在span里,没有很好的划分。这个取数要复杂一些。我在这里,研究他们的表,先取15个完整list,然后用seq等序列取数
#之后要研究是否有更好的方法
#如果有table,可以直接用data.table取数更快。。。
temp<-list_lagou %>% html_nodes("div.hot_pos_l span")
city<-temp[seq(1,90,by=6)] %>% html_text()
salary<-gsub("月薪:","",temp[seq(2,90,by=6)]%>% html_text())
year<-gsub("经验:","",temp[seq(3,90,by=6)]%>% html_text())
degree<-gsub("最低学历:","",temp[seq(4,90,by=6)]%>%html_text())
benefit<-gsub("职位诱惑:","",temp[seq(5,90,by=6)]%>% html_text())
time<-temp[seq(6,90,by=6)]%>%html_text()
data.frame(title,company,city,salary,year,degree,benefit,time,link)
}

获取函数,这里先爬一页!

url<-"[http://www.lagou.com/jobs/list_%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90?kd=%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90&spc=2&pl=&gj=&xl=&yx=&gx=&st=&labelWords=&lc=&workAddress=&city=%E6%B7%B1%E5%9C%B3&requestId=&pn=](http://www.lagou.com/jobs/list_%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90?kd=%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90&spc=2&pl=&gj=&xl=&yx=&gx=&st=&labelWords=&lc=&workAddress=&city=%E6%B7%B1%E5%9C%B3&requestId=&pn=)"
final<-data.frame()
for (i in 3){
final<-rbind(final,getdata(i,url))
} #定义个数,把上面的getdata得到的Data.frame合并

head(final)

R的爬虫和回归模型案例-以北京自如房租价格为例

library(rvest)
library(stringr)
library(XML)
library(xml2)

WebSpider <- function(m){
url <- str_c(cp,"?p=",m)
web <- read_html(url,encoding = "UTF-8")#抓取网页信息
name_rough <- web %>% html_nodes("h3") %>% html_text() #获取粗房屋名
area_rough <- web %>% html_nodes("h4") %>% html_text() #提取区位
price_rough <- web %>% html_nodes("p.price") %>% html_text() #提取价格
price <- str_extract(price_rough, "[0-9]+") %>% as.numeric()#提取精确价格
detail <- web %>% html_nodes("div.detail") %>% html_text() #提取其他信息

#合并成数据框
data.frame(name_rough,area_rough,forward,mate_num,location,price,detail)

# 4、接着是观察翻页规律,然后遇到了一个坑。原以为之后的页码不过是[http://www.ziroom.com/z/nl/z3.html](http://www.ziroom.com/z/nl/z3.html)的基础上加上/1、/2........,我依照这个思路抓了一番,也获得了将近4000多条数据,原以为这大概就是全部吧。但我仔细看数据才发现,这样下来的基本都是房山、大兴和通州等的数据,基本没有城六区的,城六区的只有选了区域选项后才会出现:
dc <- "[http://www.ziroom.com/z/nl/z3-d23008614.html](http://www.ziroom.com/z/nl/z3-d23008614.html)"
xc <- "[http://www.ziroom.com/z/nl/z3-d23008626.html](http://www.ziroom.com/z/nl/z3-d23008626.html)"
cy <- "[http://www.ziroom.com/z/nl/z3-d23008613.html](http://www.ziroom.com/z/nl/z3-d23008613.html)"
hd <- "[http://www.ziroom.com/z/nl/z3-d23008618.html](http://www.ziroom.com/z/nl/z3-d23008618.html)"
ft <- "[http://www.ziroom.com/z/nl/z3-d23008617.html](http://www.ziroom.com/z/nl/z3-d23008617.html)"
sjs <- "[http://www.ziroom.com/z/nl/z3-d23008623.html](http://www.ziroom.com/z/nl/z3-d23008623.html)"
cp <- "[http://www.ziroom.com/z/nl/z3-d23008611.html](http://www.ziroom.com/z/nl/z3-d23008611.html)"

# 这样一来,只有逐区的来进行翻页爬了。为此,只能选定部分区域来做分析了。
results_cp <- data.frame()
for(m in 1:118){ #118为昌平区信息的总页码
results_cp <- rbind(results_cp,WebSpider(m))#合并单个区每一次循环输出的数据
}
#依次重复获得7个区的数据
results <- rbind(results_cp, results_cy,results_dc,results_ft,
results_hd,results_sjs,results_xc) #将所有各区数据的合并

}

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

推荐阅读更多精彩内容

  • rvest是R语言一个用来做网页数据抓取的包,包的介绍就是“更容易地收割(抓取)网页”。其中html_nodes(...
    无鱼二饼阅读 25,000评论 5 13
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,097评论 18 139
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 170,563评论 25 707
  • 8/16 以终为始 节选自《高效能人士的7个习惯》 R:(Reading,阅读一个图书片段) “以终为始”的意思 ...
    鲍Lynphan阅读 393评论 1 1
  • 南北半球交换着自己的温度,飞机在天空与大地之间打着旋儿,朋友一年后如期而至的生辰,节假日,白昼黑夜,刻不容缓的不容...
    稻城的星阅读 117评论 0 0