我正在尝试创建一个脚本,该脚本将使用itunesr R软件包提取Apple商店中给定播客上的所有评论。我在一些条件下苦苦挣扎,这些条件将使该过程具有可复制性。
library(itunesr)
我正在使用getReviews()函数,该函数需要一个播客ID,一个Apple商店国家/地区代码和页码。例如:
pod_id <- 479679002
reviews <- getReviews(pod_id,'us',1) #returns first page of reviews in the US store.
reviews$country <- "us" #add country variable
我有一个Apple商店代码的数据集,并从中创建了一个for循环,该循环将获取每个国家/地区商店的第一页评论,并将其添加到评论数据框中。
code <- c("ca", "gb", "us")
country <- c("Canada", "UK", "USA")
stores <- as.data.frame(cbind(code, country))
for (i in 1:nrow(stores)) {
try({
x <- stores$code[[i]]
reviews_test <- getReviews(pod_id, x ,1)
reviews_test$country <- x
reviews <- rbind(reviews, reviews_test)
}, silent = T)
}
#Remove duplicates
reviews <- reviews[!duplicated(reviews$Review), ]
如果给定页面上返回的评论数量= 49,则该国家/地区的评论页面数量更多。如果返回的评论数小于等于48,则该国家/地区不再有评论。
我想在for循环中添加更多条件,只要循环在每个页面上返回的评论数= 49,就可以将脚本移至评论的第2:n页,对于循环中的每个商店。 / p>
在上面的示例中,加拿大商店只有8条评论,而美国和英国商店有49条评论。
reviews %>%
group_by(country) %>%
count()
country n
<chr> <int>
1 ca 8
2 gb 49
3 us 49
我要创建的内容将遍历gb和us商店的第2页,并继续遍历n页,直到第n页上的评论数<= 48-意味着没有其他页面。
我假设我需要某种while / loop条件,但是恐怕这是我达到自己能力范围的地方。希望能对您有所帮助。
for (i in 1:nrow(stores)) {
try({
x <- stores$code[[i]]
reviews_loop <- getReviews(pod_id, x ,1)
reviews_loop$country <- x
reviews <- rbind(reviews, reviews_test)
if (nrow(reviews > 48)) {
#return page 2 for that country
#add to reviews data frame
#repeat for 3:n pages while reviews > 48
#otherwise, return to the start of loop and get info for next country
};
}, silent = T)
}
编辑:基于以下建议,我尝试了以下操作,但没有用。
for (i in 1:nrow(stores)) {
try({
x <- stores$code[[i]]
reviews_loop <- getReviews(SJ, x, 1)
reviews_loop$country <- x
reviews <- rbind(reviews, reviews_test)
if (nrow(reviews_loop > 48)) {
for (j in 2:num_pages) {
x <- stores$code[[i]]
reviews_loop_new <- getReviews(pod_id, x, j)
reviews_loop_new$country <- x
reviews <- rbind(reviews, reviews_loop_new)
}
};
}, silent = T)
}
进一步编辑:
尝试了以下解决方案,最终陷入了无休止的循环。我认为这是因为当没有评论出现时(对于新的国家/地区代码,在第1页上;对于在第1:n页上有49个回复的国家,在第n + 1页上,回复如下:
Error in names(reviews) <- c("Title", "Author_URL", "Author_Name", "App_Version", :
attempt to set an attribute on NULL
然后,循环需要某种方式来处理上述错误。根据以下建议,类似这样的事情似乎更接近我的需求。
for (i in 1:nrow(stores)) {
try({
page = 1
x <- stores$code[[i]]
reviews_test <- getReviews(pod_id, x, page)
reviews_test$country <- x
reviews <- rbind(reviews, reviews_test)
### BREAK HERE IF REVIEWS TEST RETURNS THE ERROR ?? ##
if (nrow(reviews_test == 49))
repeat {
try({
Sys.sleep(5) ## TOO MANY CALLS = HTTP 400
page = page + 1
reviews_test <- getReviews(pod_id, x , page)
### BREAK HERE IF REVIEWS TEST RETURNS THE ERROR ##
reviews_test$country <- x
reviews <- rbind(reviews, reviews_test)
if (nrow(reviews_test < 49)) ##BREAK HERE IF REVIEWS < 49, MOVE ON TO NEXT COUNTRY CODE
}, silent = T)
}
}, silent = T)
}
由于下面的答案,我现在有一个解决方案。
for (i in 1:nrow(stores)) {
try({
page = 1
x <- stores$code[[i]]
reviews_test <- getReviews(pod_id, x, page)
reviews_test$country <- x
reviews <- rbind(reviews, reviews_test)
if (nrow(reviews_test) == 49)
repeat {
try({
Sys.sleep(5)
page = page + 1
reviews_test <- getReviews(SJ, x , page)
reviews_test$country <- x
reviews <- rbind(reviews, reviews_test)
if (nrow(reviews_test) < 49) break
})#, silent = T)
}
}, silent = T)
}
#Then run the following line to remove the duplicated records from the original reviews data frame.
reviews <- reviews[!duplicated(reviews$Review), ]
答案 0 :(得分:1)
只需重复循环的每一步,直到评论数<49:
for (i in 1:nrow(stores)) {
page = 1
x <- stores$code[[i]]
repeat {
try({
reviews_test <- getReviews(pod_id, x , page)
reviews_test$country <- x
reviews <- rbind(reviews, reviews_test)
if (nrow(reviews_test) < 49) break
page = page + 1
}, silent = T)
}
}