?

단축키

Prev이전 문서

Next다음 문서

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

단축키

Prev이전 문서

Next다음 문서

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

안녕하세요?


기상청 중기예보 RSS를 파싱하여 캐러셀 형태로 보여주는 위젯을 만들어보았습니다.


제가 실력이 형편없는 초보자이지만 이렇게 소스를 계속 작성해보고 올리는 이유는 


여기 스포어에 계신 개발자 분들께 여쭤보면서 한 수 배우려는 것이 주된 목적이고,


부수적으로는 제가 올린 스크립트를 제 스스로 보면서 더 분발해서 열심히 공부하려는 취지도 있습니다.


일단 허접한 위젯의 외형은 다음과 같습니다.



캐러설로 보여주는 부분은 Owl Carousel을 사용했습니다.


움짤을 보면 자동 스크롤이 되는 것으로 오해하실 수도 있으나 


그 기능은 활성화하지 않았고 버튼을 클릭해야 스크롤이 되도록 만들었습니다.



일단 아미나를 기준으로 만들었지만 그누보드와는 별개로 작동하고


JQuery를 로드하는 한 줄을 추가하면 독립적으로 실행할 수도 있습니다.

(이건 의도한 것이 아니라 제가 실력이 부족해서 아미나에서 위젯을 설정하는 php 파일을 만들지 못했습니다 ㅠㅠ)



데이터는 기상청 홈페이지의 중기예보 RSS를 이용했습니다. 


아웃도어 활동을 즐기는 분들에게는 오늘의 날씨만큼이나 중기예보가 중요한데요.


아미나에서 작동하는 중기예보 위젯을 찾지 못해서 제가 만들어봤습니다 ㅠㅠ



설명이 길었는데 스크립트는 다음과 같습니다.


Owl Carousel 관련 파일을 건드리지 않기 위해서 이 스크립트에 CSS 스크립트까지 집어넣었습니다 -_-;



<?php
if (!defined('_GNUBOARD_')) exit; // 개별 페이지 접근 불가
?>

<!DOCTYPE html>
<html lang="ko">
  <head>
    <meta charset="utf-8">
      <link rel="stylesheet" href="/css/owl.carousel.min.css">
      <link rel="stylesheet" href="/css/owl.theme.default.min.css">
      <script src="/owl.carousel.min.js"></script>
  </head>
</html>


<?php
  header('Content-Type: text/html; charset=utf-8');
  $url = "http://www.weather.go.kr/weather/forecast/mid-term-rss3.jsp?stnId=109";
  // Id - 강원: 105, 충북: 131, 충남: 133, 전북: 146, 전남: 156, 경북:143, 경남: 159, 제주: 184
  $ch = cURL_init();
 
  cURL_setopt($ch, CURLOPT_URL, $url);
  cURL_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
 
  $response = cURL_exec($ch);
  cURL_close($ch);

  $rss = simplexml_load_string($response);
 
  $rss_time = $rss->channel->item->title; // 발표시간 출력
  $rss_time = explode('-', $rss_time);
  echo "<strong>", $rss_time[1], "</strong><br />";
 
  $rss_comment = $rss->channel->item->description->header->wf; // 코멘트 출력
  echo $rss_comment, "<br /><br />";
?>


<!-- owl-carousel의 색상을 변경-->
<style>
.owl-theme .owl-controls .owl-page.active span {
    border: 2px solid gray;
}

.owl-theme .owl-controls .owl-page span {
    border: 2px solid gray;
}
</style>

<!--owl-carousel의 옵션 변경-->
<script type="text/javascript">
//<![CDATA[
$(document).ready(function(){
  $('.owl-carousel').owlCarousel({
    loop:true,
    autoWidth:true,
    items:3,
    margin:10,
    navigation:true,
    navigationText : ['<', '>'],
})
});
//]]>
</script>

