本頁重點:

在Windows環境下,從網站下載rar壓縮檔,並解壓縮至特定資料夾

背景介紹與目的


最近被問“在R中要如何解壓縮rar檔”;

上網查查發現R Community解答,但解答中只部份提及解決方法:

  • 使用base::system2:
    • 於R環境中使用系統指令,進行rar檔案解壓縮。

目前R沒有相關的function可以直接使用,所以希望能提供如何在R中解壓縮.rar檔案的完整說明。

環境


  1. R version 3.6.1 (2019-07-05)

  2. RStudio Desktop version 1.2.1335

  3. Platform: x86_64-w64-mingw32/x64 (64-bit)

  4. Running under: Windows 10 x64 (build 18362)

方法


流程說明:
1. 建立資料夾。
2. 取得下載rar壓縮檔的網址。
3. 從網站下載rar壓縮檔至指定資料夾。
4. 以系統指令使用7-zip應用程式,解壓縮rar壓縮檔至指定資料夾。

  • 需要的套件:
library(magrittr)#pipe
library(rvest)   #web scraping
## Loading required package: xml2
library(plyr)    #l_ply

前置作業


  • 建立兩個資料夾放置檔案:

    1. 由網址下載的壓縮檔
    2. 解壓縮後的檔案
#以特殊工業區歷年檔案為例
#建立特殊工業區壓縮檔及解壓縮檔資料夾
dir.create("D:/r/ncdr/sp/")
dir.create("D:/r/ncdr/sp/rar")
dir.create("D:/r/ncdr/sp/unrar")
  • 取得歷年資料下載網址:
#爬歷年資料網址

yearDataURLs <- read_html("https://air.epa.gov.tw/EnvTopics/AirQuality_4.aspx") %>% html_nodes("a") %>% html_attr("href") %>%
  .[which(regexpr("rar$", .) > 0)] %>% gsub(pattern = "^..", replacement = "https://air.epa.gov.tw")
  1. read_html : 讀入包含檔案下載網址的網頁

  2. html_nodes("a") : 取得網頁中所有超連結節點。

  3. html_attr("href") : 取得超連結節點中href屬性的內容(就是網址)。

  4. .[which(regexpr("rar$",.)>0)]取得所有網址中字尾是rar的網址

    • regexpr : 符合條件(pattern)傳回大於零的數值(符合條件的文字位置),不符合條件即傳回-1。

    • pattern(正則表達式) : rar$代表rar這段文字只能出現在字尾,rar前面有或沒有任何文字都可以

    • 正則表達式特殊符號 : $代表字尾,即“rar”這段文字後不能接任何文字或空白。

輸出結果:
../EnvDownload/AirQuality/2018%E4%B8%80%E8%88%AC%E7%A9%BA%E6%B0%A3%E6%B1%A1%E6%9F%93%E7%89%A9.rar

  1. gsub(pattern = "^..",replacement = "https://air.epa.gov.tw")
    將開頭的兩個字替換成主要網域網址。

    正則表達式:

    說明:
    1. 確定文字位置 : ^ 文字開頭。
    2. 控制特定文字內容 : . 指任意一個字的意思。

替換結果:
https://air.epa.gov.tw/EnvDownload/AirQuality/2018%E4%B8%80%E8%88%AC%E7%A9%BA%E6%B0%A3%E6%B1%A1%E6%9F%93%E7%89%A9.rar


  • 壓縮檔的路徑名稱建立:
    (因為下載檔案時需要指定路徑)

    其實部份網址只是由中文轉為HTML的URL編碼:

    url_unescape("../EnvDownload/AirQuality/2018%E4%B8%80%E8%88%AC%E7%A9%BA%E6%B0%A3%E6%B1%A1%E6%9F%93%E7%89%A9.rar") [1] "../EnvDownload/AirQuality/2018一般空氣污染物.rar"

[ 版本一 ]以整體文字只要替換部分文字即可為出發點

整體文字 https://air.epa.gov.tw/EnvDownload/AirQuality/2018%E4%B8%80%E8%88%AC%E7%A9%BA%E6%B0%A3%E6%B1%A1%E6%9F%93%E7%89%A9.rar

取代https://air.epa.gov.tw/EnvDownload/AirQuality/D:/r/ncdr/sp/rar/

取代後 D:/r/ncdr/sp/rar/2018%E4%B8%80%E8%88%AC%E7%A9%BA%E6%B0%A3%E6%B1%A1%E6%9F%93%E7%89%A9.rar

再使用url轉碼轉回中文字

