在for循环内循环n页-R

时间:2020-05-13 11:46:57

标签: r loops while-loop

我正在尝试创建一个脚本,该脚本将使用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), ]

1 个答案:

答案 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)
  }
}