Search

레이블이 IT인 게시물을 표시합니다. 모든 게시물 표시
레이블이 IT인 게시물을 표시합니다. 모든 게시물 표시

2019년 4월 17일 수요일

[Python] library(or package) install

#1. 들어가기

파이썬을 사용하다보면 추가적으로 필요한 라이브러리(혹은 패키지)를 사용해야 할 때가 있다.
Windows를 기준으로 cmd나 사용중인 IDE의 terminal 창을 이용해 명령어로 간단하게 동작시킬 수 있다.


#2. 명령어

python -m pip install {lib_name}

여기에서 {lib_name} 대신 본인이 설치하길 원하는 라이브러리명을 넣으면 된다.


[Python] Python 설치하기 - Anaconda 사용

#1. 들어가기

최근들어 많은 사람들이 프로그래밍 언어로 Python을 사용하는데, 설치 및 간략한 환경 설정하는 법을 작성해본다. (Python의 3.x 버전을 기준으로 작성하였으며, 현 시점 최신버전인 3.7버전으로 진행)

먼저, python을 설치하는데, 왜 자꾸 anaconda 이야기가 나오지? 라는 분들도 간혹 있으실텐데, 복잡한건 다 빼고 간단하게 설명하자면.. 영어로 python은 작은 비단뱀이고 anaconda는 거대한 뱀이다. (거대한 뱀이 작은 뱀을 삼키는 이미지를 머릿속에 그려본다면..) 기본적인 프로그래밍 언어로서 python에다가 이것저것 편리한 기능 및 패키지들을 기본 옵션으로 장착한 녀석이 바로 anaconda라고 생각하면 수월하다.


#2. 다운로드 및 설치

아나콘다의 다운로드 사이트(https://www.anaconda.com/distribution/#download-section)로 들어가보면, 각자의 OS와 bit에 맞춰서 다운로드를 받을 수 있다. (여기에서는 Windows 64bit를 기준으로 작성)


다운로드 받은 파일을 실행하여 next를 눌러가며 설치하되,
'Advanced options' 라는 창이 뜨며 체크박스 항목이 중간에 한번 뜨게된다.
이 때, 직접 환경변수를 편집해서 추가할 생각이 아니라면 모두 체크하고 설치하면 보다 간편하게 설치를 진행할 수 있다.

* 혹이라도 체크를 못하고 넘어갔어도, 환경 변수->시스템 변수 -> Path에서

C:\ProgramData\Anaconda3;C:\ProgramData\Anaconda3\Library\mingw-w64\bin;C:\ProgramData\Anaconda3\Library\usr\bin;C:\ProgramData\Anaconda3\Library\bin;C:\ProgramData\Anaconda3\Scripts;

위와 같이 직접 경로를 추가할 수 있으니 걱정은 안해도 된다.
Path 자체를 추가할줄 모른다면, OS마다 그리고 설치 경로마다 조금씩 상이하니, 검색을 추천한다... (아니면 지우고 다시 설치..?)


#3. 실행 테스트

시작->실행->cmd 창을 열어서 아래와 같이 명령어를 바로 입력하고 엔터를 쳐보자.

python --version

그러면 하단에 'Python 3.7.0' 라고 현재 PC에 설치된 python 버전을 가르쳐주면 정상적으로 설치가 된 것을 나타낸다.



2019년 1월 31일 목요일

[Linux] [CentOS] 반복 및 예약 작업 설정하기 (crontab)

#1. 들어가기

매월 혹은 매일 단위로 배치 작업을 수행해야 하거나, 특정 날짜의 특정 시간에 이벤트성으로 작업을 걸어줘야 하는 경우가 있다.
이럴 경우엔 사람이 직접 수작업으로 수행할 수 없으니 crontab을 활용해 자동화 시키는 방법을 알아보자.


#2. crontab 사용

crontab을 사용하기 위해서는 crond가 동작되고 있어야 한다.
아래의 명령어를 통해 cornd가 돌아가고 있는지 확인/시작/중지 시킬 수 있다.
bash ~]$ ps -ef | grep crond                 # crond 확인
bash ~]$ /etc/rc.d/init.d/crond start        # crond 시작
bash ~]$ /etc/rc.d/init.d/crond stop         # crond 중지

crond가 정상적으로 확인된다면, crontab을 통해 현재 예정된 작업들을 확인/수정 할 수 있다.
bash ~]$ crontab -l                          # 예정된 작업리스트 확인
bash ~]$ crontab -e                          # 작업리스트 수정(추가/수정/삭제)


#3. crontab 작업리스트 추가 옵션

작업리스트는 총 6개의 항목을 작성하여 등록할 수 있는데, 아래와 같이 순서에 맞게 6개의 항목을 작성해주면 된다. (구분은 스페이스바 공백으로 하면 되고, 전체의 의미는 *이다.)

기본구문:     (1)   (2)   (3)   (4)   (5)요일   (6)실행명령구문

ex> 15  2  *  *  *  ~/run_batch.sh                                설명: 매월 매일 새벽 2시 15분에 home의 run_batch.sh 파일을 실행시킨다.
ex> 15  2  *  *  0  ~/run_batch.sh > ~/batch_log.txt    설명: 매주 일요일 새벽 2시 15분에 명령을 수행하고, batch_log.txt에 로그를 기록한다.


아래와 같이 조금 더 세부적인 컨트롤도 가능하다.

- 콤마(,): 여러 특정 범위를 지정할 수 있다.
- 하이픈(-): 여러 연속된 범위를 지정할 수 있다.
- 슬래쉬(/): 범위에 대한 간격을 지정할 수 있다.

ex> 0,15,30,45  2  *  *  *  ~/run_batch.sh                       설명: 매월 매일 새벽 2시 00, 15, 30, 45분에 명령 수행.
ex> */15  2  *  *  *  ~/run_batch.sh                                설명: 매월 매일 새벽 2시 00, 15, 30, 45분에 명령 수행.
ex> 0  1-5  *  *  *  ~/run_batch.sh                                  설명: 매월 매일 새벽 1~5시 정각에 명령 수행.



