조회 수 990 추천 수 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
번호 분류 제목 글쓴이 날짜 조회 수
38 코드 파이선 셸에서 실행하면...? 3 제르엘 2018.07.22 546
37 코드 [Python] 모 정부기관 사이트 파싱 후 PC 통신처럼 열람하고 싶은 게시글 번호를 입력하면 내용을 보여주는 소스 (허접) 4 이니스프리 2018.09.14 742
36 코드 [오토핫키] 특정 사이트에 대한 ping 테스트 결과를 실행시간과 함께 로그 파일로 저장하는 스크립트 2 이니스프리 2018.09.22 2052
35 코드 [오토핫키] 구글 드라이브의 공유링크를 이미지 호스팅을 위한 다이렉트 링크로 바꿔주는 스크립트 10 file 이니스프리 2018.09.25 1754
34 코드 [PHP] 기상청 중기예보를 캐러셀로 보여주는 위젯 (매우 허접합니다 ㅠㅠ) 10 file 이니스프리 2018.09.28 733
33 코드 [오토핫키] 브라우저를 열어 지난번과 동일한 폴더에 MZK를 다운받고 압축을 네이티브로 해제하는 스크립트 file 이니스프리 2018.10.20 918
» 코드 [PHP] 기상청 RSS 시간별 예보 위젯 - cache 적용(?) 9 file 이니스프리 2018.10.28 990
31 코드 [PHP] 그누보드 자동 게시글 작성 - 일본기상협회의 우리나라 날씨를 크롤링한 후 파파고로 번역하여 글 작성 4 file 이니스프리 2018.11.15 821
30 코드 [아미나] 게시글을 작성하면 ID와 IP로 필터링하여 자동으로 랜덤 댓글을 남기기 (+랜덤 포인트) 7 file 이니스프리 2018.11.18 803
29 코드 [Python] 텔레그램을 이용한 게시판 새 글 알림봇 7 이니스프리 2018.12.02 3977
28 코드 [PHP] 간단한 캐싱 클래스 3 title: 황금 서버 (30일)humit 2018.12.06 855
27 코드 [아미나] 출석 여부를 나타내는 메인화면 위젯 4 file 이니스프리 2018.12.15 769
26 코드 [아미나] 네이트 실시간 검색어 순위 위젯 (아미나 캐시 적용) 3 file 이니스프리 2018.12.18 1122
25 코드 [PHP] 이미지를 원하는 크기(원본비율 유지)로 리사이즈 하여 출력 (원본 이미지는 수정하지 않습니다) 6 이니스프리 2018.12.20 7994
24 코드 [JS] http를 https로 리디렉션! 3 Hanam09 2018.12.30 839
23 코드 [JS]클라이언트에서 Ip를 얻어보자 2 Hanam09 2019.01.21 776
22 코드 [Python] 선택한 파일을 Dropbox API를 이용하여 업로드하고 공유링크를 받아서 이미지 호스팅 용도로 URL을 변환하기 1 file 이니스프리 2019.07.02 1166
21 코드 [Python] Selenium을 이용하여 특정 element를 캡처하는 스크립트 2 file 이니스프리 2019.07.03 6105
20 코드 [PHP/Javascript] 아미나에 자동으로 게시글을 생성하고 Ajax로 전송하여 결과를 표시하기 2 file 이니스프리 2019.07.09 925
19 코드 [Python] 네이버 모바일 이미지 검색에서의 이미지 파일을 멀티스레드로 다운받고 1개의 파일로 병합 11 file 이니스프리 2019.07.12 1473
Board Pagination Prev 1 2 3 4 Next
/ 4