조회 수 982 추천 수 0 댓글 9
?

단축키

Prev이전 문서

Next다음 문서

크게 작게 위로 아래로 댓글로 가기 인쇄 첨부
?

단축키

Prev이전 문서

Next다음 문서

크게 작게 위로 아래로 댓글로 가기 인쇄 첨부
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 •
  • profile
    NoYeah 2018.10.29 00:24
    키보드 리얼포스로 구매하셨나보네요! 저는 가격때문에 만져보지도 못하는... 부럽습니다. ㅋㅋ
    디자인이 90년대 컴퓨터 학원에서나 보던 그런 디자인이긴 한데 또 그 때의 키감만한 키보드가 흔치않죠.

    리얼포스 R2가 그렇게 평이 좋던데 타이핑할 때 도움 많이 되시겠습니다~
  • profile
    이니스프리 2018.10.29 05:58
    기계식만큼은 아니지만 관리만 잘 해주면 수명이 길테니 오래 사용할 것이라고 마음먹고 구입했어요 ^^
    제가 예전에 엘보 부상 때문에 고생한 기억이 있어서요.
    맛스타 님께서도 손목이나 팔꿈치가 안 좋으시다면 추천 드립니다!
    몇 개월 꾸준히 사용해보고 스포어에 후기 올리겠습니다 :)

    8, 90년대에 당시에 컴퓨터 구입하면 번들로 제공되던 알프스 키보드가 요새 고가에 거래되더군요 ㅠㅠ
    집에 몇 개 굴러다녀서 친구들에게 그냥 줬던 기억이 나는데 말이죠.
    그럼 오늘도 좋은 하루 되세요~!
  • profile
    title: 황금 서버 (30일)humit 2018.10.31 19:57
    ㄷㄷ... 가격을 찾아보니 거의 30만원이군요..;;
    나중에 많이 벌 때 한 번 생각해봐야겠네요;;
  • profile
    title: 황금 서버 (30일)humit 2018.10.31 20:01 Files첨부 (1)

    https://caniuse.com/
    위 사이트에 가시면 어떤 브라우저에서 동작하는지 바로 알 수 있습니다.

    break-after로 검색한 결과 사진입니다~

  • profile
    이니스프리 2018.10.31 20:58

    바쁘신데 댓글 달아주셔서 감사합니다!

    말씀해주신 사이트가 모질라 홈페이지보다 CSS 지원 여부에 대해 정리가 훨씬 잘 되어있네요 :)


    리얼포스 R2는 제가 손목이 좋지 않은 편이라서 큰 맘 먹고 구입했어요 ㅠㅠ

    타건샵에서 여러 제품을 비교해본 후에 구입했는데요.

    제가 여태껏 사용해본 키보드 중에서는 손에 가장 덜 무리가 가는 제품인 것 같아요.


    어느덧 11월이 다가왔는데 humit 님께서도 전역하시는 날까지 감기 조심하시고 건강하시길 기원합니다!!

    항상 감사드립니다 ^-^

  • profile
    title: 황금 서버 (30일)humit 2018.11.01 17:51
    저도 나중에 전역하면 타건샵 한 번 가봐야 겠네요 ㅎㅎ...
    혹시 추천하실만한 타건샵이 있을까요?
  • profile
    이니스프리 2018.11.01 18:44

    용산에서는 선인상가 21동 3층의 피씨기어와 신용산역 지하상가의 리더스키가 가장 유명해요.

    저도 열흘 전에 갔는데 군복 입으신 분들이 계시더군요 ^-^


    매장 자체는 리더스키가 조금 더 넓고 인테리어를 잘 꾸며놓았지만

    피씨기어가 조금 덜 붐비고 제 개인적인 느낌이지만 사장님께서 조금 더 친절하신 것 같아요~

    저는 구입 리스트에 올려놓은 제품들이 타건 가능한지 전날에 전화로 문의했는데

    피씨기어 사장님께서 전화 응대도 친절하시더군요 :)

    제가 궁금한 점을 이것저것 질문 드려도 아주 상세하게 설명해주셨구요.

    나중에는 키보드 가져와서 의자에 앉아서 타건해보라고 권해주셨어요 ㅎㅎ

    (아마 손님이 거의 없는 시간대여서 그랬던 것 같네요)

    토요일에 열지 않는 매장도 있고, 영업시간이나 점심시간에 차이가 있으니

    미리 확인해보고 가시는 것을 추천 드려요~


    그리고 저는 한 번도 못 가봤지만 

    선인상가의 리썬즈몰도 위 두 매장과 비슷한 스타일이고 마찬가지로 유명하다고 알고 있구요.

    조금 더 대중적인 모델은 구산컴넷에 많이 있다고 하더군요.

    (제 기억이 맞다면 다른 손님분의 재고 질문에 대해 피씨기어 사장님께서 구산컴넷에 가보라고 안내해주셨어요)


    타건샵에 진열된 제품들은 이미 손을 많이 탔기 때문에

    개봉 직후의 물건과는 키감이 전혀 다른 경우도 많다고 하더군요 ㄷㄷ

    그래서 저는 피씨기어 사장님께 개봉한지 얼마나 경과한 제품인지 여쭤보고 타건했어요 ^^


    결론적으로 타건해보고 싶으신 모델이 있는지 미리 확인하고 방문하시는 것을 추천드리구요.

    친절하고 덜 붐비는 환경에서 여유있게 타건해보시려면 피씨기어를 추천드립니다 :)

  • profile
    title: 황금 서버 (30일)humit 2018.11.01 18:48
    오오 감사합니다!!
  • profile
    이니스프리 2018.11.11 13:26
    한달이 넘어가는 시점에서 날짜가 잘못 표시되는 문제가 있어서
    strtotime 함수를 이용하여 그 부분을 수정해서 올립니다 :)


    <!DOCTYPE html>
    <html>
    <head>
    <style>
    div.weather {
    column-count: 2;
    column-gap: 0.8em;
    padding-left: 7px;
    }
    table {
    border-collapse: separate;
    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>
    </head>

    <body>
    <?php
    include_once("./simple_html_dom.php");
    $filename = './check_kma.txt';
    if (file_exists($filename))
    $lastmod = date("d_H", filemtime($filename));
    if (date("d_H") == $lastmod) {
    $rssfile = @fopen($filename, "r");
    $response = fread($rssfile, filesize($filename));
    fclose($rssfile);
    }
    else {
    $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);
    fclose($rssfile);
    }

    $rss = str_get_html($response);
    $announced_time = $rss->find('tm', 0)->plaintext;
    $announced_day = substr($announced_time, 0, 8);
    settype($announced_day, "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
    $timestamp = strtotime($announced_day + $day[$n]->innertext);
    echo(date("d", $timestamp)."日");
    ?>
    </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("&nbsp".$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>

    <table>
    <?php
    for (; $n < $number; $n++)
    {
    ?>
    <tr>
    <td class="day">
    <?php
    $timestamp = strtotime($announced_day + $day[$n]->innertext);
    echo(date("d", $timestamp)."日");
    ?>
    </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("&nbsp".$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)
    {
    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>

List of Articles
번호 분류 제목 글쓴이 날짜 조회 수
58 코드 사이트 서버 이전 (또는 미러링 사이트 구축) 쉽게하는 스크립트 1 NoYeah 2018.01.14 1027
57 코드 유튜브에 약간의 기능을 추가 해주는 크롬 확장 프로그램. 11 file Hanam09 2018.01.26 1076
56 코드 컴퓨터의 uuid 얻기 5 title: 황금 서버 (30일)humit 2018.01.28 1220
55 코드 CMD로 로컬 연결 고정 IP 설정하기 1 title: 황금 서버 (30일)humit 2018.02.06 1092
54 코드 Cmd 에서 서비스 시작 / 종료하기 1 ProjectSE 2018.02.18 691
53 코드 미완성 받아쓰기 (C) title: 대한민국 국기gimmepoint 2018.04.20 565
52 코드 아주 간단한 기초 C++ 6 제르엘 2018.04.21 567
51 코드 Hello, World!를 출력해보자 18 네모 2018.04.21 661
50 코드 html 초보가 만든 자소서 4 title: 대한민국 국기gimmepoint 2018.04.21 730
49 코드 c 이진트리 전,중,후위 알고리즘 2 title: 대한민국 국기gimmepoint 2018.04.24 642
48 코드 HEX를 RGB로, RGB를 HEX로 바꾸는 PHP 코드 1 네모 2018.05.05 672
47 코드 클라이언트단에서 이미지 리사이징 6 file 네모 2018.05.06 1154
46 코드 내가 만든 함수 모음집 4 title: 대한민국 국기gimmepoint 2018.05.08 520
45 코드 내가 만든 사칙연산 계산기 title: 대한민국 국기gimmepoint 2018.05.11 621
44 코드 내가 만든 함수 모음집 2 title: 대한민국 국기gimmepoint 2018.05.12 528
43 내가 만든 merge sort 3 title: 대한민국 국기gimmepoint 2018.05.17 528
42 코드 매우 특이한 버그 9 title: 대한민국 국기gimmepoint 2018.06.05 720
41 코드 잘못 쓰면 컴퓨터가 날아가는 코드 29 제르엘 2018.07.08 1016
40 코드 폰트를 자동 설치하는 코드 1 네모 2018.07.16 972
39 코드 C언어 삼중자를 이용한 코드 title: 황금 서버 (30일)humit 2018.07.22 481
Board Pagination Prev 1 2 3 4 Next
/ 4