完整的RAR檔案路徑 D:/r/ncdr/sp/rar/2018一般空氣污染物.rar

#準備檔案名稱

#版本一: gsub 取代
filenames <- gsub(
  "https://air.epa.gov.tw/EnvDownload/AirQuality/",
  "D:/r/ncdr/sp/rar/",
  yearDataURLs
) %>% url_unescape()

[ 版本二 ]以需要的文字在什麼位置為出發點

  • 目標文字的起始點與終點

所以起始點為https://air.epa.gov.tw/EnvDownload/AirQuality/的文字個數加一,終點為整個網址的文字個數。

#準備檔案名稱

#版本二:substring 文字位置
startposi <- nchar("https://air.epa.gov.tw/EnvDownload/AirQuality/") + 1
endposi <- sapply(yearDataURLs, nchar, USE.NAMES = F)
filenames <- sapply(1:length(endposi), function(i)
  substring(yearDataURLs[i], startposi, endposi[i]) %>% url_unescape() %>% paste0("D:/r/ncdr/sp/rar/", .)) 
  • 起始點 : 使用nchar取得 https://air.epa.gov.tw/EnvDownload/AirQuality/的文字個數後加一。

  • 終點 : 因為每個網址的文字個數都不一樣,以sapply應用nchar於多個網址文字,而取出多個網址的文字個數。

  • 組合RAR檔名 : 以sapply控制網址個數,以substring取出一個個網址中相同起始點,而不同終點位置的RAR檔名文字,取出檔名後,由url_unescapeurl轉碼轉回中文字,再paste0合併檔案目錄,即有完整的RAR檔案路徑。

[ 版本三 ]以需要什麼樣的文字為出發點

#準備檔案名稱

#版本三:regexpr 正則表達式
filenames <- regexpr("[0-9]{4}.+", yearDataURLs) %>% regmatches(x = yearDataURLs) %>% url_unescape() %>% paste0("D:/r/ncdr/sp/rar/", .)
  1. 利用regexpr(pattern)regmatches取出符合正則表達式條件的文字。
    正則表達式[0-9]{4}.+$, 代表取出0到9的數字出現四次後到一直到字尾的文字。

    目標文字 2018%E4%B8%80%E8%88%AC%E7%A9%BA%E6%B0%A3%E6%B1%A1%E6%9F%93%E7%89%A9.rar

    正則表達式:

    說明:
    1. 控制特定文字內容 :
      [0-9]{4} 指四位數字中,任一位數字都是由0到9其中一個數字組成。
      [0-9]{4}.+ 指四位數字後接著一個以上的文字或空白。
  2. 取出目標文字後,使用url_unescape轉碼為原本的文字編碼。

    目標文字轉碼為原本的文字編碼2018一般空氣污染物.rar


結果


  1. download.file: 從網站下載rar壓縮檔(yearDataURLs)至指定檔案路徑(filenames)。

  2. system2: 以系統指令使用7-zip應用程式(C:/Program Files/7-Zip/7z.exe),解壓縮rar壓縮檔(filenames)至指定檔案path(D:/r/ncdr/sp/unrar)。

7-zip系統指令

C:/Program Files/7-Zip/7z.exe x D:/r/ncdr/sp/rar/2018一般空氣污染物.rar -oD:/r/ncdr/sp/unrar

x :解壓縮壓縮檔,x 後面空一格後,填入壓縮檔路徑(D:/r/ncdr/sp/rar/2018一般空氣污染物.rar)此指令詳細說明

-o :設定解壓縮至指定目錄下,-o 後面空一格後,填入所指定資料夾的路徑(D:/r/ncdr/sp/unrar)此指令詳細說明

#開始下載所有壓縮檔,並進行解壓縮
l_ply(1:length(yearDataURLs), function(i) {
  download.file(yearDataURLs[i], destfile = filenames[i], mode = "wb")
  #利用base::system2執行dos指令,以7-zip解壓縮rar檔到D:/r/ncdr/sp/unrar
  system2("C:/Program Files/7-Zip/7z.exe",
          args = paste0("x ", filenames[i], " -oD:/r/ncdr/sp/unrar"))
})

討論


突然遇到無法直接用R的function解決的問題怎麼辦

希望使用R下載並解壓縮RAR檔案時,因為unzip沒辦法解壓縮RAR檔,我開始上網搜尋unrar in r,當查到stackoverflow解答,但是因為我看不懂解答code的內容跟解釋,很多沒看過的術語(例如-o到底是啥意思QQ),所以也沒辦法把code拿來用,就我個人而言,反而是R Community解答比較能看懂在R中解壓縮檔案需要克服的問題,主要需要利用既有的應用程式解壓縮rar檔案,而且可以用system2執行此應用程式指令進行解壓縮,再去查詢7-zip應用程式系統指令的使用方法,最後就寫出上述的程式碼。