기타 더 세부적인 옵션은 아래의 참조 사이트들을 참고해보자.
참조1: https://www.adminschoice.com/crontab-quick-reference
참조2: http://egloos.zum.com/program/v/802690

2018년 12월 23일 일요일

[Database] [Oracle] sequence에 상관없이 string 값 비교하기 (TRANSLATE)

#1. 들어가기

특히, 코드값 등을 비교하는 쿼리를 작성할 때, 아래와 같이 특정 시퀀스에 관계없이 일치 여부를 판별해야 하는 경우가 종종 있다.
아래의 예는 TMP_TABLE에서 A_COL과 B_COL을 비교해 EQUAL 컬럼을 생성한 예제이다.



즉, 모든 유니크한 원소의 개수는 일치하면서 순서만 다른 경우를 판별하는 케이스인데, CONNECT BY LEVEL 등을 활용한 구문보다 TRANSLATE의 알고리즘을 활용하면 보다 간결하고 빠르게 동작하는 쿼리를 작성할 수 있다.


#2. 쿼리

아래와 같이 TRANSLATE 구문을 사용해 문제를 해결할 수 있다.

--string값의 순서에 상관없이 비교하기
SELECT      A_COL
           ,B_COL
           ,CASE WHEN TRANSLATE(A_COL, B_COL,' ') = TRANSLATE(B_COL, A_COL,' ')
                 THEN 'TRUE'
            ELSE      'FALSE'  END  AS  EQUAL
FROM        TMP_TABLE
;




[Database] [Oracle] 테이블 및 컬럼 검색하기

#1. 들어가기

데이터베이스 내에서 사용하는 스키마나 테이블이 많을 경우, 한 번에 어떤 컬럼 혹은 테이블이 어느 위치에 있는지 잘 모를 때가 많다. 혹은, 한글로된 코맨트 정보를 이용해 역추적 하는 경우도 많다.


#2. 쿼리

아래의 코드를 이용해 WHERE구문을 변경해가며 테이블이나 컬럼 위치를 찾으면 보다 유용하다.
- 테이블명 검색 : (영문or물리)A1.TABLE_NAME, (국문or논리)A1.COMMENTS
- 컬럼명 검색 : (영문or물리)A3._COLUMN_NAME, (국문or논리)A3.COMMENTS


--테이블 및 컬럼명 검색
SELECT      A1.OWNER                                                /*OWNER*/
           ,A1.TABLE_NAME                           AS  TAB_ID      /*테이블영문명*/
           ,A2.COMMENTS                             AS  TAB_NM      /*테이블한글명*/
           ,A3.COLUMN_ID                            AS  COL_SEQ     /*컬럼순서*/
           ,A1.COLUMN_NAME                          AS  COL_ID      /*컬럼영문명*/
           ,A1.COMMENTS                             AS  COL_NM      /*컬럼한글명*/
           ,A3.NULLABLE                             AS  NULL_YN     /*NULL여부*/  
           ,A3.DATA_TYPE||'('||A3.DATA_LENGTH||')'  AS DATA_TYPE    /*데이터타입*/
FROM        SYS.ALL_COL_COMMENTS  A1
INNER JOIN  SYS.ALL_TAB_COMMENTS  A2
        ON  A1.OWNER       = A2.OWNER
       AND  A1.TABLE_NAME  = A2.TABLE_NAME
INNER JOIN  SYS.ALL_TAB_COLS  A3
        ON  A1.OWNER       = A3.OWNER
       AND  A1.TABLE_NAME  = A3.TABLE_NAME
       AND  A1.COLUMN_NAME = A3.COLUMN_NAME
WHERE       A1.TABLE_NAME  = 'MY_TABLE_NAME'
ORDER BY    A1.OWNER
           ,A1.TABLE_NAME
           ,A3.COLUMN_ID
;

[R] console창의 print 길이 조절하기

#1. 들어가기

print를 통해 한 번에 많은 양의 데이터를 출력하면 아래와 같이

reached getOption("max.print") -- omitted 999 rows

라고 뜨면서 최대 인쇄 길이를 조정하라고 한다.
이 때, 더 많은 양을 출력하기 위해서는 아래와 같이 설정한다.


#2. 코드

# console 프린트 길이
options(max.print=1000000)

[R] 출력되는 소수점 자리수 설정하기

#1. 들어가기

분석 시, 소수점 자리가 너무 길거나 짧게되면 데이터를 확인하는데 불편함이 있을 수 있다.
아래의 코드로 모든 소수에 대해 출력되는 자리 수를 한번에 설정할 수 있다.
(scipen 뒤의 숫자를 변경하면 된다.)


#2. 코드

# 소수자릿수 표현
options(scipen = 4)

[R] string 값을 factor로 자동변경 하지 않기

#1. 들어가기

R에서 분석을 하다보면 file을 통해 데이터를 불러오는 경우가 많다.
이 때, 데이터에 string값이 있을 경우 자동으로 factor로 만들어주기 때문에 read속도가 느리기도 하고, 때에 따라서는 factor를 다시 character로 변경해야하는 불편함이 있다.
그래서 아래의 코드로 아예 처음부터 factor방식으로 변경하지 않게 만들 수도 있다.


#2. 코드

# string을 factor로 자동 변경하지 않음
options(stringsAsFactors = FALSE)

[R] 내부망의 CARN mirror사이트 설정

#1. 들어가기

많은 기업들은 분석을 위해 내,외부망이 분리된 환경에서 분석을 수행한다.
그 경우, 내부망의 크랜 미러사이트를 검색할 수 있게 만들어줘야 한다.


#2. 코드

# 내부 mirror사이트 path
options(repos="http://192.168.0.1/cran")

2018년 11월 28일 수요일

[R] [function] R에서 한글 csv 파일 읽기 - euc-kr, utf-8, encoding 처리 (readr)

#1. 들어가기

R에서 csv파일을 열 때, 한글이 섞인 문서를 열다 보면 알 수 없는 외계어와 함께 파일을 제대로 불러올 수 없는 현상이 있다.
프로그래밍을 처음 접한 사람들에게는 생각보다 당혹스러운 현상인데, 나중에 encoding을 알게되면 자연스럽게 해결되는 문제이다.(라고 쓰고, 한글을 쓰게되면 평생 따라다니는 귀찮은 문제이다. 라고 읽습니다...)