<!-- carousel에 들어갈 태그-->
<!-- 기상청 RSS가 5일 간은 오전 오후로, 나머지 3일은 오전 오후 구분 없이 예보합니다-->
<div class="owl-carousel owl-theme">
  <div class="item" style="width:200px">
    <?php
        $n=0;
        $when = $rss->channel->item->description->body->location[0]->data[$n]->tmEf;
        $when = explode(' ', $when);
        $when = $when[0]; // 날짜만 변수에 넣음
        echo "<strong><font color = 'blue'>", $when, "</font></strong><br />";
        echo "AM: ";
        skystatus($n, $rss);
        echo "<br />PM: ";
        skystatus($n+1, $rss);
        echo "<br />";

        $tmn = $rss->channel->item->description->body->location[0]->data[$n]->tmn; // 온도 출력
        $tmx = $rss->channel->item->description->body->location[0]->data[$n]->tmx;
        echo $tmn, " ~ ", $tmx, "C <br />";
    ?>
  </div>
  <div class="item" style="width:200px">
    <?php
        $n=2;
        $when = $rss->channel->item->description->body->location[0]->data[$n]->tmEf;
        $when = explode(' ', $when);
        $when = $when[0]; // 날짜만 변수에 넣음
        echo "<strong><font color = 'blue'>", $when, "</font></strong><br />";
        echo "AM: ";
        skystatus($n, $rss);
        echo "<br />PM: ";
        skystatus($n+1, $rss);
        echo "<br />";
           
        $tmn = $rss->channel->item->description->body->location[0]->data[$n]->tmn; // 온도 출력
        $tmx = $rss->channel->item->description->body->location[0]->data[$n]->tmx;
        echo $tmn, " ~ ", $tmx, "C <br />";
    ?>
  </div>
  <div class="item" style="width:200px">
    <?php
        $n=4;
        $when = $rss->channel->item->description->body->location[0]->data[$n]->tmEf;
        $when = explode(' ', $when);
        $when = $when[0];  // 날짜만 변수에 넣음
        echo "<strong><font color = 'blue'>", $when, "</font></strong><br />";
        echo "AM: ";
        skystatus($n, $rss);
        echo "<br />PM: ";
        skystatus($n+1, $rss);
        echo "<br />";
           
        $tmn = $rss->channel->item->description->body->location[0]->data[$n]->tmn; // 온도 출력
        $tmx = $rss->channel->item->description->body->location[0]->data[$n]->tmx;
        echo $tmn, " ~ ", $tmx, "C <br />";
    ?>
  </div>
  <div class="item" style="width:200px">
    <?php
        $n=6;
        $when = $rss->channel->item->description->body->location[0]->data[$n]->tmEf;
        $when = explode(' ', $when);
        $when = $when[0];  // 날짜만 변수에 넣음
        echo "<strong><font color = 'blue'>", $when, "</font></strong><br />";
        echo "AM: ";
        skystatus($n, $rss);
        echo "<br />PM: ";
        skystatus($n+1, $rss);
        echo "<br />";
           
        $tmn = $rss->channel->item->description->body->location[0]->data[$n]->tmn; // 온도 출력
        $tmx = $rss->channel->item->description->body->location[0]->data[$n]->tmx;
        echo $tmn, " ~ ", $tmx, "C <br />";
    ?>
  </div>
  <div class="item" style="width:200px">
    <?php
        $n=8;
        $when = $rss->channel->item->description->body->location[0]->data[$n]->tmEf;
        $when = explode(' ', $when);
        $when = $when[0]; // 날짜만 변수에 넣음
        echo "<strong><font color = 'blue'>", $when, "</font></strong><br />";
        echo "AM: ";
        skystatus($n, $rss);
        echo "<br />PM: ";
        skystatus($n+1, $rss);
        echo "<br />";
           
        $tmn = $rss->channel->item->description->body->location[0]->data[$n]->tmn; // 온도 출력
        $tmx = $rss->channel->item->description->body->location[0]->data[$n]->tmx;
        echo $tmn, " ~ ", $tmx, "C <br />";
    ?>
  </div>
  <div class="item" style="width:200px">
    <?php
      $n=10;
        $when = $rss->channel->item->description->body->location[0]->data[$n]->tmEf; // 날짜 출력
        $when = explode(' ', $when);
        $when = $when[0];  // 날짜만 변수에 넣음
        echo "<strong><font color = 'blue'>", $when, "</font></strong><br />";
        skystatus($n, $rss);
        echo "<br />";
 
        $tmn = $rss->channel->item->description->body->location[0]->data[$n]->tmn; // 온도 출력
        $tmx = $rss->channel->item->description->body->location[0]->data[$n]->tmx;
        echo $tmn, " ~ ", $tmx, "C <br /><br />";
    ?>
  </div>
  <div class="item" style="width:200px">
    <?php
      $n=11;
        $when = $rss->channel->item->description->body->location[0]->data[$n]->tmEf; // 날짜 출력
        $when = explode(' ', $when);
        $when = $when[0];
        echo "<strong><font color = 'blue'>", $when, "</font></strong><br />";
        skystatus($n, $rss);
        echo "<br />";
 
        $tmn = $rss->channel->item->description->body->location[0]->data[$n]->tmn; // 온도 출력
        $tmx = $rss->channel->item->description->body->location[0]->data[$n]->tmx;
        echo $tmn, " ~ ", $tmx, "C <br /><br />";
    ?>
  </div>  
  <div class="item" style="width:200px">
    <?php
      $n=12;
        $when = $rss->channel->item->description->body->location[0]->data[$n]->tmEf; // 날짜 출력
        $when = explode(' ', $when);
        $when = $when[0];
        echo "<strong><font color = 'blue'>", $when, "</font></strong><br />";
        skystatus($n, $rss);
        echo "<br />";
 
        $tmn = $rss->channel->item->description->body->location[0]->data[$n]->tmn; // 온도 출력
        $tmx = $rss->channel->item->description->body->location[0]->data[$n]->tmx;
        echo $tmn, " ~ ", $tmx, "C <br /><br />";
    ?>
  </div>
