R语言爬虫:豆瓣电影Top250(二)

时间: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)

猜你喜欢

转载自blog.csdn.net/woooooood/article/details/82975520