#2. 해결하기

보통의 경우에는 한글이 포함된 csv파일이더라도 utf-8형태로 저장됐다면, R에서 읽는데 문제가 없다. 하지만, excel등에서 읽을 때는 외계어를 만날 수 있다... 반대로, euc-kr로 저장됐다면 excel에서 읽는데 문제가 없지만, R에서는 읽히지 않을 수 있다.
그래서 어떠한 인코딩 형태이던지 우리가 읽을 수 있게끔 read.csv() 펑션을 만들고 싶은데, 때마침 해당 내용을 잘 정리한 블로그를 발견하여 참조를 달고 함수를 그대로 가져와봤다.
참조 : http://philogrammer.com/2017-03-15/encoding/

#2-1. 함수 생성

install.package("readr")
library(readr)
read.csv.any <- function(text, sep = "", ...) {
  encoding <- as.character(guess_encoding(text)[1,1])
  setting <- as.character(tools::file_ext(text))
  if(sep != "" | !(setting  %in% c("csv", "txt")) ) setting <- "custom"
  separate <- list(csv = ",", txt = "\n", custom = sep)
  result <- read.table(text, sep = separate[[setting]], fileEncoding = encoding, ...)
  return(result)
}


#2-2. 함수 사용

my_csv_file <- read.csv.any("file/path/csv_file.csv", header = TRUE)


2018년 3월 11일 일요일

[Database] [Oracle] PIVOT과 UNPIVOT 함수 사용하여 데이터 형태 변환하기

#1. 들어가기
우리는 종종 GROUP BY를 통해 데이터를 집계하곤 한다.
보통 여러 컬럼에 구분된 값을 집계할 때 CASE문을 사용하는데, PIVOT 함수를 활용하는 방법을 알아보자.
또한, 잘 알려져있지는 않지만 UNPIVOT 함수를 이용해 그 역의 형태로 되돌리는 방법도 알아보자.


#2. PIVOT

 -> 

좌측(12rows) 형태에서 우측(4rows) 형태로 변환하려면, 아래와 같은 쿼리를 이용한다.
SELECT * FROM TMP
PIVOT (
    SUM(CNT) FOR MON IN (
        'M01' AS MON01
       ,'M02' AS MON02
       ,'M03' AS MON03
    )
)
ORDER BY ID
;


#3. UNPIVOT

  -> 

앞선 예제와는 반대로, 좌측(4rows) 형태에서 우측(12rows) 형태로 변환하려면, 아래와 같은 쿼리를 이용한다.
SELECT * FROM TMP
UNPIVOT (
    CNT FOR MON IN (
        MON01 AS 'M01'
       ,MON02 AS 'M02'
       ,MON03 AS 'M03'
    )
)
ORDER BY ID, MON
;


2018년 3월 8일 목요일

[Analysis] [R] (offline R 분석 시) CRAN Repository에 있는 모든 패키지 설치하기

일을 하다 보면 인터넷 연결이 되어 있지 않은 환경에서 R 분석 작업을 진행해야 하는 경우가 있다.
다른 환경도 인터넷 연결 없이 진행하기 힘들겠지만, R은 특히 패키지 의존성이 강하기 때문에 offline으로 작업할 경우 매번 필요한 패키지를 설치하기 어려워 분석을 지속적으로 진행하기 어려운 경우가 생긴다.
보통 필수적으로 필요로 하는 패키지 위주로 개별적으로 다운을 받아서 옮기는 작업을 하는데, 이러다 보면 일부 dependency 패키지가 설치되어 있지 않아서 다시 다운받고 옮기는 작업을 반복하게 된다.
중간중간 패키지를 매번 새로 받아 옮기는 것보다 CRAN Repository에 있는 모든 패키지를 미리 다운받아서 설치하는 것이 편리한데, 이번 블로그에 그 내용을 담아보고자 한다.


1. CRAN Repository download

wget ftp://cran.r-project.org/pub/R/src/contrib/*.tar.gz

* 유효한 ftp 주소인지 확인해 보려면 .. (thanks to @김진혁)

ftp ftp://cran.r-project.org/pub/R/src/contrib/


2. Install on R

2-1. 압축 풀기

tar -xzvf /다운로드된경로 -C /압축풀경로


2-2. 압축푼경로로 R에서 라이브러리 경로지정

[Anaysis] [R] 현재 라이브러리 경로 확인 및 패키지 설치



2-3. 특정 패키지 설치여부 확인
(정말 필수적으로 필요한 패키지에 대해 샘플링하여 설치여부 확인)

pk.list <- c("RJDBC", "data.table", "dplyr", "tidyr", "Amelia" , "lubridate", "xlsx",
             "sparklyr", "rsparkling", "h2o", "visNetwork", "igraph", "ggplot2")
pk.installed <- installed.packages()[, "Package"]
setdiff(pk.list, pk.installed)
character(0)  # 모든 필수 라이브러리 설치 완료


* 대부분의 경우 이런 방식으로 리눅스 서버에서 설치 가능하지만 만약 설치가 안되는 경우가 있다면 다음 방법 참조

download.path <- "압축푼경로"
pk.list <- list.files(download.path)
pk.list <- setdiff(pk.list, installed.packages()[, "Package"])
for(i in pk.list){
  pk.path <- file.path(download.path, i)
  install.packages(pk.path, repos = NULL, type="source")
}

다만, 이 방법은 dependency 에 따라서 설치가 안되는 패키지가 있을 수 있으니, 여러번 반복수행하여야 한다.



2018년 3월 4일 일요일

[Analysis] [R] Text Analysis 맛보기(2) - Word Counter 만들고, 트랜드 살펴보기

#1. 들어가기
지난 시간에는 Google에서 단순하게 뉴스를 수집해주는 프로그램을 만들었다.
이번에는 그 후속편으로, 모아놓은 뉴스들을 활용해 그 안에서 의미를 파악하는 방법을 다루어보고자 한다.