</div>


<?php
function skystatus($n, $rss) // 구름량에 관한 함수 선언
{
  $sky = $rss->channel->item->description->body->location[0]->data[$n]->wf;
  $sky = iconv("UTF-8", "EUC-KR", $sky);
  if (preg_match('/맑음/', $sky) == 1)
  {
    echo "<img src = 'http://www.weather.go.kr/images/icon/NW/NB01.png'/>";
  }
  elseif (preg_match('/조금/', $sky) == 1)
  {
    echo "<img src = 'http://www.weather.go.kr/images/icon/NW/NB02.png'/>";
  }
  elseif (preg_match('/많음/', $sky) == 1)
  {
    echo "<img src = 'http://www.weather.go.kr/images/icon/NW/NB03.png'/>";
  }
  else
  {
    echo "<img src = 'http://www.weather.go.kr/images/icon/NW/NB04.png'/>";
  }
  $sky = iconv("EUC-KR", "UTF-8", $sky);
  echo $sky;
}
?>

(스크립트를 제대로 긁어서 붙여넣었는데 코드 하이라이터에서 보여줄 때 깨지는 부분이 있네요 ㅜㅜ 부득이 파일로 첨부하였습니다)

widget.php 



제가 이 스크립트를 짜면서 궁금했던 부분이 있어서 좀 여쭤보겠습니다 ㅠㅠ


1. 제가 beautifulsoup에 익숙해져서 그런지 simplexml_load_string으로 


$when = $rss->channel->item->description->body->location[0]->data[$n]->tmEf;


이런 식으로 셀렉터를 길게 나열하는 것이 효율적이지 않다고 느껴지는데요.


더 효율적인 방법이나 더 나은 parser는 없는지 여쭤봅니다. 


차라리 정규식을 바로 사용하는 것이 효율적이었을까요?


아참 simplexml_load_file로 url을 바로 불러오지 않고 cURL로 불러와서 simplexml_load_string로 다시 불러온 것은


제가 사용한 웹호스팅(닷홈 무료) 쪽인지 기상청 쪽인지 모르겠지만 막아놓은 것 같더군요 ㅠㅠ



2. 마지막에 함수 선언해 놓은 부분에서 


$sky = iconv("UTF-8", "EUC-KR", $sky) 로 변수 하나씩 변환하여 정규식으로 비교하고 


다시 $sky = iconv("EUC-KR", "UTF-8", $sky) 로 변환해서 출력해야 


인코딩이 안 깨지고 제대로 비교하고 출력이 되던데요.


원래 이렇게 해야하는 것인지 아니면 제가 인코딩 변환에 대해 잘 몰라서 이런 우회적인 방법을 사용한 것인지 모르겠네요 ㅠㅠ



3. 제가 사용한 무료 웹호스팅 환경에서 Owl Carousel이 매뉴얼대로 완벽하게 작동하지는 않는 것 같구요.


캐러셀의 대상이 되는 div 태그 내에 폰트어썸을 사용하면 캐러셀 전체가 깨지던데요 ㅜㅜ


텍스트를 캐러셀로 더 쉽게 구현할 수 있는 방법이 있을까요?


이미지 파일은 bxslider를 많이 사용하길래 시도해봤는데요. 


이 스크립트처럼 텍스트만 사용하려니 깨져서 보이더군요.



4. <!-- carousel에 들어갈 태그--> 부분을 원래 n이 1씩 증가하는 PHP의 for 문으로 짜보려고 했는데요.


for 문의 내용으로 html인 div 태그가 들어가서 for 문을 사용하지 못하고 


결국 ctrl + c, v 해서 스크립트를 길게 나열하게 되었는데요.


이런 경우에 반복문을 돌릴 수 있는 다른 해결책이 없는지 여쭤봅니다.



여러모로 부족하고 장황한 글을 읽어주신 모든 분께 감사드립니다!


그럼 즐겁고 뜻깊은 9월의 마지막 주말 되시기를 기원합니다 ^^


Who's 이니스프리

profile

Make StudyForUs Great Again!

 

CSVpuymXAAAVVpd.jpg

