时间:2018年十一假期(学习) 2018-10-8(记录)
参考:R语言爬虫-RCurl和XML学习笔记
爬取内容:豆瓣电影Top250:主演及导演
R语言爬虫:豆瓣电影Top250(二)
提取其他信息中所需内容
从其他信息(information)中提取上映时间,国家以及影片类型。以第一个元素为例:
> information[1]
[1] " 导演: 弗兰克·德拉邦特 Frank Darabont 主演: 蒂姆·罗宾斯 Tim Robbins /... 1994 / 美国 / 犯罪 剧情
> information <- gsub("\n", "", information) # 去除“\n”
> information[1]
[1] " 导演: 弗兰克·德拉邦特 Frank Darabont 主演: 蒂姆·罗宾斯 Tim Robbins /... 1994 / 美国 / 犯罪 剧情
使用正则表达式将其中的四位数字即上映时间提取出来,并将其转为数值型:
> date_data <- str_extract(information[1], "[0-9]{4}")
> date <- as.numeric(date_data)
> date
[1] 1994
将information的第一个元素用strsplit函数,按“/”分割开:
> d <- strsplit(information[1], split = "/")
> d
[[1]]
[1] " 导演: 弗兰克·德拉邦特 Frank Darabont 主演: 蒂姆·罗宾斯 Tim Robbins "
[2] "... 1994 "
[3] " 美国 "
[4] " 犯罪 剧情
可以看出,d的第一个元素的最后一个元素为影片类型,倒数第二个为国家。
注:将information中元素按“/”分割时可能出现分为5部分的情况,因此不能认为第3个为国家,第4个为类型。
> nation_data <- d[[1]][length(d[[1]])-1]
> type_data <- d[[1]][length(d[[1]])]
> nation_data
[1] " 美国 "
> type_data
[1] " 犯罪 剧情 "
使用for循环可以提取information中每一个元素的信息。
代码如下:
> # 提取information中有用内容
> date_data <- list() # 上映时间
> nation_data <- list() # 国家
> type_data <- list() # 影片类型
> for (i in 1:length(information)){
+ date0_data <- str_extract(information[i], "[0-9]{4}")
+ date0 <- as.numeric(date0_data)
+ date_data <- c(date_data, list(date0_data))
+ d <- strsplit(information[[i]], split = "/")
+ nation0_data <- d[[1]][length(d[[1]])-1]
+ nation_data <- c(nation_data, list(nation0_data))
+ type0_data <- d[[1]][length(d[[1]])]
+ type_data <- c(type_data, list(type0_data))
+ }
爬取影片主演以及导演数据
打开豆瓣电影 Top 250,右键查看网页源代码,找到我们需要的资源所在的标签。
我们需要爬取的是每一个影片的网址,如第一个影片:https://movie.douban.com/subject/1292052/。
由上图可知,我们需要的内容在名为“hd”的标签div中的a。
将所有250个影片的网址爬取下来,存在名为info的变量中。
代码如下:
> a <- seq(0, 225, by = 25)
> myHttpheader <- c("User-Agent"="Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.1.6) ",
+ "Accept"="text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
+ "Accept-Language"="en-us",
+ "Connection"="keep-alive",
+ "Accept-Charset"="GB2312,utf-8;q=0.7,*;q=0.7")
> info <- NULL
> # 提取排行页面显示的有用信息: 排名、片名、评论、评分、观看人数、其他信息
> for(i in 1:10){
+ url1 <- "https://movie.douban.com/top250"
+ url2 <- "?start="
+ url3 <- "&filter="
+ url<-paste0(url1, url2, a[i], url3)
+ webpage <- read_html(url) # 排行榜的网址(10页,每页25个影片)
+ # |------------------info 爬取每部影片的网址----------------------
+ # 把网页爬下来
+ web<-getURL(url,httpheader=myHttpheader)
+ # 对爬取的网页进行处理,生成标准的HTML树形结构
+ doc<- htmlTreeParse(web,encoding="UTF-8", error=function(...){}, useInternalNodes = TRUE,trim=TRUE)
+ # 定位到标签<div>里面的<a>,资源提取
+ node<-getNodeSet(doc, "//div[@class='hd']/a")
+ # 通过sapply函数和XML函数结合,可以进一步提取资源,比如我们需要的是a标签里面href的内容
+ info0 <- sapply(node,xmlGetAttr,"href") # 所有影片的网址
+ info <- c(info, info0)
+ # ---------------------------------------------------------------|
+ }
打开某一影片网页,使用SelectorGadget得主演和导演的CSS选择器为“span:nth-child(1) .attrs a”和“.actor a”。
同样,使用html_nodes函数和html_text函数可以爬取到主演和导演的数据。
由于没有考虑到豆瓣的反爬虫设置,直接对250个网页的数据内容进行了爬取,导致IP被封…TAT…
原始代码(导致被封的代码)如下:
directors <- list()
actors <- list()
#--------------------------------导致IP被封的代码------------------------------
for(i in 1:length(info)){
webpage <- read_html(info[i])
directors_data_html <- html_nodes(webpage, "span:nth-child(1) .attrs a")
directors_data0 <- html_text(directors_data_html)
directors <- c(directors, list(directors_data0))
actors_data_html <- html_nodes(webpage, ".actor a")
actors_data0 <- html_text(actors_data_html)
actors <- c(actors, list(actors_data0))
}
-------------------------------------------------------------------------------
查询知豆瓣设置每分钟申请不得超过50次,修改代码如下:
> t <- sample(seq(1,3, by = 1), 100, replace = TRUE)
> directors <- list()
> actors <- list()
> #--------------------------------代码------------------------------
> # for(i in 1:length(info)){
> # 该部分代码已改为爬取Top100影片信息, 且加入了Sys.sleep()函数
> for(i in 1:100){
+ webpage <- read_html(info[i])
+ directors_data_html <- html_nodes(webpage, "span:nth-child(1) .attrs a")
+ directors_data0 <- html_text(directors_data_html)
+ directors <- c(directors, list(directors_data0))
+ actors_data_html <- html_nodes(webpage, ".actor a")
+ actors_data0 <- html_text(actors_data_html)
+ actors <- c(actors, list(actors_data0))
+ Sys.sleep(t[i])
+ }
-------------------------------------------------------------------------------
将所有数据综合起来生成数据框:
由于主演及导演只爬取了前100部影片的数据,因此其他各项数据也只取前100项。
> rank <- as.matrix(rank_data[1:100])
> title <- as.matrix(title_data[1:100])
> comment <- as.matrix(comment_data[1:100])
> rate <- as.matrix(rate_data[1:100])
> num <- as.matrix(num_data[1:100])
> date <- as.matrix(date_data[1:100])
> nation <- as.matrix(nation_data[1:100])
> type <- as.matrix(type_data[1:100])
> actor <- as.matrix(actors)
> director <- as.matrix(directors)
> web <- as.matrix(info[1:100])
> data_movies <- data.frame(rank, title, actor, director, comment, rate, num, date, nation, type, web)