#2. 워드 카운터 만들어보기
이번 화에서 사용할 데이터는 전 시간('Google News Crawler 만들기'편 참조)의 최종 결과물인 'result'라는 변수에 저장된 data.frame으로, 그 중 기사내용(article) 컬럼에 있는 단어들을 추출해 작업해보고자 한다. 아래는 그 코드이다.

#########################################
# WORD COUNTER - v1.0
# - martinpark
# - ruserive@gmail.com
#########################################

# load library and user function ------------------------------------------
# install.packages(c("KoNLP","plyr","dplyr","qdap","plotly"))
library(KoNLP)
library(plyr)
library(dplyr)
library(qdap)
library(plotly)


# word count part ---------------------------------------------------------
# 기사 내용 추출해서 단어 카운트하기 (전체 기사)
txt        <- result$article
txt        <- gsub(keyWord," ",gsub("“|”|\"|`|'|\\(|\\)|<|>|\\[|\\]|·|…|△|▷| \\(중략\\)..."," ",txt))
txt        <- unlist(sapply(txt, extractNoun, USE.NAMES = F))
txt        <- base::Filter(function(x){nchar(x)>1},txt)
word_count <- freq_terms(txt,top=10)

# 완성 데이터 확인
print(word_count)

먼저, '쇼트트랙'이라는 단어로 검색한 뉴스의 기사내용들을 모아 단어만 추출하고, 다시 그 단어들 중에 사용된 순서가 높은 순서대로 10개만 모아보면 아래와 같다.



결과에서 m이 1위에 뽑힌 이유는, 간단하게 이용해보려고 사용한 KoNLP 라이브러리의 단어사전에 숫자들이 제외되었기 때문이다. 예를 들어, 500m, 1000m, 3000m 등등의 텍스트에서 숫자는 다 없어지고 m만 남았다.


#3. 시간의 흐름에 따른 단어 사용량 파악해보기
간단하게 위 방법을 사용해 단어와 그 사용 빈도만 파악해 보아도 최근 뉴스에서 어떤 내용을 다루는지 충분히 짐작할 수 있을 것이다. 하지만, 단순하게 단어에 대한 사용량만 놓고 본다면 무엇인가 새로운 인사이트를 찾고자 노력할 때, 정보가 너무 뭉개졌다는 느낌을 받을 것이다.

그래서, 아래의 코드를 추가해 분석을 조금 더 진행해봤다. 이번에는 3위에 랭크된 '금메달'이라는 단어를 뽑아, 시간의 흐름에 따른 카운트를 다시 파악해봤다.

# time trend --------------------------------------------------------------
# 기사 내용 추출해서 시간별로 단어의 사용량 추이 확인하기
df           <- result[,c("article","time")]
df$article   <- gsub(keyWord," ",gsub("“|”|\"|`|'|\\(|\\)|<|>|\\[|\\]|·|…|△|▷| \\(중략\\)..."," ",df$article))

# 날짜별
txt2         <- sapply(df$article, extractNoun, USE.NAMES = F)
txt2         <- lapply(txt2, function(x) x[nchar(x)>1])
names(txt2)  <- df$time
txt2_result  <- data.frame(date = rep(names(txt2), lapply(txt2, length))
                           ,word = unlist(txt2)
                           ,row.names = NULL
                           ,stringsAsFactors = FALSE)

# 빈도 높은 단어(혹은 관심 단어) 하나 선택하기
word_filter  <- "금메달"

## word plot(1) - 0불포함(쇼트트랙 관련 기사에 금메달이라는 단어가 없던 날은 아예 그래프에서 제외)
tmpPlot      <- txt2_result[txt2_result$word == word_filter,]$date

# 결과 그래프(1) 확인
plot(table(tmpPlot),"l")


## word plot(2) - 0포함(쇼트트랙 관련 기사에 금메달이라는 단어가 없던 날도 그래프에 포함)
tmpPlot2      <- left_join(data.frame(tmpPlot=unique(txt2_result$date),stringsAsFactors=FALSE)
                           ,as.data.frame(table(tmpPlot),stringsAsFactors=FALSE))
tmpPlot2$Freq[is.na(tmpPlot2$Freq)] <- 0
tmpPlot2      <- tmpPlot2[order(tmpPlot2$tmp),]
tmpPlot2$Date <- gsub("-","/",substr(tmpPlot2$tmpPlot,6,10))

# 결과 그래프(2) 확인
plot_ly(tmpPlot2, x = ~Date, y = ~Freq, type = 'scatter', mode = 'lines')

위 코드를 그대로 붙여넣어 수행하면 얻어지는 그래프를 1번, 2번 순서대로 캡쳐해 보았다.
(간단하게 보여주기 위함이니.. 선이나 글씨 크기, 배치 등등은 스스로 설정하자.)




이렇게 그래프를 그리고 나면, 우리는 여기에서 새로운 정보를 얻을 수 있게 되었다.
나는 분명 신문 기사를 읽지도 않았고 쇼트트랙도 잘 모르지만, 쇼트트랙 기사 중 금메달이라는 카운트가 2/10, 2/17/ 2/20, 2/22에 높다는 사실을 알 수 있다. (캡쳐해놓은 이미지가 인터넷 상에선 잘 안보이지만.. 코드를 돌려보면 나옵니다..)
그래서, 해당 날짜들에 어떤 사건이 있는지 역추적 해보니 아래와 같다는 것을 알 수 있다.

2/10 - 임효준 남자 1,500m 금메달
2/17 - 최민정 여자 1,500m 금메달
2/20 - 대한민국 여자 3,000m 계주 금메달
2/22 - 금메달은 못 땄으나, 남자 500m 은,동메달, 여자 1,000m 4위와 실격처리, 남자 5,000m 계주 4위 등 아쉬운 장면들이 많이 연출되던 날.


#4. 마치며
우선은 일반 사람들에게 생소한 TA(Text Analysis) 맛보기를 해보았는데, 실제로 해보면 생각만큼 TA영역이 쉽지 않은 것임을 알 수 있을 것이다. 단어 정제도 그렇고, 의미 파악도 그렇고.. 하지만 이 분야에 재미를 느끼는 독자분들이 있다면, 한 번 씩 도전해 보고 언젠간 멋진 결과를 다시 공유해줄 수 있었으면 합니다.


