2017년 8월 2일 수요일

IoT 사물인터넷 : BigData - XAMPP, EditPlus


이번에는 간단하게 긁어오기 쉬운 뉴스 사이트의 정보들을 긁어들여와서 저장하는 진행을 한다.

먼저, EditPlus가 아니라 많이들 쓰는 NotePad++를 쓰면 안 되냐는 생각이 들겠지만, NotePad++는 옆에 디렉터리가 바로 안나오니까 그냥 그것때문에 쓰는거다. 아무 편집기나 이용하면된다. 본인이 편한걸로. 참고로 EditPlus는 30일 쉐어웨어다.

XAMPP는 쉽게 서버단을 구축해서 작동시키기 위해 이용한다.
여기서는 Apache와 Mysql을 이용하기 위해 설치한다.

 1. 검색 후에 이런 곳에 들어가면


2. 운영체제에 맞는 프로그램을 설치한다.


3. 설치프로그램을 누르고 따로 바꿀 사항없이 
쭉 진행하면 다음의 화면을 얻게된다.


4. 이런 화면이 뜨면 그냥 기본으로 미국을 선택한다.
(독일어는 알아 들을 수 없는 나니까)


참고로 과정에서 뜨는 방화벽허용은 
각 프로그램을 이용하기 위해 허락을 구하는 거니 허용하도록하자.

5. 프로그램이 실행하는 화면이다.


여기서 Apache랑 MySql을 이용 할 건데,
아래에 뜨는 오류 중 port오류가 발생한다면 , 
Apache는 [apache의 config - httpd-ssl.conf]에서 아래 부분을 다른 포트로 바꿔준다. 
간단하게 442로 바꿔주면 될 것 같다.

그리고 나면 전체 config에 들어가서 포트부분 역시 변경해준다.

자, 이제 설정은 다 끝났다.
html과 php를 이용해서 뉴스에서 정보를 긁어오자!

아래는 ETNews 사이트의 정보를 긁어오는 소스다.
차근차근 뜯어서 살펴보자.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
<!doctype html>
<html lang="en">
 <head>
  <meta charset="UTF-8">
  <meta name="Generator" content="EditPlus®">
  <meta name="Author" content="">
  <meta name="Keywords" content="">
  <meta name="Description" content="">
  <title>Document</title>
 </head>
 <body>
    Crawling Test<br>
    <form action="etnews.php" method="post">
        <input type="text" name="sch_txt">
        <input type="submit" name="search">
    </form>
    <?php

        error_reporting(0);
        include_once('simple_html_dom.php');
        if(is_file('./output_data.txt')==true){
            unlink('./output_data.txt');
        }else{
            echo "no file";
        }
        if(isset($_POST['sch_txt'])){
            $conn = mysqli_connect("localhost""root""""deu") or die("DB connect error");
            mysqli_query($conn'set names utf8');
            $truncate = "truncate article";
            mysqli_query($conn$truncate);
            $sch_txt = $_POST['sch_txt'];
            $sch_title = $_POST['sch_txt'];
            $html = file_get_html("http://search.etnews.com/etnews/search.php?category=CATEGORY1&kwd={$sch_txt}&pageNum=1");
            $reply_cnt = $html->find('h3.list_search_tit>span',0)->plaintext;
            $num = preg_replace("/^0-9]*/s","",$reply_cnt);
            $total_num = substr($num,5,6);
            $file=fopen("./output_data.txt","a+");
            for($j=1$j<=10$j++){
                $html = file_get_html("http://search.etnews.com/etnews/search.php?category=CATEGORY1&kwd={$sch_txt}&pageNum=$j");
                $i = 0;
                foreach($html->find('dd.summury > a'as $element){
                    $i++;
                    $href = $element->href;
                    $url = file_get_html($href);
                    $title = $url->find('h2.article_title',0)->plaintext;
                    $title = trim(strip_tags(html_entity_decode($title, ENT_QUOTES)));
                    $title = str_replace("'"""$title);
                    $title = str_replace("\"","",$title);
                    $contents = $url->find('section.article_body',0)->plaintext;
                    $contents = trim(strip_tags(html_entity_decode($contents, ENT_QUOTES)));
                    $contents = str_replace("'","",$contents);
                    $contents = str_replace("\"","",$contents);
                    
                    $regdate = $url->find('time.date',0)->plaintext;
                    $d = substr($regdate-2);
                    $m = substr($regdate-5-3);
                    $y = substr($regdate-10-6);
                    $rdate = $y."-".$m."-".$d;
                    $query = "insert into article set art_date=\"{rdate}\", article=\"{$contents}\", title=\"{$title}\", url=\"{$href}\" ";
                    $result = mysqli_query($conn$query);
                    fwrite($file$contents);
                    fwrite($file"\r\n ");
                }//foreach
                
            }//for
            echo "총".$total_num."건 기사 중";
            echo $i."건 출력되었습니다.";
            fclose($file);
        }else{
            echo "<p>검색어를 입력해주세요.</p>";
        }//else
    ?>
  
 </body>
