코드

[PHP] 기상청 RSS 시간별 예보 위젯 - cache 적용(?)

by 이니스프리 posted Oct 28, 2018
?

단축키

Prev이전 문서

Next다음 문서

ESC닫기

크게 작게 위로 아래로 댓글로 가기 인쇄
Extra Form
라이선스 MIT

안녕하세요?


아침부터 천둥번개가 치던데 다들 주말 아침 잘 보내고 계시는지요? ^^


올해에도 작년 겨울처럼 춥다면 기상예보를 자주 확인하게 될 것 같네요.


그래서 기상청 RSS를 파싱하여 다음과 같은 2단 위젯 형태로 보여주는 PHP 스크립트 파일을 작성하였습니다.

(기상청 RSS 출처: http://www.weather.go.kr/weather/lifenindustry/sevice_rss.jsp)



이번에는 시인성 등 디자인적인 요소도 최대한 고려하여 만들어보려고 노력했어요 ^^


지난번에 기상청 중기예보를 carousel 형태로 만들어서 사용해보니 


carousel보다는 2단 위젯 형태가 보다 한 눈에 잘 들어올 것 같더군요.





이번 스크립트를 작성할 때에는 테이블의 CSS 디자인과 cache에 대해 공부해보는 것을 목적으로 했습니다.


cache에 대해 어떻게 구현해하는지 참고할 자료가 없어서 막막했는데요.

(생활코딩에는 코드 이그나이터에서의 cache에 대한 내용만 있더군요 ㅠㅠ)


RSS 파일을 불러와서 O시 XX분에 저장한 후에 O시 59분이 지나기 전에 다시 위젯을 확인하면


새로 RSS 파일을 불러오지 않고 저장된 파일을 열어서 보여주는 방식을 택했습니다.


기상예보가 시간별로 발표되기 때문에 이렇게 했는데요.


과연 이 방법이 cache로서 적절한지는 잘 모르겠습니다 ㅠㅠ



그리고 네모 님께서 저번에 말씀해주신 다음과 같은 내용이 큰 도움이 되었습니다 ^^


1. HTML 태그를 도중에 닫으면 안 된다.


2. PHP의 for문 내부에 HTML 코드를 섞어서 작성할 수 있다.



<!DOCTYPE html>
<html>
   <head>
      <style>
         div.weather {
            column-count: 2;
            column-gap: 0.8em;
            padding-left: 5px;
         }
         table {
            border-collapse: separate; // spacing으로 테이블에 입체감(?)을 주기 위해 이렇게 했습니다.
            border-spacing: 3px;
            border-left: 5px solid #369;
            border-bottom: 3px solid black;
            border-right: 1px solid #ccc;
            border-top: 1px solid #ccc;
            -webkit-border-radius: 8px; // 둥근 모서리로 처리했습니다.
            -moz-border-radius: 8px;
            border-radius: 8px;    
         }
         td {
            text-align:center;
            padding-left: 2px;
            padding-right: 2px;
            border-bottom: 1px solid gray;
         }
         td.day {
            background: #FBEFF8;
            font-weight: bold;
         }
         td.hour {
            text-align:right;
         }
         td.temperature {
            text-align:right;
            background: #F7F7F7;
         }
      </style>
      </style>
   </head>

   <body>
      <?php
         include("./simple_html_dom.php"); // Simple HTML DOM Parser를 사용했습니다.
         $filename = './check_kma.txt';
         if (file_exists($filename)) // cache 파일이 존재하면 작성시간을 비교합니다.
            $lastmod = date("d_H", filemtime($filename));
         if (date("d_H") == $lastmod) { // 파일 작성시간과 같은 시각이면 파일을 불러옵니다.
            $rssfile = @fopen($filename, "r");
            $response = fread($rssfile, filesize($filename));
            fclose($rssfile);
         }
         else { // 파일 작성시간과 다른 시각이면 RSS 파일을 다시 불러옵니다.
            $url = "http://www.kma.go.kr/wid/queryDFSRSS.jsp?zone=지역코드";
            $ch = cURL_init();
            cURL_setopt($ch, CURLOPT_URL, $url);
            cURL_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
            $response = cURL_exec($ch);
            cURL_close($ch);
            $rssfile = fopen($filename, "w");
            fwrite($rssfile, $response); // 새로 읽어온 RSS를 파일로 저장합니다.
            fclose($rssfile);
         }
         
         $rss = str_get_html($response); // RSS에서 날짜, 시간, 온도 등을 파싱합니다.
         $announced_time = $rss->find('header', 0)->plaintext;
         $announced_time = substr($announced_time, 9, 2);
         settype($announced_time, "integer");
         $day = $rss->find('day');
         $hour = $rss->find('hour');
         $temp = $rss->find('temp');
         $sky = $rss->find('wfKor');
         $number = count($hour);
      ?>

      <div class="weather">
         <table style="break-after:column;"> // 위젯 좌측열
            <?php
            for ($n = 0; $n < ($number/2); $n++)
            {
            ?>
            <tr>
               <td class="day"> // 날짜
                  <?php
                     $when = intval($day[$n]->innertext) + $announced_time;
                     echo($when."日");
                  ?>
               </td>
               <td class="hour"> // 시간
                  <?php
                     $time = $hour[$n]->innertext;
                     echo($time);
                  ?>
               </td>
         
                <td class="temperature"> // 날짜
                  <?php
                     $temp_int = $temp[$n]->innertext;
                     if ($temp_int >= 10 || $temp_int <= -10) // 문자열 길이를 맞춰줍니다.
                        echo($temp_int."º");
                     else
                        echo(" ".$temp_int."º");
                  ?>
               </td>
               <td class="comment"> // 기상상태
                  <?php
                     $skycomment = preg_replace("/\s+/", "", $sky[$n]->innertext); // 공백 제거
                     echo($skycomment);
                  ?>
               </td>
               <td class="picture"> // 기상상태 png 파일
                  <?php skypicture($skycomment);?>
               </td>
               <?php }?>
            </tr>
         </table>
         
         <table> // 위젯 우측열 (좌측과 동일합니다)
            <?php
               for (; $n < $number; $n++)
               {
            ?>
            <tr>
                <td class="day">
                   <?php
                      $when = intval($day[$n]->innertext) + $announced_time;
                      echo($when. "日");
                   ?>
                </td>
                <td class="hour">
                   <?php
                      $time = $hour[$n]->innertext;
                      echo($time);
                   ?>
                </td>
             
                <td class="temperature">
                  <?php
                     $temp_int = $temp[$n]->innertext;
                     if ($temp_int >= 10 || $temp_int <= -10)
                         echo($temp_int."º");
                     else
                         echo(" ".$temp_int."º");
                  ?>
               </td>
               <td class="comment">
                  <?php
                  $skycomment = preg_replace("/\s+/", "", $sky[$n]->innertext);
                  echo($skycomment);
                  ?>
               </td>  
               <td class="picture">
                  <?php skypicture($skycomment);?>
               </td>
               <?php }?>
            </tr>
         </table>
      </div>
   
      <?php
         function skypicture($skycomment) // 기상상태를 png 파일로 보여주는 함수
         {
            if (strpos("맑음", $skycomment) !== false)
               echo "<img src = 'http://www.weather.go.kr/images/icon/DY/DB01.png'>";
            elseif (strpos("구름조금", $skycomment) !== false)
               echo "<img src = 'http://www.weather.go.kr/images/icon/DY/DB02.png'>";
            elseif (strpos("구름많음", $skycomment) !== false)
               echo "<img src = 'http://www.weather.go.kr/images/icon/DY/DB03.png'>";
            elseif (strpos("흐림", $skycomment) !== false)
               echo "<img src = 'http://www.weather.go.kr/images/icon/DY/DB04.png'>";
            elseif (strpos("비", $skycomment) !== false)
               echo "<img src = 'http://www.weather.go.kr/images/icon/DY/DB05.png'>";
            else
               echo "<img src = 'http://www.weather.go.kr/images/icon/DY/DB01.png'>";
            return;
         }
         
         $rss->clear();
         unset($rss);
      ?>
   
   </body>
</html>



제가 현재까지 테스트한 바로는 크롬, 파폭, IE에서 깨지지 않고 작동하네요.


그리고 영하로 떨어지면 온도에 (-) 부호가 붙을텐데 


제 나름대로는 그런 경우까지 고려하여 깨지지 않는지 테스트를 해보려고 노력했네요 ^^

(과연 제대로 작동을 할지는 이번 겨울에 지켜봐야 알 것 같네요 ㅎㅎ)


그리고 table의 스타일로 break-after:column;을 지정했는데요.


구글링 해보니 서포트가 안 되는 브라우저가 있을 것이란 설명이 있던데


다행히 제가 테스트한 환경에서는 작동을 잘 하는 것 같네요 :)



