--- image:https://i.imgur.com/mVZVshx.png --- # 用R做網頁爬蟲+風花圖 :::warning **更新:現在氣象局的 [CODiS 氣候資料服務系統](https://codis.cwa.gov.tw/)已經更改網頁介面,這篇介紹的方法已經沒辦法再使用,只能用 python 自動抓取,或者手動下載資料再用 R 整理,目前尚無解。** ::: 風花圖,又叫做風玫瑰圖(wind rose),是一種呈現風向、風速與頻度分布的資訊繪圖,從圖面上可以了解某地在特定時間的風向、風速概要,在設計機場跑道方向或者設計建築物座向時都會用到。 <center> <img src="https://i.imgur.com/HsKMnRq.png" width=50%> 中央氣象局氣候年報所使用的風花圖圖例。 </center> --- 最近需要製作中央氣象局香山氣象站的氣候圖與風花圖,因此研究了一下如何用 R 簡單繪製,最後找到了阿好伯的文章〈[以R語言爬取監測站歷史資料並以ggplot2繪製風玫瑰圖(風花圖,Wind Rose)_大寮測站為例](https://hackmd.io/@LHB-0222/Wind_Rose)〉,裡面詳細記錄了如何用 R 從氣象局的測站資料網把資料爬下來,再繪製成風花圖。不過我想做的是彙整各年度冬、夏季的資料,所以有一些不同,稍微更改一些程式碼,記錄在這邊。 首先到氣象局的[測站資料查詢網](https://e-service.cwb.gov.tw/HistoryDataQuery/)找到香山氣象站的**日報表**(才有每個小時的風速、風向資料),看一下網址的組成。 網址長這樣:https://e-service.cwb.gov.tw/HistoryDataQuery/DayDataController.do?command=viewMain&**station=**C0D570&**stname**=%25E9%25A6%2599%25E5%25B1%25B1&**datepicker**=2020-09-09&**altitude**=15m 黑體標記是之後再爬蟲的時候要換掉的部分。 接下來就是把阿好伯大大的程式碼稍做更改如下: ```java! packages <- c("jsonlite", "rvest", "magrittr", "lubridate","ggplot2") invisible(lapply(packages, library, character.only = TRUE)) url_start <- "http://e-service.cwb.gov.tw/HistoryDataQuery/DayDataController.do?command=viewMain&station=C0D570&stname=%25E9%25A6%2599%25E5%25B1%25B1&datepicker=" windcrawler <- function(x,y){ start_date <- ymd(x) end_date <- ymd(y) data1 <- data.frame() data2 <- data.frame() for(d in c(0:(end_date - start_date))){ url <- paste0(url_start,as.character(start_date + d),"&altitude=15m") #時間資料 time_H <- url %>% read_html() %>% html_nodes(xpath='//*[(@id = "MyTable")]//td[(((count(preceding-sibling::*) + 1) = 1) and parent::*)]') %>% html_text(trim = T) %>% as.numeric() #風速資料 Windspeed <- url %>% read_html() %>% html_nodes(xpath='//td[(((count(preceding-sibling::*) + 1) = 7) and parent::*)]') %>% html_text(trim = T) %>% gsub("X","-9999", .) %>% as.numeric() #風向 windDirection<- url %>% read_html() %>% html_nodes(xpath='//td[(((count(preceding-sibling::*) + 1) = 8) and parent::*)]') %>% html_text(trim = T) %>% gsub("X","-9999", .) %>% as.numeric() data1 <- cbind(as.character(start_date + d), time_H, Windspeed,windDirection) #合併資料 data2 <- rbind(data2, data1) } data3 <- na.omit(data2) #刪除包含NA值的列 data3$windDirection_N <- cut(as.numeric(data3$windDirection), breaks = c(0, 11.26, 33.76, 56.26, 78.76, 101.26, 127.76, 146.26, 168.76, 191.26, 213.76, 236.26, 258.76, 281.26, 303.76, 326.26, 348.75, 360), labels = c("N","NNE","NE","ENE","E","ESE","ES","SSE","S","SWS","SW","WSW","W","WNW","NW","NNW","N"), include.lowest = TRUE) data3$風級 <- cut(as.numeric(data3$Windspeed), breaks =c(0, 1.5, 3.3, 5.4, Inf), labels = c("0–1 級", "2 級", "3 級", "3 級以上"), right = F) data3$風速區間 <- cut(as.numeric(data3$Windspeed), breaks =c(0, 0.5, 1.5, 3.0, Inf), labels = c("0–0.5 m/s", "0.5–1.5 m/s", "1.5–3 m/s", ">3 m/s"), right = F) data3$Windspeed <- as.numeric(data3$Windspeed) return(data3) } ``` 觀測資料查詢網的網址結構和阿好伯發文的時候相比,現在多加了 **&altitude=** 在網址最後,在處理時要小心,記得加上。 <br> 因為想了解香山在冬季和夏季的風向異同,所以需要分成冬夏季來抓資料。在這邊定義冬季 12–2 月、夏季是 6–8 月,就以此定義新的函數: ```java= #夏季風向風速資料 windcrawlerS <- function(x){ a = paste0(x,0,601) b = paste0(x,0,831) windcrawler(a,b) } #冬季風向風速資料 windcrawlerW <- function(x){ a = paste0(x-1,1201) b = paste0(x,0,301) windcrawler(a,b) } #舉例:抓取2010年夏季風向風速資料 Summer2010 <- windcrawlerS(2010) ``` 如果要抓取數年的資料,可以寫個迴圈來抓,或者逐年手動抓也可以,最後再用 `rbind()` 合併即可。 <br> 最後是繪製風花圖,有設定字型為[思源柔黑體(源柔ゴシック)](http://jikasei.me/font/genjyuu?reject=yes): ```java! WindSummer <- read.csv("WindSummer.csv") windowsFonts(GJ = windowsFont("Gen Jyuu Gothic P Medium")) WindSummer$風速區間 <- factor(WindSummer$風速區間, levels = c("0–0.5 m/s", "0.5–1.5 m/s", "1.5–3.0 m/s", ">3.0 m/s")) WindSummer$windDirection_N <- factor(WindSummer$windDirection_N, levels = c("N","NNE","NE","ENE","E","ESE","ES","SSE","S","SWS","SW","WSW","W","WNW","NW","NNW")) col = c("gray86", "#19B4C5", "#F9BD21", "#7F1084") SummerRose <- ggplot(WindSummer, aes(x = windDirection_N, fill = 風速區間))+ geom_bar(position = position_stack(reverse = T)) + labs(title = "香山氣象站 2008–2020 年度夏季風花圖") + theme_bw() + theme(plot.title = element_text(hjust = 0.5, face = "bold", size = 32), axis.title.y = element_text(hjust = 0.75, vjust = 2.5, size = 18, color = "azure4"), text = element_text(size=18)) + coord_polar(start = -0.2) + xlab("") + ylim(0, 10000) ggpar(SummerRose, font.family = "GJ", palette = col) ``` <center> <img src="https://i.imgur.com/mVZVshx.png"> 繪製出的風花圖。 </center>   <br> <br> 可以發現香山地區在夏季還是吹北風居多,有可能因為台灣在行星風帶中位於東北信風帶,夏天沒有西南氣流吹來的時候,還是以偏北風為主嗎? 另外,香山測站(C0D570)已經撤銷了,取而代之的是 2022 年 3 月 8 開始有觀測資料的香山濕地測站(C0D680),之後若需要了解香山溼地周遭的氣候,要更換查詢對象了。 最後再次感謝[阿好伯大大](https://hackmd.io/@LHB-0222)。 <span style="font-size:30px">🐕‍🦺</span> <font color="dcdcdc">2022.10.12</font>