2018년 2월 18일 일요일

[Analysis] [R] Text Analysis 맛보기(1) - Google News Crawler 만들기

#1. 들어가기
가끔 세상이 어떻게 돌아가는지 알아보기 위해 구글링을 할 때가 종종 있다.
그런데, 수백 수천건의 뉴스기사를 시간순으로 정렬해 일일히 눈으로 확인하는 것은 몹시 피곤한 일이다. 그래서 이번에는 필자 대신 뉴스기사를 긁어 모아서, 얼마나 많은 단어들이 사용되었는지 확인할 수 있는 아주 간단한(?) 텍스트 분석 도우미를 만들어보고자 한다.

본 시리즈는 총 2편으로 구성할 계획이며,
1편에서는 Google News Crawler를 R로 만들어 뉴스기사를 스크랩할 예정이고,
2편에서는 KoNLP 패키지를 사용해 간단하게 word count를 구현해보고자 한다.
(추가적으로, 시간이 된다면 파이썬 버전도 만들어볼 계획)

#2. 구글 뉴스 크롤러 만들어보기
구글 뉴스 크롤러를 만들기 위해 사용되는 패키지는 총 4개로, 개발자마다 다르게 사용할 수도 있다. 또한, 다른 코드가 더 맘에 든다면 얼마든지 변경할 수 있으며, 독자분들 중에 더 효율적인 라이브러리나 코드를 찾았다면 댓글 부탁드립니다.
사용할 라이브러리는 httr, xml2, stringr, lubridate인데, 가급적 인스톨 패키지를 통해 최신으로 업데이트 하는 것을 추천한다. (특히 lubridate의 경우, 하위 버전에서 동작하지 않는 타입을 확인했음)

작성한 코드는 아래와 같으며, keyWord와 numOfPost를 변경하여 가볍게 사용해볼 수 있게 만들어두었다. 또한, 맨 하단에 csv로 내려받는 코드를 넣어두었는데, 저장 위치를 변경해서 쉽게 다운로드할 수 있다.

#########################################
# GOOGLE NEWS CRAWLER - v1.0
# - martinpark
# - ruserive@gmail.com
#########################################

# load library and user function ------------------------------------------
# install.packages(c("httr","xml2","stringr","lubridate"))
library(httr)
library(xml2)
library(stringr)
library(lubridate)
unescape_html <- function(str){
  xml2::xml_text(xml2::read_html(paste0("<x>", str, "</x>")))
}

# control keyword and number of posts -------------------------------------
# 검색어
keyWord     <- "쇼트트랙"

# 검색 뉴스 수 (너무 많을 경우, 블락당할 수 있음)
numOfPost   <- 300

# google news crawler main part -------------------------------------------
# 키워드 변환
keyWordUTF8 <- URLencode(iconv(keyWord,to='utf8'))

# 크롤링 페이지 분할
startPosts    <- seq(1,numOfPost,100)
startPosts[1] <- startPosts[1] - 1
if (numOfPost%%100==0) {
  endPosts      <- rep(100,numOfPost/100)
} else {
  endPosts      <- c(rep(100,floor(numOfPost/100)),numOfPost%%100)
}

# 결과셋 생성
result      <- data.frame(stringsAsFactors=FALSE)

for (i in seq(length(startPosts))) {
  # 뉴스 가져오기
  url         <- paste0("https://www.google.co.kr/search?hl=ko&q=",keyWordUTF8,"&tbm=nws&start=",startPosts[i],"&num=",endPosts[i])
  doc         <- content(GET(url), "text")
  # doc         <- readLines(url,warn=FALSE)
  doc_table   <- str_split(doc,"<table><tr>")
  
  for(p in seq(endPosts[i])+1) {
    # 뉴스 정제
    doc_tab     <- str_split(doc_table[[1]][p],"</div>")
    doc_tab2    <- str_split(doc_tab[[1]][1],"</a></h3>")
    
    # 뉴스 제목
    title       <- unescape_html(doc_tab2[[1]][1])
    
    # 뉴스 기사
    article     <- unescape_html(gsub("&nbsp;..."," (중략)...",doc_tab[[1]][2]))
    
    # 뉴스 제공업체
    supplier    <- str_split(unescape_html(doc_tab2[[1]][2])," - ")[[1]][1]
    
    # 뉴스 URL
    news_url    <- URLdecode(str_sub(doc_tab2[[1]][1]
                                     ,str_locate(doc_tab2[[1]][1],"\"/url")[2]+4
                                     ,str_locate(doc_tab2[[1]][1],"&")[1]-1))
    
    # 뉴스 게시 시간
    tmp_time    <- str_split(unescape_html(doc_tab2[[1]][2])," - ")[[1]][2]
    if(length(grep(" 전",tmp_time))==0){
      post_time <- as_date(tmp_time)
    } else {
      post_time <- lubridate::ymd_hms(Sys.time())
      num       <- as.integer(gsub("[^0-9]","",tmp_time))
      unit      <- gsub("([0-9]*)| 전","",tmp_time)
      if(unit=="일"){
        lubridate::day(post_time) <- lubridate::day(post_time) - num
      } else if(unit=="시간"){
        lubridate::hour(post_time) <- lubridate::hour(post_time) - num
      } else if(unit=="분"){
        lubridate::minute(post_time) <- lubridate::minute(post_time) - num
      } else if(unit=="초"){
        lubridate::second(post_time) <- lubridate::second(post_time) - num
      }
      post_time <- as_date(post_time)
    }
    
    # 데이터프레임화
    res         <- data.frame(keyword=keyWord
                              ,title=title
                              ,article=article
                              ,supplier=supplier
                              ,url=news_url
                              ,time=post_time
                              ,stringsAsFactors=FALSE)
    
    result      <- rbind(result, res)
  }
  print(paste0("Done..! (",nrow(result),"/",numOfPost,")"))

  # 빠르게 자주 사용하면 블락당함..
  Sys.sleep(3)
}

# 완성 데이터 확인
# View(result)

