我们这学期开设了数据采集课程,完全建立在R软件基础之上。在搜索相关资料过程中,发现关于R爬取的东西特别少,把提取部分分享到博客中希望可以帮助有缘人。
library(stringr)
library(RCurl)
library(XML)
在这里找到豆瓣电影所对应的链接https://movie.douban.com/top250?&filter=, 打开这个链接我们可以看到排行前25名的电影信息,top250的电影信息以同样的形式分布在10页上。
(1)提取一页的电影信息
在这里,我们以第一页为例,提取所需要的内容,首先是用readLines()函数读取整个网页。
url<-https://movie.douban.com/top250?&filter=
web<-readLines(url,encoding="UTF-8")
查看源代码我们可以知道,电影名字在标签…中,用str_extract_all()函数进行筛选并把内容展开,程序如下:
name<- str_extract_all(string = web, pattern = '
movie.names_line<- unlist(name)
查看movie.names_line可以得到:
结果并不是太完美,接下来用正则表达式进行提取,并且删除空缺NA值,程序如下:
movie.names<- str_extract(string = movie.names_line, pattern =">[^&].+<") %>%
str_replace_all(string = ., pattern =">|<",replacement = "")
movie.names<- na.omit(movie.names)
这时候再次查看movie.names
[1] "肖申克的救赎" "霸王别姬" "这个杀手不太冷"
[4] "阿甘正传" "美丽人生" "千与千寻"
[7] "泰坦尼克号" "辛德勒的名单" "盗梦空间"
[10]"机器人总动员" "三傻大闹宝莱坞" "海上钢琴师"
[13]"忠犬八公的故事" "放牛班的春天" "大话西游之大圣娶亲"
[16]"楚门的世界" "龙猫" "教父"
[19]"星际穿越" "熔炉" "触不可及"
[22]"乱世佳人" "无间道" "当幸福来敲门"
[25]"怦然心动"
接下来提取影片的发行年份,用到强大的grep(),用substr定位输出。
year<- web[grep(' ',web)+2]
movie.year<- substr(year,28,32)
查看输出结果,对应25部影片的发行年份:
>movie.year
[1] " 1994" " 1993" "1994" " 1994" " 1997" " 2001" "1997" " 1993" " 2010"
[10]" 2008" " 2009" " 1998" " 2009" "2004" " 1995" " 1998" " 1988" "1972"
[19]" 2014" " 2011" " 2011" " 1939" "2002" " 2006" " 2010"
我们还想要提取影片的评论人数和评分,方法和影片名称的提取类似,代码如下:
rating<- str_extract_all(web,pattern = '[:digit:]+人评价')
rating.num_line<- unlist(rating)
rating.num<-str_extract(rating.num_line, pattern = "[:digit:]+")
score_line<- str_extract_all(web, pattern = ' ')
score_line<- unlist(score_line)
score<- str_extract(string = score_line, pattern = '\\d\\.\\d')
查看一下两个输出结果
>rating.num
[1] "1056891""770031" "986399" "839784" "491099" "786841" "778988"
[8] "445741" "875226" "574298" "788783" "672243" "547874" "528564"
[15]"578714" "552487" "488237" "395560" "579863" "321178" "429336"
[22]"306544" "472399" "624586" "657651"
>score
[1] "9.6" "9.5""9.4" "9.4" "9.5" "9.3" "9.3""9.4" "9.3" "9.3" "9.2" "9.2"
[13]"9.2" "9.2" "9.2" "9.1" "9.1""9.2" "9.2" "9.2" "9.2" "9.2""9.1" "8.9"
[25]"8.9"
这样第一页电影的名字、年份、评分和评论人数都已经获取了,简单的设置一个数据框,把信息进行汇总可得到前25名的电影信息汇总:
movie<-data.frame(names=movie.names,year=as.numeric(movie.year),
score=as.numeric(score),rate=as.numeric(rating.num))
>movie
names year score rate
1 肖申克的救赎 1994 9.6 1056891
2 霸王别姬1993 9.5 770031
3 这个杀手不太冷 1994 9.4 986399
4 阿甘正传1994 9.4 839784
5 美丽人生1997 9.5 491099
6 千与千寻2001 9.3 786841
7 泰坦尼克号1997 9.3 778988
8 辛德勒的名单 1993 9.4 445741
9 盗梦空间2010 9.3 875226
10 机器人总动员 2008 9.3 574298
11 三傻大闹宝莱坞 2009 9.2 788783
12 海上钢琴师1998 9.2 672243
13 忠犬八公的故事 2009 9.2 547874
14 放牛班的春天 2004 9.2 528564
15 大话西游之大圣娶亲 1995 9.2 578714
16 楚门的世界1998 9.1 552487
17 龙猫1988 9.1 488237
18 教父1972 9.2 395560
19 星际穿越2014 9.2 579863
20 熔炉2011 9.2 321178
21 触不可及2011 9.2 429336
22 乱世佳人 1939 9.2 306544
23 无间道2002 9.1 472399
24 当幸福来敲门 2006 8.9 624586
25 怦然心动2010 8.9 657651
(2)用for循环提取10页内容
接下来,使用for循环,把10页中top250的电影信息全部提取出来,运行代码如下:
name.list<-list()
year.list<-list()
score.list<-list()
rate.list<-list()
for(i in1:10){
j<-(i-1)*25
url<-paste("http://movie.douban.com/top250?start=",j,"&filter=",sep="")
web<-readLines(url,encoding="UTF-8")
year<- web[grep(' ',web)+2]
movie.year<- substr(year,28,32)
movie.year<-as.numeric(movie.year)
name<- str_extract_all(string = web, pattern = '
movie.names_line<- unlist(name)
movie.names<- str_extract(string = movie.names_line, pattern =">[^&].+<") %>%
str_replace_all(string = ., pattern =">|<",replacement = "")
movie.names<- na.omit(movie.names)
rating<- str_extract_all(web,pattern = '[:digit:]+人评价')
rating.num_line<- unlist(rating)
rating.num<-str_extract(rating.num_line, pattern = "[:digit:]+")
rating.num<-as.numeric(rating.num)
score_line<- str_extract_all(web, pattern = ' ')
score_line<- unlist(score_line)
score<- str_extract(string = score_line, pattern = '\\d\\.\\d')
score<-as.numeric(score)
name.list[[str_c("p.",i)]]<-list(name=movie.names)
year.list[[str_c("p.",i)]]<-list(year=movie.year)
score.list[[str_c("p.",i)]]<-list(score=score)
rate.list[[str_c("p.",i)]]<-list(rating.num=rating.num)
}
由上面的代码可以看出,把电影名字、年份、评分、评论人数都放到了list中,我们用数据框进行汇总并查看:
movie.list<-data.frame(unlist(name.list),unlist(year.list),unlist(score.list),unlist(rate.list))
>head(movie.list)
unlist.name.list. unlist.year.list.unlist.score.list.
p.1.name1 肖申克的救赎 1994 9.6
p.1.name2 霸王别姬 1993 9.5
p.1.name3 这个杀手不太冷 1994 9.4
p.1.name4 阿甘正传 1994 9.4
p.1.name5 美丽人生 1997 9.5
p.1.name6 千与千寻 2001 9.3
unlist.rate.list.
p.1.name1 1056891
p.1.name2 770031
p.1.name3 986399
p.1.name4 840010
p.1.name5 491099
p.1.name6 786841
根据显示内容可知,虽然包含了想要的内容,但并没有一个完美的形式,进行一个简单的形式调整。
movies<-as.matrix(movie.list)
colnames(movies)<-c("name","year","score","rate")
rownames(movies)=NULL
>head(data.frame(movies))
name year score rate
1 肖申克的救赎 1994 9.6 1056891
2 霸王别姬 1993 9.5 770031
3 这个杀手不太冷 1994 9.4 986399
4 阿甘正传 1994 9.4 840010
5 美丽人生 1997 9.5 491099
6 千与千寻 2001 9.3 786841