마지막으로 제가 스크립트를 작성하는 과정에서 궁금한 점이 있어서 좀 여쭤보려고 하는데요.


1. cache를 이렇게 파일 형태로 하는 방법이 적절한지 잘 모르겠는데요. 혹시 더 좋은 방법은 없는지 여쭤봅니다 :)


2. 위젯에서 '비'(기상상태) + '우산표시'(PNG 파일) 이 부분을 별도의 td 태그로 나눠서 만들었는데요.


이걸 하나의 td 태그 내에 담으면 텍스트와 그림의 높이가 다르기 때문에 줄이 안 맞아보이더군요 ㅠㅠ


두 개의 td 태그를 묶어서 하나의 border-bottom: 1px solid gray를 적용해서 border-bottom이 이어지도록 하거나


또는 하나의 td 태그에 텍스트와 그림이 포함된 경우에 vertical-align을 middle로 맞추는 방법은 없는지 여쭤봅니다 ^^


border-collapse: separate를 그 부분에만 적용하지 않는 방법은 안 먹히는 것 같더군요.



허접한 스크립트와 장황한 글 읽어주셔서 감사합니다!


그럼 스포어 회원님들께서도 점심식사 맛있게 드시고 좋은 주말 되세요 ^^


답변 달아주실 분들께 미리 감사드립니다~



P.S. 

리얼포스 R2 균등 30g 키보드는 장시간 타이핑할 때 확실히 편하네요! 

개발자 분들이나 워드 작업 많이 하시는 분들께 강추합니다 ^-^

TAG •

Articles

1 2 3 4