需要看過7-zip應用程式系統指令的使用方法才能了解stackoverflow解答的內容,我覺得在解釋程式碼時,還是先解說流程後,才展示說明詳細的程式碼會比較好理解。

希望上述內容可以幫助在R中解壓縮rar檔有障礙的朋友們XD

補充說明(網頁抓取和正則)


抓取網頁上的資料和專門進行文字處理的正則表達式有興趣的鄉親朋友們可以繼續看下方內容。

在網頁抓取的部分,可以看下我之前寫的R實習筆記(二)-取得環保署網頁的AQI色碼,其實方法大同小異 ,找標籤用css選節點,了解是需要節點的內容rvest::html_text或是節點屬性的內容rvest::html_attr。(我還太菜還有很多要學習的٩(๑❛ᴗ❛๑)۶)

正則表達式主要功能是取出符合模式的文字,所以只要文字處理相關都是很好用的方法,唯獨學習門檻超高QQ,其中正則表達式的學習訣竅就是別想為什麼這麼多奇怪符號啦XDD,了解一下我個人在寫正則表達式時思考的過程,可能會對想學習正則的人比較友善(?),其一文字有沒有要出現在字首或字尾,其二要出現什麼特定的文字,是數字、空格或是英文,而組合這些特定文字出現的條件,其三為特定條件要出現的次數,以上是我個人的想法´・ᴗ・`

例如取出RAR檔的正則表達式 [0-9]{4}.+

  1. 年份的四位數字不是出現在網址的字首或字尾。

  2. 只要是四位數字就可以確定為年份數字,因為文字中沒有其他出現四位數字的部分,所以寫成[0-9]代表0到9的任一數字,而其實都是2015~2019年的數字,所以也可以寫成201[5-9]代表201後面可以接5到9的任一數字。

  3. 由於[0-9]代表0到9的任一數字,而需要的年份數字有四個位數,所以額外加上文字的出現次數為四次,所以寫成[0-9]{4}{} 中間寫的數字為前方條件出現的次數,所以一定是決定完文字出現的條件才能控制次數

  4. 重複1 ~ 3步驟的思考,表達自己需要的文字模式,由於目標的文字是由年份數字到字尾的部分,所以需要增加文字的範圍到字尾,寫成[0-9]{4}.+取得從年份數字到字尾的文字;
    .為特殊的正則表達式符號是指任意一個字或空白的意思,因為有一個以上的文字接在年份數字後面,所以使用+表示前一個條件出現一次以上,故.+取得一個以上的文字到字尾。

補充:希望使用“.”這個文字時,需要在正則表達式寫成\\.

所以短短的正則表達式就可以取得想要的文字內容,是不是很方便呢~~

在Help輸入regexpr就有base中pattern使用正則表達式的函數, 粗略地說我比較常用的函數:

  • grep(value = T) : 傳回向量中符合模式的元素。

  • grepl : 傳回TRUE/FALSE,向量中各個文字元素是否符合模式。

  • gsub : 替換符合模式的文字,而傳回替換結果。

  • regexprregmatches : 傳回向量元素中符合模式的文字片段。 (regexpr先傳回符合模式的文字位置,regmatches再傳回符合模式的文字內容)

R實際應用正則表達式的範例


希望取出向量 c(“EPA2019_data”,“EPA2016_data”,“EPA1999_data”) 中的年份四位數字, 只有gsubregexpr regmatches能取出年份四位數字。

文字向量元素

text<-c("EPA2019_data","EPA2016_data","EPA2015_data")
  • 傳回向量元素
grep("([0-9]{4})",text,value = T)
## [1] "EPA2019_data" "EPA2016_data" "EPA2015_data"
  • 傳回向量元素是否符合模式TRUE/FALSE
grepl("([0-9]{4})",text)
## [1] TRUE TRUE TRUE
  • 傳回替換結果:
    以([0-9]{4})為一組,所以用\\1替換,如EPA2019_data2019取代(我知道有點難懂XD),gsub中關於replacement參數有更詳細的解說。
gsub(".+([0-9]{4}).+","\\1",text)
## [1] "2019" "2016" "2015"
  • 傳回向量元素中符合模式的文字片段
regmatches(text,regexpr("([0-9]{4})",text))
## [1] "2019" "2016" "2015"