# csv 추출
write.csv(result, file.path("C:\\Users\\Martin\\Desktop\\google_news.csv"),row.names=FALSE,fileEncoding="CP949")

#3. 크롤링 결과 확인
더 필요한 정보가 있다면 구조를 변경하여 추가해도 되지만, 우선은 간단하게 이 정도만 크롤링 해보는 것으로 이번 장을 마칩니다.



2017년 6월 20일 화요일

[Project 01] 4. Raspberry Pi 클러스터 꾸미기

#1. 들어가기

전 단계에서 완성한 Raspberry Pi 클러스터를 구동하려고 봤더니, 바닥을 너무 어지럽히는것 같다. 좋은 수가 없을까? 먼저, 개별적으로 굴러다니는 Raspberry Pi는 클러스터 케이스를 이용해 하나로 합치고, 복잡한 LAN선은 Wi-fi 연결을 통해 해결할 수 있을 것 같다.


#2. 클러스터 케이스



국내 온라인 쇼핑몰에서는 Raspberry Pi 클러스터용 케이스를 찾기 힘들어, 해외 직구를 통해 주문을 넣어 한 달동안 기다렸다. (구매 사이트와 상품의 정보가 필요하다면 댓글이나 메일을 통해 물어보세요.)




먼저, 위처럼 아크릴판에 붙은 보호용지를 떼어낸다.


 

아크릴판과 Raspberry Pi 사이가 흔들리지 않도록 작은 베어링(?)을 넣고, 볼트와 너트를 이용해 조여준다.




기다란 봉을 이용해 각 아크릴판을 연결해준다. 맨 아래의 경우, 작은 봉을 이용한다.




지저분하게 제각각 있던 클러스터보다 훨씬 더 미적으로 아름다워졌다.


#3. Wi-fi 연결

LAN선이 보기 싫어서 Wi-fi를 연결하고자 마음먹었다면, 우선 본인의 공유기를 체크해보길 바란다. 전 장에서 잠깐 다루었듯이, 각 제조사와 모델에 따라서 Raspberry Pi 3에 연결이 불가능한 모델도 더러 존재한다.

우선은 LAN선을 연결한 상태에서 각 노드의 Wi-fi 모듈을 아래의 명령어 두 줄을 통해 업데이트 해준다. 작업이 완료되면 재부팅을 해주자.

# wi-fi 모듈 업데이트
curl --location https://github.com/RPi-Distro/firmware-nonfree/raw/master/brcm80211/brcm/brcmfmac43430-sdio.bin > /usr/lib/firmware/brcm/brcmfmac43430-sdio.bin
curl --location https://github.com/RPi-Distro/firmware-nonfree/raw/master/brcm80211/brcm/brcmfmac43430-sdio.txt > /usr/lib/firmware/brcm/brcmfmac43430-sdio.txt

# 재부팅
shutdown -r now



업데이트와 재부팅이 끝나면 다시 접속해Raspberry Pi에서 wi-fi를 사용 할 준비가 됐는지 확인해준다.

# wi-fi 모듈이 사용 가능하면 wlan0 항목이 표시됨.
nmcli d



아래 명령어를 통해 주변에서 잡히는 와이파이 신호를 살펴보고, 본인이 접속할 wi-fi명과 패스워드를 넣어 연결해준다.

# 주변 wi-fi 탐색
nmcli d wifi

# wi-fi 연결
nmcli d wifi connect  password 

# 연결 확인
nmcli d



연결한 wi-fi의 세부정보를 확인하려면 아래와 같은 명령어를 사용한다.
# 접속한 wi-fi 세부정보 확인
nmcli d show wlan0




이것으로 본 Project 01에 대한 모든 내용을 정리해봤다.
아마 이 글을 읽는 독자분들이 지금까지 잘 따라왔다면, 분산병렬처리를 실험해볼 수 있는 클러스터를 하나씩 얻었을 것이라 생각된다.


----------------------
[Project 01] Raspberry Pi로 개인용 클러스터 구축하기
   #1: 클러스터 제작을 위한 준비물
   #2: Raspberry Pi에 CentOS 설치
   #3: Network 및 기초 설정
> #4: Raspberry Pi 클러스터 꾸미기



2017년 5월 11일 목요일

[Project 01] 3. Network 및 기초 설정

#1. 들어가기

전 단계에서 완성한 Raspberry Pi에 전원을 연결해 부팅 시켜보자. 운 좋게도 HDMI 선이 있다면 바로 연결시켜 컨트롤 할 수 있을것이다. 하지만, 없다고 해도 너무 우울해 하지 말자. 네트워크 공유기(AP)가 있다면 원격으로 접속하여 충분히 설정할 수 있다.



#2. 공유기 연결 및 설정

먼저, 준비한 공유기에 전원을 넣고 WAN과 연결해보자.
공유기에서 WAN을 연결하는 포트는 주로 색이나 무늬가 다르게 생겼다..
집에서 흔히 사용하던 인터넷 선을 여기에 연결시킨다.




공유기를 연결한 후, 해당 네트워크를 통해 접속하면(유선이나 무선 모두) 공유기를 설정할 수 있는 페이지에 접속할 수 있게 된다. ipTime 제품의 경우에는 초기 설정이 아래와 같을 것이다.

SSID : iptime
접근주소 : http://192.168.0.1
ID : admin
PW : admin



여기에서 각자의 취향에 맞게 이름, ID, PW 등을 변경해준다.



#3. Network 설정

아주 간단한 공유기 설정을 마쳤으면, 이제 본격적으로 Raspberry Pi들에게 네트워크를 할당해줄 차례이다.
먼저, 세 대 모두 LAN 케이블을 연결해준다. (나중에 Raspberry Pi를 Wifi로 연결하는 부분도 설명 할 예정임)




이렇게 연결하고 난 후, 다시 공유기 관리 사이트에 들어가보자. (Raspberry Pi의 어댑터에 파워를 넣으면 자동으로 부팅이 된다.)



내부 네트워크 설정 옵션에 들어가보면 공유기에 연결된 순서대로 IP번호를 부여받아 연결되어 있는 모습을 볼 수 있다. 각각의 라즈베리 파이에 고정IP를 부여하는 방법은 두가지가 있는데, 공유기에서 바로 MAC주소를 확인해 IP를 부여하는 방법과, OS에서 직접 IP를 static으로 할당하는 방법이 있다. 여기에서는 전자의 방법을 사용해보자.



ipTime 메뉴 기준으로 우측 아래 '수동 등록'을 통해 각각의 Raspberry Pi에 원하는 IP와 이름을 할당해준다. 필자는 관리를 편하게 하기 위해 뒷 자리를 11,12,13으로 맞췄다. (ex> 192.168.0.11)
단, 이렇게 수동 등록을 하고 나면, 공유기를 재부팅해야 정상적으로 동작한다는 사실을 알아두자.


#4. SSH 연결

ssh 연결을 위해 흔히 putty를 사용하는데, 필자는 Xshell이 더 다루기 편리해서 주로 이용중이다. 위 프로그램은 검색을 통해 쉽게 다운받을 수 있다.




조금 전 공유기에서 설정한 것 처럼, 각각의 IP를 입력하고 연결한다.
Raspberry Pi의 CentOS 7 버전을 기준으로 초기 ID와 PW는 다음과 같다.

ID : root
PW : centos

접속하고 나면 아래와 같은 화면이 뜰 것이다. 축하한다!



(단, 위 스크린샷은 고정IP를 할당하기 이전에 hostname을 변경하는 등, 캡쳐한 내용이 다소 다를 수 있다. 아무튼 이런 식으로 접속이 된다.)



#5. 기초 설정

접속에 성공한 후, 적어도 아래의 두 가지 사항은 바꿔줄 것을 권고한다. (그대로 두게 되면 보안상 취약하기도 하고, 세 대가 모두 같은 호스트네임을 쓰게 되어 문제가 생기기 때문에 꼭 바꿔주기를 권장한다.)

1. root password
# root password 변경
passwd


2. hostname
# hostname 변경
vi /etc/hostname

# hostname 적용
hostname -F /etc/hostname



추가로, 메모리카드에 4기가 이상을 넣었다면(아마 거의 대부분이..) 모든 메모리 용량을 사용하기 위해 아래와 같이 하나의 작업을 더 해줘야 한다. (root로 진행 필요)

# 디스크 용량 확인
hf -h

# 디스크 용량 확장
/usr/local/bin/rootfs-expand

# 작업이 완료될때까지 잠시 대기 후, 디스크 용량 재확인
hf -h






그럼, 3장에 대한 내용은 여기까지 마치고, 다음 장에서는 제작한 클러스터를 예쁘게(?) 꾸미는 방법을 알아보도록 하겠습니다.


----------------------
[Project 01] Raspberry Pi로 개인용 클러스터 구축하기
   #1: 클러스터 제작을 위한 준비물
   #2: Raspberry Pi에 CentOS 설치
> #3: Network 및 기초 설정
   #4: Raspberry Pi 클러스터 꾸미기

2017년 4월 27일 목요일

[Project 01] 2. Raspberry Pi에 CentOS 설치

#1. 들어가기

전 단계에서 모든 물품을 준비했다면, 이제 본격적으로 Raspberry Pi에 OS를 올려서 클러스터를 구성해보자. 본 글에서는 이미 안정화 된 CentOS 7 버전을 사용한다.



#2. 다운로드

1. centos img
아래 링크에서 최신 버전의 Raspberry Pi3용 이미지 파일을 다운로드한 후, 압축을 풀어준다.
http://mirror.centos.org/altarch/7/isos/armhfp/




2. rufus
아래 링크에서 최신 버전의 Rufus를 다운로드 한다.
https://rufus.akeo.ie/





#3. img write

1. sd card를 리더기에 넣고 usb 인식
2. rufus 실행
3. DD이미지 선택 후, 우측 단추를 눌러서 조금 전에 준비한 centOS 이미지를 선택하고 write 시작


4. 약 3~5분 후 완료되면 파일 확인


5. usb안전하게 제거



#4. sd카드 장착

리더기에서 micro sd카드를 제거 후, 하단의 이미지처럼 Raspberry Pi 3에 장착




그럼, 2장에 대한 내용은 여기까지 마치고, 다음 장에서는 Network 설정을 알아보고, 방금 전에 만든 Raspberry Pi에 접근하는 방법을 알아보도록 하겠습니다.



----------------------
[Project 01] Raspberry Pi로 개인용 클러스터 구축하기
   #1: 클러스터 제작을 위한 준비물
> #2: Raspberry Pi에 CentOS 설치
   #3: Network 및 기초 설정
   #4: Raspberry Pi 클러스터 꾸미기



2017년 4월 26일 수요일

[Project 01] 1. 클러스터 제작을 위한 준비물

#1. 들어가기.

지금부터 'Raspberry Pi로 개인용 클러스터 구축하기'라는 주제로 하나씩 글을 써내려가게 될텐데, 우선 그 첫 번째 단계인 구성품부터 먼저 알아보자.



#2. 클러스터 제작을 위한 구성품.




위에서부터 그리고 좌측에서부터 우측으로 순서대로 설명을 하면,

1. 개별 멀티탭(필수) - 넉넉하게 12~15A 이상 커버 가능한 제품 선택
2. microSD card 리더기(필수)
3. 라즈베리파이 방열판(옵션) - 라즈베리파이3는 발열이 높다고 함
4. 라즈베리파이3(필수) - 가급적이면 클러스터를 구성하는 라즈베리파이의 모델을 통일하며, 목적에 맞게 최소 3대 이상으로 구성
5. 전원어댑터(필수) - 주의! 라즈베리파이3 부터 최소 2.5A이상의 전원 필요. Wifi등 모듈 구동 시 넉넉하게 2.5~3A 제품으로 선택
6. microSD card(필수) - 기호에 맞게 선택. 단, 앞으로의 사용을 위해 넉넉한 용량과 10 class 이상의 등급을 추천
7. LAN케이블(필수) - Wifi로 연결해 사용 가능하나, 최초 이더넷 설정 시 필요함.
8. 유/무선 공유기(필수) - 주의! 라즈베리파이3의 Wifi를 지원하지 않는 모델 더러 존재. iptime제품을 살 경우에는 아래의 사이트를 참조하여 지원 가능한 모델 선택(필자가 선택한 모델의 경우 Wifi 사용이 불가했음... ㅜ)
공유기 wifi 지원 모델 참조 사이트 : http://forums.rasplay.org/topic/196/%EA%B3%B5%EC%A7%80-raspberrypi-model-3b-wifi-issue/2



#3. 구성품 표.

아래와 같이 표로 정리해봤다.
(혹이라도 현명한 소비에 민폐를 끼칠가봐 미리 제품명과 가격은 가려두었음.. 그래도 모델이나 구입 사이트가 필요하신분은 개인적으로 댓글이나 메일 주시면 가르쳐 드리겠습니다.)




그럼, 1장에 대한 내용은 여기까지 마치고, 다음 장에는 Raspberry Pi에 CentOS를 올리는 방법을 알아보도록 하겠습니다.


----------------------
[Project 01] Raspberry Pi로 개인용 클러스터 구축하기
> #1: 클러스터 제작을 위한 준비물
   #2: Raspberry Pi에 CentOS 설치
   #3: Network 및 기초 설정
   #4: Raspberry Pi 클러스터 꾸미기



2017년 4월 25일 화요일

[Bigdata] [Raspberry Pi] [Project 01] Raspberry Pi로 개인용 클러스터 구축하기

# 첫 번째 프로젝트를 시작하며..


  요즘 많은 사람들에게 '빅데이터'라는 단어는 아마 더 이상 어색한 단어가 아닐 것이다. 이렇게 빅데이터에 대한 관심이 날로 증대됨에 따라 '데이터 사이언티스트'에 대한 궁금증도 많이 늘어났을 것이다. 하지만, 데이터 사이언티스트라는 의미가 너무 크고 포괄적이어서 다시 그 의미를 크게 두 가지로 나누어 보겠다.
  먼저, 다양한 시스템 환경을 다룰 줄 알며, 각종 데이터의 생성, 관리, 처리에 관한 영역을 주로 전담는 '데이터 엔지니어'가 있다. 이러한 데이터 엔지니어들은 일반적으로 시스템 환경이나 구조, 아키텍처 등에 대해 깊은 이해가 있으며, 데이터 자체를 직접 핸들링하여 효율적으로 처리하는 기술을 갖추고 있다.
  다음으로, 각종 데이터에서 의미 있는 인사이트를 찾기 위해 주로 매쉬업이나 모델링과 같은 분석을 수행하는 '데이터 애널리스트'가 있다. 이러한 데이터 애널리스트들은 일반적으로 깊은 통계적 지식과 분석적 사고를 바탕으로 데이터를 바라보며, 비즈니스에 대한 로직을 적용시킬 수 있는 기술을 갖추고 있다.

  서론이 조금 길었는데, 필자는 많은 사람들이 꿈꾸는 '데이터 사이언티스트'에 한발짝 더 다가갈 수 있게, 그 환경을 구축하고 이용하는 방법에 대해 조금 더 설명하고자 몇 개의 프로젝트를 구상했다. 그 중 첫번째 프로젝트인 'Raspberry Pi로 개인용 클러스터 구축하기'는 아마 빅데이터 환경을 맛보고 실습하는데 필요한 개인용 서버를 부담되지 않는 비용으로 구축하는데 큰 도움이 될 것이다.




> [Project 01] Raspberry Pi로 개인용 클러스터 구축하기
   #1: 클러스터 제작을 위한 준비물
   #2: Raspberry Pi에 CentOS 설치
   #3: Network 및 기초 설정
   #4: Raspberry Pi 클러스터 꾸미기



# 이후 예정 프로젝트.


[Project 02] 분산병렬처리 및 실시간 처리를 위한 SW아키텍처 구축하기
[Project 03] IoT 장비를 이용한 실시간 센싱 데이터 처리하기




2017년 2월 24일 금요일

[Windows] [cmd] iconv를 이용해 cp949파일을 utf-8파일로 인코딩하기.

#1. 들어가기

 Windows에서 작성한 파일을 Linux에 넣다 보면 인코딩으로 인해 외계어가 속출하게 된다. (특히 DB 등에 넣다 보면...)
보통 윈도우는 cp949로 파일이 인코딩 된다.. 이것을 utf-8로 바꿔서 넣는 것이 정신건강에 이롭기 때문에 간편하게 윈도우 cmd 창에서 utf-8로 바꾸는 방법을 알아본다.


#2. iconv 다운로드

아래 사이트에서 'Complete package, except sources' 라고 되어있는 파일을 받자.
http://gnuwin32.sourceforge.net/packages/libiconv.htm

그리고 다음을 눌러가며 설치해주자.
설치 위치를 변경했다면, 바뀐 위치를 외워두고, 그렇지 않으면 default로 설치된 위치를 알아두자.


#3. 따라하기.

 1) 윈도우 메뉴 -> 실행 (단축키 : Win + r) -> cmd
 2) cmd 창에서 아래의 명령어 입력.

     cd C:\Program Files (x86)\GnuWin32\bin
     iconv -f cp949 -t utf-8 C:\test.txt > C:\test_utf8.txt

 3) 알 수 없는 문자들로 인해 모든 파일의 인코딩이 수행되지 못한 채로 에러가 나는 경우에는 아래의 두 가지 방법 중 하나를 선택할 수 있다.
     IGNORE : 에러나는 문자를 무시한다.
     TRANSLIT : 에러나는 문자를 비슷한 문자로 변경한다.

     iconv -f cp949 -t utf-8//IGNORE C:\test.txt > C:\test_utf8.txt
     iconv -f cp949 -t utf-8//TRANSLIT C:\test.txt > C:\test_utf8.txt

  4) 액세스가 거부되었습니다. 라고 나오는 경우에는 해당 위치에 파일 쓰기 권한이 없기 때문에, 아래와 같은 위치 등으로 옮겨서 저장해보자.

     C:\Users\user\Documents\test_utf8.txt