</html>
cs




오른쪽의 화면은 전체 구성 화면이고 왼쪽의 화면은 아래의 소스가 구성할 화면이다.

1
2
3
4
5
Crawling Test<br> <!--Crawling Test라는 것을 알리고-->
    <form action="etnews.php" method="post">
        <input type="text" name="sch_txt"><!-- text를 통해 입력받은 정보를 sch_txt라는 변수로 넘기고-->
        <input type="submit" name="search"><!-- 제출이라는 버튼을 누르면 etnews.php라는 파일이 post라는 동작으로 실행되겠다.-->
    </form>
cs

이제 본격적으로 실행 될 php를 작성한다.
1
2
3
4
5
6
7
8
  <?php
        error_reporting(0);//에러 발생시 어떤 에러가 일어나는지 표시
        include_once('simple_html_dom.php');//아래에서 쓰일 형식이 설정되어 있는 파일
//여기선 db저장 뿐만 아니라 파일로도 저장할 것이기 때문에 파일이 존재하는지 확인하고 있으면 unlink
        if(is_file('./output_data.txt')==true){
            unlink('./output_data.txt');
        }else{//정상적인 동작을 할 때 실행
            echo "no file";
        }
cs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
if(isset($_POST['sch_txt'])){ //만약 위에서 검색창에 단어가 존재한다면
//DB연결을 시도. "localhost"라는 주소에 "root"사용자로 pw는 "", 데이터베이스명은 "deu"
            $conn = mysqli_connect("localhost", "root", "", "deu") or die("DB connect error");
//혹시나 하니 utf8설정해주고
            mysqli_query($conn, 'set names utf8');
//article이라는 테이블을 쓰겠다고 설정
            $truncate = "truncate article";
            mysqli_query($conn, $truncate);
            $sch_txt = $_POST['sch_txt'];// $sch_txt변수는 검색창에 쓴 말(default설정)
            $sch_title = $_POST['sch_txt'];// $sch_title변수는 검색창에 쓴 말(default설정)

//여기서 부터의 설명은 아래의 그림을 참고하자.
            $html = file_get_html("http://search.etnews.com/etnews/search.php?category=CATEGORY1&kwd={$sch_txt}&pageNum=1");
            $reply_cnt = $html->find('h3.list_search_tit>span',0)->plaintext;
            $num = preg_replace("/^0-9]*/s","",$reply_cnt);
            $total_num = substr($num,5,6);
            $file=fopen("./output_data.txt","a+");//앞으로의 소스를 파일에 저장하기위해 open!
cs

먼저, 저 html을 어떻게 들고오게 된 것이냐면, 

1. etnews.com에 접속
2. 왼쪽 상단의 검색창에서 단어를 검색


검색 하단의 "뉴스 더보기"를 클릭해서 검색된 전체기사를 본다.
그러면 아래와 같이 번호들이 뜨고 

주소창을 보면,
http://search.etnews.com/etnews/search.php?category=CATEGORY1&kwd=인도&pageNum=1&pageSize=3&reSrchFlag=false&sort=1&startDate=&endDate=&sitegubun=&jisikgubun=&preKwd%5B0%5D=인도
와 같이 뜬다는 것을 알 수 있다.

페이지를 달리 해가면서 보면, 규칙이 존재한다. 
1페이지, 2페이지,... 의 공통분모를 찾는거다.
http://search.etnews.com/etnews/search.php?category=CATEGORY1&kwd=인도&pageNum=2&pageSize=10&reSrchFlag=false&sort=1&startDate=&endDate=&sitegubun=&jisikgubun=&preKwd%5B0%5D=인도

어디가 바뀌고, 어디가 안 바뀌는지를 찾았으면 
주소창에 쳐보면서 불필요한 부분들을 제거한다.

위의 예제에서는 긴주소를 다음과 같이 검색해도 동일한 결과를 얻는다.
http://search.etnews.com/etnews/search.php?category=CATEGORY1&kwd=인도&pageNum=1

규칙을 찾았다면 $html = file_get_html("여기")
"여기"부분에 입력해줄건데, 위의 keyword인 인도를 $sch_txt로 검색 할 부분이기 때문에 주소에서도 수정해준다.

그럼 다음과 같이 된다.
참고로 file_get_html이라는 함수는 위에서 
include_once했던 'simple_html_dom.php'파일에 정의가 되어있다.
아래에서 쓰일 대부분의 parsing은 위의 파일을 이용해서 처리하고 있다.
$html = file_get_html("http://search.etnews.com/etnews/search.php?category=CATEGORY1&kwd={$sch_txt}&pageNum=1");


3. 총 들고 올 기사의 갯수를 알아보자.

저 부분에 마우스를 대고 오른쪽을 클릭하면 
다음과 같이 뜨게 되는데 저 부분의 html을 보여준다.


저 부분을 들고오기 위해 다음과 같이 쓴다.
$reply_cnt = $html->find('h3.list_search_tit>span',0)->plaintext;
그러면 저 span안의 내용(( 18,852건 중11~20건 ))을 전부 들고오게 된다.

그러면 아래의 소스로 18,852라는 수만 남을 수 있게 수정해준다.
(참고로 수가 굉장히 커질때는 사람이 직접 다시 수정해줘야한다.
이 부분을 좀 더 유연하게 고칠 수 있다면 좀 더 나은 프로그램이 되겠지..)
//안에 들어가는 이상한 기호들을 ""으로 대체 $num = preg_replace("/^0-9]*/s","",$reply_cnt);
//그러게 걸러진 문장을 5번째부터 6개정도 자른다. $total_num = substr($num,5,6);

1
2
3
4
5
6
7
8
9
10
11
12
13
for($j=1; $j<=10; $j++){ //10개의 기사를 읽어들여오겠다고 제한.
// 만약 전체 기사를 끌고오고 싶다면? 10대신 $total_num을 넣자!
  $html = file_get_html("http://search.etnews.com/etnews/search.php?category=CATEGORY1&kwd={$sch_txt}&pageNum=$j");
//위의 방법과 같은데 $j, 즉 페이지의 수가 추가되었다.
  $i = 0; // 나중에 총 출력 건수를 표시해주기 위해 존재.

  foreach($html->find('dd.summury > a') as $element){
//이 부분은 많은 페이지들이 존재하는 1페이지에서 각각의 url들을 끌고 오기 위한 방법.
//어떤 부분을 말하는거지? 싶으면 아래를 참조하자.
    $i++;
    $href = $element->href; //대부분 <a href ~>형식으로 되어 있어서 다음과 같이 처리!

    $url = file_get_html($href);
//그 페이지로 이동! 참고로 url주소인 경우에 echo를 해버리면 그 사이트로 이동해버린다.
//echo $url;
    $title = $url->find('h2.article_title',0)->plaintext;
   $title = trim(strip_tags(html_entity_decode($title, ENT_QUOTES)));
//$title 필요한 부분만 잘라내준다.
    $title = str_replace("'", "", $title);
//$title에서 '나 \"부분을 공백으로 대체
    $title = str_replace("\"","",$title);
cs

다음과 같이 선택하면 dd.summary > a부분을 읽어와야한다는 사실을 알 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
//contents는 title과 같은 형식으로 필요한 부분을 들고오도록 설정
$contents = $url->find('section.article_body',0)->plaintext;
$contents = trim(strip_tags(html_entity_decode($contents, ENT_QUOTES)));
$contents = str_replace("'","",$contents);
$contents = str_replace("\"","",$contents);
                    
//날짜부분은 기사 형식에 따라 다르다.
//대부분의 뉴스기사는 그냥 바로 넣으면 되는 형식이지만 다음과 같은 형식으로 바꿔준다.
$regdate = $url->find('time.date',0)->plaintext;
$d = substr($regdate, -2);
$m = substr($regdate, -5, -3);
$y = substr($regdate, -10, -6);
$rdate = $y."-".$m."-".$d;

//db에서 실행시킬 query문을 작성한다. 
$query = "insert into article set art_date=\"{rdate}\", article=\"{$contents}\", title=\"{$title}\", url=\"{$href}\" ";
$result = mysqli_query($conn, $query);

//파일에 기사내용을 저장한다.
fwrite($file, $contents);
fwrite($file, "\r\n ");
}//foreach
                
}//for

//완료되고 나면 화면에 보이는 부분
echo "총".$total_num."건 기사 중";
echo $i."건 출력되었습니다.";
fclose($file);
}else{//아직 검색어가 입력되지 않았을 때 실행되는 부분
   echo "<p>검색어를 입력해주세요.</p>";
}//else
?>
  
cs

다음과 같이 맞는 부분을 걸러서 가져온다.
다음은 날짜를 가져오는 부분이다.


마지막으로 뽑아야 되는 부분을 정리를 하자면,





2017년 7월 12일 수요일

IoT 사물인터넷 : PaaS 01(클라우드 기반 개발인프라)

PaaS (클라우드 기반 개발인프라)
: 가상으로 저장공간을 생성해놓고 저장공간을 활용하는 방법.
개발시 네트워크 연결 인프라부터 어프릴케이션 실행을 위한 런타임까지 제공되며,
사용자는 어플리케이션과 데이터만 관리합니다.

대표 PaaS 서비스 종류

서비스






IBM Bluemix
Azure(MS)
Amazon
WebService의
(AWS Beanstalk)
Google
Cloud Platform의
(Google App Engine)
설명
개발회사에
충실히
제공해주는
플랫폼
 
대학생들 교육용으로 출발
기업들에게 마케팅
클라우드 장비대여로 시작
기업위주의 서비스 제공
 
장비부터
시작하다보니
기반이
튼실하지만
비용이 높음
 
현재 클라우드 시장 1등 기업
 
구글 자체의 언어를 사용함에도 불구하고
이미지 효과를
잘 활용하여
국내의 회사들이 다수 사용 중.
사후처리도 양호.

+
서비스
 
 
 
CloudFoundry
OpenShift
Docker
설명
VMWare사에서 처음 시작한 프로젝트로 제품자체는 오픈소스지만 컨트롤하기 어려워서 Pivotal PCF/PWS에서 기능을 추가해서 유료로 판매.
레드햇에서 만든 것으로 무료로 제공.
VMWare의 단점을 보완하기 위해 
만들어진 것으로 하나의 os를 공유해서 쓴다.
, 리눅스만 지원함.
(리눅스의 같은 파일시스템의 환경을 들고 와서 쓸 수 있다는 말.)


(부가적인 설명 : http://www.insunginfo.co.kr/upfiles/PdsBoard/PdsFile/OpenCloud%EC%9D%B4%ED%95%B4(3).pdf, p.8)

PaaS란?
왼쪽부터 기존의 프로그램- IaaS-PaaS-SaaS순으로 나열되어 있고
그림에서 보는것과 같이 노란색으로 칠해진 부분이 개발자가 직접 설치/설정해야 하는 부분이다.

Standard는 처음부터 모두 설치하고 설정해주어야 한다.
IaaS는 VMware같은 존재로 위의 그림에서는 os가 빠져있지만 os까지 포함되어 지원되는 경우도 존재한다. 서비스마다 다르게 지원하기 때문이다.
PaaS는 어플리케이션 부분을 개발하는 부분이다. os는 당연히 신경쓰지 않아도 되는 공간이다.
SaaS는 왜 개발자가 실행하는 부분이 없는걸까? 바로 사용자의 공간이기 때문이다. 예시로는 이미 개발되어 사용자에게 제공되는 네이버, 다음의 이메일 서비스 같은 존재이다.

다음은 환경비교를 캠핑하는 경우로 비유를 한 모습이다.

Standard
IaaS
PaaS
SaaS
 

 무인도

 캠핑
 글램핑
호텔 

PaaS의 활용사례?
국내 : 레진코믹스, 사운드 그래프 -> 구글클라우드 기반의 PaaS를 사용한 사례
국외 : 위의 4대 업체 + 정부 공공기관(미국, 일본, 영국에선 정부중심의 클라우드서비스가 구축되어 제공되고 소비되고 있음) + (독일은 산업현장을 중심으로 빠른 전환이 일어나고 있음.)
∴ 우리나라는 정부차원에서 다음과 같은 PaaS-TA(파스타)가 구성되어 앞으로의 빅데이터 시대가 열릴 것으로 전망 됨

왜 PaaS를 쓰는 걸까?
위 그림과 같이 개발비용이 감소한다는 것을 알 수 있음

PaaS의 향후 전망

공공분야, 대기업
금융
산업현장
의료
서버 전산실을 유지하는데 잡아먹는 비용을 축소하기 위해 PaaS활용
금융회사 역시 서버 전산실을 유지하는데 잡아먹는 비용을 축소하기 위해 PaaS활용
스마트 팩토리 구축으로 인해 많은 데이터를 처리하는데 많은 비용이 들면서 PaaS활용
병원 역시 병원 내부의 서버가 존재하고 유지비용을 줄이기 위해 활용가능하고 환자들의 원격진료를 하기 위한 처리를 수월하도록 도와줌
PaaS환경을 이용한 IoT 어플리케이션 시연

본래는 측정장비에서 서버로 올라간 정보를 확인했다면, 서버로 올라간 정보를 클라우드로 올려서 동시에 여러명이 접근하여 확인할 수 있도록 만든 서비스


PaaS 기반 어플리케이션 개발 흐름
1. 사이트마다 다르지만 계정 생성을 통해 계정을 생성한다
(현재 글에서는 startiot.or.kr을 이용하도록 한다.)
2. 프로그램을 개발한다.
(언어는 많이 쓰는 언어들을 지원하는데 현재 일반적으로 사용하는 언어는 대부분 지원한다고 볼 수 있다. C, JAVA, Python 등등)
3. 배포과정을 통해 클라우드로 올려 사이트 주소로 외부에서도 접근가능해진다.