獲取豆瓣電影數據(R與API獲取網頁數據)


一般成熟的網站都會有反爬蟲策略,例如限制訪問次數,限制訪問 IP,動態顯示數據等。爬蟲和反爬蟲就是一直相愛相殺地互相鉗制。如果要通過爬蟲來獲取某些大型網站的數據,那是一件很費時費力的活。小白總遭遇過在趟過各種坑之前就被封 IP 或封賬號的打擊(嗚嗚~說的就是我)。

不過有一些公司心懷開放互聯的態度,友好地給大家提供了 api 接口。這一篇博客將以豆瓣電影為例記錄如何站在巨人(api)的肩膀上獲取數據。不過豆瓣 api 現在貌似也逐漸收起來了,api key 也停止申請了,且用且珍惜了。

>> Required Packages


```r library(httr) library(jsonlite) ```
#### >> Get JSON
豆瓣電影的 url 還是很規律,比如說 id 為 27074316 的電影的 url 就是 https://movie.douban.com/subject/27074316 , 但是 id 的排序並不是規律的。例如一部 2000 年上映的電影的 id 可能會大於 2010 年上映的電影的 id。

豆瓣電影的 id 范圍大約為 1300000 到 27200000,但其中可能會有一部分無效的 id。如果需要獲取所有豆瓣電影的數據,那么就要遍歷所有 id。如果只是需要一部分的數據,就要用到 search key。

比如 id 為 27074316 的電影的 api resource url 是
https://api.douban.com/v2/movie/subject/27074316?apikey={your_api_key}

比如搜索 2018年電影的 api resource url 是
https://api.douban.com//v2/movie/search?q=2018?apikey={your_api_key}

在瀏覽器中輸入上述 url (記得替換為你的 api key) 是可以看見返回的 json 的,而在 R 中要獲取 json 就要用到 package httr 中的 GET 函數。如果返回 200 則表示請求成功。

url <- https://api.douban.com/v2/movie/subject/27074316
film_json <- GET(url, query = list(apikey="your_api_key"))
if(status_code(film_json) == 200)
	message("success\n")

#### >> Get Text
獲取 json 后要讀取里面需要的內容,例如獲取電影名稱,電影導演等: ```r film_data <- fromJSON(content(film_json, "text")) title <- film_data$title director <- film_data$directors$name %>% paste(collapse=",") ``` json 在瀏覽器中的文字都是擠成一團的很不好辨認 key-value pairs。在 R console 中執行下面的代碼就可以清晰看到各組合了: ```r toJSON(fromJSON(content(film_json, "text")), pretty=TRUE) ```
#### >> Loop over IDs
上面有提到說如果要獲取全部數據那么我們就要嘗試遍歷所有 id。目前豆瓣對於 api 的訪問頻率是有限制的,我了解到的是每分鍾不超過 40 次。所以在兩次訪問之間要設置合理的時間差。

而且並不是每個 id 都一定有對應的頁面,因此在遍歷的過程中還要剔除無效 id。這時候就可以用上 tryCatch 法器了。

basic_url <- "https://api.douban.com/v2/movie/subject/"
film <- data.frame()
for (ii in 1:100){ #just for example not real id
  Sys.sleep(runif(1,1,2)) # set time interval
  tryCatch(
    {
      url <- paste0(basic_url, ii)
      film_json <- GET(url, query = list(apikey="your_api_key"))
      if(status_code(film_json) != 200)
        next
      film <- rbind(film, getFilmInfo(film_json,ii)) #user-defined function
    },
    error = function(cond) {
      message("Here's the original error message:")
      message(cond)
      message("\n")
    }
  )
}

以上只是拋磚引玉,而除了豆瓣以外還有很多可用的 api (可以上 Github 查一查),多加利用哦,數據就是生產力 !


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM