Projects
gist

Scrape Daily Daylight (R)

R Script สำหรับดึงข้อมูลเวลาดวงอาทิตย์ขึ้น-ตก และคำนวณช่วงแสงในแต่ละวันจากสมาคมดาราศาสตร์ไทย

นี่คือโค้ด R ที่ใช้สำหรับดึงข้อมูลเวลาพระอาทิตย์ขึ้นและพระอาทิตย์ตกจากเว็บไซต์สมาคมดาราศาสตร์ไทย (thaiastro.nectec.or.th) จากนั้นนำข้อมูลมาคำนวณหาความยาวนานของแสงแดด (Daylight Hours) ในแต่ละวันสำหรับจังหวัดที่กำหนด

การดึงข้อมูลชุดนี้มีประโยชน์มากสำหรับการวิจัยที่เกี่ยวข้องกับผลกระทบของสภาพแวดล้อมโดยเฉพาะเรื่องแสง ที่มีต่อการเจริญเติบโตของพืช หรือการศึกษาพฤติกรรมสัตว์

📦 ไลบรารีที่จำเป็นต้องใช้

ก่อนใช้งานโค้ดนี้ ให้ทำการติดตั้งและโหลดไลบรารีเหล่านี้ให้เรียบร้อย:

library(rvest)     # สำหรับทำ Web Scraping อ่านโครงสร้าง HTML และดึงข้อมูล
library(dplyr)     # สำหรับจัดการและทำความสะอาด dataframe
library(stringr)   # สำหรับจัดการรูปแบบข้อความ (String manipulation)
library(lubridate) # สำหรับจัดการและคำนวณวัน-เวลา
library(purrr)     # สำหรับการวนลูปอ่านตารางแต่ละเดือน (Functional programming)

💻 ฟังก์ชัน get_daily_daylight

โค้ดเต็มสำหรับฟังก์ชันที่ใช้ดึงข้อมูล

get_daily_daylight <- function(year, province_name) {
  
  # 1. จัดการตัวเลขปี
  year_ce <- ifelse(year > 2500, year - 543, year)
  index_url <- paste0("https://thaiastro.nectec.or.th/skyevnt/sunmoon/", year_ce, "/")
  
  # 2. ค้นหาลิงก์ของจังหวัดเป้าหมาย
  index_page <- tryCatch(
    read_html(index_url, encoding = "UTF-8"),
    error = function(e) { stop(paste("ไม่สามารถเข้าถึงข้อมูลสารบัญของปี", year_ce)) }
  )
  
  links <- index_page %>% html_nodes("a")
  prov_df <- data.frame(
    province = html_text(links) %>% str_trim(),
    href = html_attr(links, "href"),
    stringsAsFactors = FALSE
  )
  
  matched_row <- prov_df %>% filter(str_detect(province, province_name))
  if (nrow(matched_row) == 0) stop(paste("ไม่พบข้อมูลของจังหวัด:", province_name))
  
  # 3. ดึงข้อมูลจากหน้าของจังหวัดนั้นๆ
  target_url <- paste0("https://thaiastro.nectec.or.th/skyevnt/sunmoon/", year_ce, "/", matched_row$href[1])
  target_page <- read_html(target_url, encoding = "UTF-8")
  
  # ดึงตาราง "ทั้งหมด" ในหน้านั้น (เว็บนี้แยก 1 ตารางต่อ 1 เดือน)
  tables <- target_page %>% html_table(fill = TRUE)
  
  # กรองเอาเฉพาะตารางที่มี 11 คอลัมน์ (ตามโครงสร้างมาตรฐานของตารางเวลาเว็บนี้)
  valid_tables <- keep(tables, ~ ncol(.x) == 11)
  
  if (length(valid_tables) == 0) stop("ไม่พบตารางที่มีโครงสร้างถูกต้อง (11 คอลัมน์) ในหน้านี้")
  
  # 4. นำตารางทั้ง 12 เดือนมาต่อกัน (Bind rows)
  raw_df <- map_df(valid_tables, function(tbl) {
    # เปลี่ยนชื่อคอลัมน์ชั่วคราวเพื่อให้ต่อกันได้
    colnames(tbl) <- paste0("V", 1:11)
    # แปลงทุกคอลัมน์เป็นตัวอักษรเพื่อป้องกัน Error ชนิดข้อมูลชนกัน
    mutate_all(tbl, as.character)
  })
  
  # ตั้งชื่อคอลัมน์ใหม่ตามโครงสร้างจริง
  colnames(raw_df) <- c("DateStr", "Weekday", 
                        "Sunrise", "Sunrise_Azimuth", 
                        "Sunset", "Sunset_Azimuth",
                        "Moon_Illum", 
                        "Moonrise", "Moonrise_Azimuth", 
                        "Moonset", "Moonset_Azimuth")
  
  # 5. ทำความสะอาดและคำนวณช่วงแสง
  final_data <- raw_df %>%
    # กรองเอาเฉพาะบรรทัดที่เป็นข้อมูลเวลาจริงๆ (สังเกตจากเครื่องหมาย :)
    filter(str_detect(Sunrise, ":") & str_detect(Sunset, ":")) %>%
    mutate(
      Year = year_ce,
      Province = province_name,
      
      # แยกวันที่และเดือนออกจากกัน (เช่น "1 ม.ค." -> Day=1, Month_Th="ม.ค.")
      Day = as.integer(str_extract(DateStr, "^\\d+")),
      Month_Th = str_replace(DateStr, "^\\d+\\s*", ""),
      
      # แปลงข้อความ "HH:MM" เป็นระยะเวลา (Period)
      rise_time = hm(Sunrise),
      set_time = hm(Sunset),
      
      # คำนวณช่วงแสงเป็นชั่วโมง (ทศนิยม)
      Daylight_Hours = round(time_length(set_time - rise_time, unit = "hour"), 2)
    ) %>%
    # จัดเรียงคอลัมน์ที่จำเป็นสำหรับนำไปใช้งานต่อ
    select(Year, Province, Month_Th, Day, Weekday, Sunrise, Sunset, Daylight_Hours)
  
  return(final_data)
}

💡 ตัวอย่างการใช้งานจริง

ดูตัวอย่างฟังก์ชันการดึงข้อมูลความยาวแสงแต่ละวันในปี 2024 ในพื้นที่ต่างๆ

# ดึงข้อมูลของจังหวัดพัทลุง ในปี ค.ศ. 2024
phatthalung_daylight <- get_daily_daylight(2024, "พัทลุง")

# ตรวจสอบ 5 บรรทัดแรกของตารางข้อมูล
head(phatthalung_daylight)

# ดึงข้อมูลของกรุงเทพมหานคร ในปี ค.ศ. 2025
bkk_daylight <- get_daily_daylight(2025, "กรุงเทพมหานคร")
head(bkk_daylight)