Atachment
첨부 '2'
  • profile
    네모 2018.09.28 20:59
    0.
    5~13 라인에서 이미 html 태그를 닫아버리셨네요. 뭐, 대부분의 브라우저에서 작동은 하니, 일단은 넘어갑시다.

    1.
    jQuery 셀렉터와 비슷한 방식을 사용할 수 있는 라이브러리가 있습니다.
    http://simplehtmldom.sourceforge.net/ 참고하시면 될 것 같습니다.

    2.
    PHP 파일 자체의 인코딩에 문제가 있지 않을까요?
    정규식에 사용된 한글을 저장할 때 EUC-KR로 저장되어, PHP 인터프리터가 해석할 때 인코딩 없이는 오류가 발생하는 것이겠지요.
    UTF-8 형식으로 저장한 뒤 테스트해 보면, iconv 처리 없이도 정상 작동하리라 판단됩니다.

    3.
    그을쎄요... 이 부분은 패스할게요. 둘 다 많이 사용해보지 못해서요.
    다만 호스팅 환경에 따라 차이가 나는건 아닌것 같습니다.

    4.
    <?php for($i = 0; $i < 10; $i++) { ?><div><?php echo $i; ?></div><?php } ?>
    같은 방법으로 작성하시면 됩니다.
  • profile
    이니스프리 2018.09.28 21:24

    입대를 앞두고 바쁘실텐데 네모 님께서 이렇게 댓글을 달아주셔서 정말 감사드립니다!!


    0.

    html 태그를 닫아버리면 안 되는 것이었군요 ㅠㅠ

    아미나 소스를 참고하면서 만들었는데요.

    PHP를 쓰다가 HTML 코드를 쓰고 HTML을 닫아준 후에 다시 PHP를 쓰길래

    저는 그렇게 PHP 시작 전에 HTML을 반드시 닫아줘야 되는 것으로 오해했습니다 ㅜㅜ

    파일의 끝에서 닫아줘야 된다는 말씀이신거죠?

    제가 HTML은 생활코딩 유튜브 강의 들은 것이 전부라서 그런지 기초가 약하네요.

    (강의가 별로라는 의미가 아니라 강의는 이해가 쏙쏙 되게 잘 해주셨는데 제가 연습이 부족했나 보네요 ㅠㅠ)

    더 공부를 열심히 하겠습니다 T.T


    1.

    PHP Simple HTML DOM Parser를 글에서만 접하고 아직 사용해보지 못했는데

    이번 기회에 꼭 사용해보겠습니다 ^^

    감사합니다!!


    2.

    방금 에디터의 환경설정을 확인해보니 인코딩이 '자동인식'으로 되어있네요.

    아무래도 설정상의 문제인 것 같은데 'UTF-8'로 변경하겠습니다 ㅠㅠ


    3.

    미국 유저들이 Owl Carousel 내에 폰트어썸을 잘 사용하고 있던데

    제가 어디에선가 제대로 설정하지 못한 부분이 있는 것 같네요 ㅜㅜ


    4.

    말씀하신 방식으로 for 문 안에 div 태그를 넣어줄 수 있군요!

    제가 미처 그 방법까지 생각을 못했네요 ㅜㅜ


    네모 님 덕분에 많이 배우고 갑니다!!

    번번이 정말 감사합니다 ^-^

  • profile
    네모 2018.09.28 21:37 Files첨부 (1)

    PHP에서 출력되는 값이 없을때는 닫으셔도 됩니다만,

    출력하는 내용이 있다면, HTML 태그 밖에 문자열이 출력되어 문제가 발생합니다.




    거의 대부분의 브라우저에서 HTML 밖의 태그도 출력을 합니다만,

    표준이 아니므로, 해당 코드를 출력하지 않는다고 하여 브라우저가 잘못한 일은 아니라는거죠.

    크롬, FF 등의 브라우저에서, 태그를 닫지 않아도 어느정도 보정이 되는것 처럼,

    브라우저에서 정상적으로 출력을 하기는 해도, 정상적인 코드가 아니므로, 가능하면 출력은 HTML > BODY 안에..!

  • profile
    이니스프리 2018.09.28 21:50
    앗 정말 감사합니다!!
    그림으로 보니깐 이해가 잘 되네요 ^^
    HTML의 body 태그 안에 PHP에서 출력하는 내용까지 담아줘야 되는 것이군요!
    제가 나중에 사이트를 제작할 일이 있으면 꼭 네모 님께 의뢰를 드려야겠네요 ㅎㅎ
    그럼 네모 님께서도 불금 즐겁게 보내세요!
    다시 한 번 진심으로 감사드립니다 (--) (__)
  • profile
    title: 황금 서버 (30일)humit 2018.09.29 15:57
    일단 1에서 simplexml_load_file이 동작하지 않는 이유는 서버에서 allow_fopen_url의 설정 값이 OFF로 되어 있어서 그렇습니다.
    보안상의 문제로 인해 막아놓는 경우가 많으며 이 부분은 직접 호스팅사에 요청을 해서 해제를 하는 방법이 있을 것 같네요.
  • profile
    title: 황금 서버 (30일)humit 2018.09.29 16:01
    그리고 여기에서처럼 단순히 문자열 자체를 비교할 때는 preg_match보다는 strpos를 사용하는 것이 좋습니다.
    http://php.net/manual/kr/function.preg-match.php
    공식 문서에서도 Tip으로 "하나의 문자열이 다른 문자열에 들어있는지 확인하기 위해서 preg_match()를 사용하지 마십시오. 더욱 빠른 strpos()나 strstr()을 사용하십시오."라고 나와있습니다 :)
  • profile
    이니스프리 2018.09.29 16:17
    humit 님께서도 군 복무 중이라 바쁘실텐데 이렇게 허접한 스크립트를 시간 내어 읽어주셔서 정말 감사드립니다!
    여러모로 부족한 스크립트를 올리는 것이 많이 부끄럽지만 humit 님 덕분에 많이 배우게 되네요 ^^

    1. 호스팅 업체측에서 보안상의 이유로 막아놓은 것이었군요.
    제가 연습용으로 닷홈 무료 호스팅을 사용한 것이어서 당장은 큰 불편함이 없지만
    다음에 유료 계정에서 비슷한 문제를 겪으면 말씀해주신대로 해제 요청을 해야겠네요!

    2. 제가 요새 틈틈이 정규식을 공부하다보니 preg_match를 너무 남발한 것 같네요 ㅠㅠ
    이번 주말에 말씀해주신대로 strpos로 수정해보겠습니다!

    그럼 humit 님께서도 좋은 주말 되시고 요새 일교차가 큰데 감기 조심하세요!
    번번이 큰 도움을 주셔서 진심으로 감사드립니다 ^-^
  • profile
    title: 황금 서버 (30일)humit 2018.09.29 16:29
    추가로 1번에서 xpath 함수를 이용하는 방법이 있습니다.
    예제에서처럼 사용한다면 아래와 같이 사용이 가능하겠네요.

    $xml = simplexml_load_string($string);
    $result = $xml->xpath("//description/body/location[1]/data");
  • profile
    이니스프리 2018.09.29 17:06

    XPath() 함수를 이용하면 노드를 보다 쉽게 선택할 수 있군요 ^^

    제가 스크립트를 짜다가 뭔가 이상하다는 느낌이 드는 부분은

    나중에 알고보면 제가 공부가 부족해서 우회적인 방법으로 삽질을 한 경우가 대부분이네요 ㅎㅎ

    프로그래밍 언어의 세계는 저같은 컴맹에게는 정말 심오하네요!

    말씀해주신 XPath()에 대해 공부를 더 하고 스크립트에 반영하여 수정하도록 하겠습니다.

    다시 한 번 진심으로 감사드립니다~

    그럼 humit 님께서도 좋은 주말 되세요!

  • profile
    title: 황금 서버 (30일)humit 2018.09.30 10:21
    네 좋은 코딩하세요~

List of Articles
번호 분류 제목 글쓴이 날짜 조회 수
78 자료 AdBlock 접근 방지 애드온 v0.1 3 file 네모 2017.10.05 746
77 자료 AdminLTE용 에디터 스타일 4 file title: 은메달도다 2017.07.07 839
76 코드 AWSCLI, in a single file (portable, linux) 1 file Seia 2021.04.10 312
75 코드 c 이진트리 전,중,후위 알고리즘 2 title: 대한민국 국기gimmepoint 2018.04.24 651
74 코드 Cmd 에서 서비스 시작 / 종료하기 1 ProjectSE 2018.02.18 698
73 코드 CMD로 로컬 연결 고정 IP 설정하기 1 title: 황금 서버 (30일)humit 2018.02.06 1094
72 코드 C언어 삼중자를 이용한 코드 title: 황금 서버 (30일)humit 2018.07.22 484
71 자료 even_move - 감성적인 에러 페이지 7 file title: 열려라 맛스타의 자물쇠TVJ 2017.08.08 899
70 자료 Gentelella 3 file NoYeah 2017.06.29 1062
69 자료 Gentelella 레이아웃에 사용가능한 가격 테이블 위젯입니다. 3 file NoYeah 2017.07.03 696
68 코드 Git 저장소에서 자동으로 받아 업데이트하는 쉘 스크립트 5 NoYeah 2017.09.16 787
67 코드 Hello, World!를 출력해보자 18 네모 2018.04.21 662
66 코드 HEX를 RGB로, RGB를 HEX로 바꾸는 PHP 코드 1 네모 2018.05.05 692
65 코드 html 초보가 만든 자소서 4 title: 대한민국 국기gimmepoint 2018.04.21 740
64 코드 JavaScript에서 파이썬 문자열 처리 함수 중 하나 (바인딩)를 구현 7 Seia 2020.01.20 564
63 코드 Koa에서 자동으로 라우팅 채워주기 Seia 2020.01.22 670
62 자료 RBGE - 이쁘고 깔끔한 에러페이지 4 file title: 열려라 맛스타의 자물쇠TVJ 2017.08.08 772
61 자료 [1.8a] Bootstrap 'Panel' 위젯 스타일 1 file title: 은메달도다 2017.08.09 678
60 자료 [Autohotkey] 매분 정각에 전체화면을 캡쳐하는 스크립트 4 file 이니스프리 2020.05.22 1243
59 자료 [Bootstrap] xeACE 레이아웃 3 title: 은메달도다 2017.09.17 727
Board Pagination Prev 1 2 3 4 Next
/ 4