Web Crawling with Scrapy(2)

지난 포스트에서는 Scrapy Shell에서 간단한 명령 코드를 이용하여 간단히 Web Crawling을 수행해 보았다.

이번에는 지난 포스트에서 작성한 Shell 명령 코드를 활용하여 Spider Project를 만들어서 데이터를 주기적으로 업데이트 할 수 있는 Crawler 모듈을 만들어 보겠다.

그럼, Spider Project를 만들어 보자.

아래와 같이 Project를 구성할 위치에서 명령어를 실행해보자.

# newsCrawler라는 Spider Project를 만든다.
$ scrapy startproject newsCrawler

명령 실행이 완료 되면, 다음과 같은 메시지가 나오면서 Start Project가 만들어 진것을 확인 할 수 있다.

You can start your first spider with:
    cd newsCrawler
    scrapy genspider example example.com

이제, newsCrawler라고 만든 프로젝트를 이용하여 Crawler 모듈 개발 작업을 시작하면 되는데… 그전에 먼저, Project의 구성에 대해서 간단히 알아보도록 하자.

  • newsCrawler/ # Root Directory
    • scrapy.cfg # 프로젝트 설정 파일
    • newsCrawler/ # 프로젝트 공간
      • __init__.py
      • items.py # Spider가 작업을 완료한 후 반환하는 결과 값의 Schema를 정의하는 파일
      • middlewares.py # Spider가 요청을 보낼 때 process를 제어하는 파일
      • pipelines.py # Spider가 응답을 받았을 때 process를 제어하는 파일
      • settings.py # Spider 실행에 필요한 전반적인 옵션을 설정하는 파일
      • spiders/ # 데이터를 수집 가공하는 Spider(Crawler) 모듈을 개발하는 공간, 여러개의 Spider가 있을 수 있다.
        • __init__py

위 프로젝트 구성을 보면 “nwesCrawler/spider”라는 위치에서 Spider(Crawler)를 개발하면 되는 것을 알 수 있다.

해당 위치로 이동하여 아래와 같이 Spider(Crawler) 생성 명령을 실행해 보자.

# Project의 spiders폴더로 이동하여 newsBot이라는 Spider를 생성한다.
$ cd newsCrawler/spiders
$ scrapy genspider newsBot 'news.daum.net/ranking/popular'

명령 실행이 완료되면 다음과 같이 기본 Template이 생성되었다는 메시지를 확인 할 수 있다.

Created spider 'newsBot' using template 'basic' in module:
  {spiders_module.__name__}.{module}

이제, 만들어진 Template(newsBot.py)에 이전에 만들어둔 Shell 명령 코드를 넣어서 Spiders(Crawler) 모듈 개발 작업을 하면 된다.

import scrapy

class NewsbotSpider(scrapy.Spider):
    name = 'newsBot'
    allowed_domains = ['news.daum.net/ranking/popular']
    start_urls = ['http://news.daum.net/ranking/popular/']

    def parse(self, response):
        # Web Crawling with Scrapy(1) 참고
        titles = response.xpath('//ul[@class="list_news2"]/li/div[2]/strong/a/text()').extract()
        authors = response.xpath('//ul[@class="list_news2"]/li/div[2]/strong/span/text()').extract()
        previews_text = response.xpath('//ul[@class="list_news2"]/li/div[2]/div[1]/span/text()').extract()
        previews_image = response.xpath('//ul[@class="list_news2"]/li/a/img/@src').extract()

        for item in zip(titles, authors, previews_text, previews_image):
            scraped_info = {
                'title': item[0].strip(),
                'author': item[1].strip(),
                'preview_text': item[2].strip(),
                'preview_image': item[3].strip()
            }
            yield scraped_info

개발 작업 완료되었으면, 아래와 같이 newsBot을 실행시켜 보자.

# newsBot 실행하고 결과는 JSON 파일로 지정위치에 출력한다.
$ scrapy crawl newsBot -o ./newsCrawler/json/result.json

실행이 완료되면 결과가 지정된 위치 “newsCrawler/json”에 JSON 파일로 만들어 진 것을 확인 할 수 있다.

그런데 JSON 파일을 열어보면 다음과 같이 Unicode로 결과가 출력되어 데이터가 잘 수집된 것인지 확인 하기가 어렵다.

[
    {
        "title": "\ubb38 \ub300\ud1b5\ub839 \"3\ub2e8\uacc4 \uaca9\uc0c1\uc740 \ub9c8\uc9c0\ub9c9 \uc218\ub2e8..\ubd88\uac00\ud53c\ud558\uba74 \uacfc\uac10\ud788 \uacb0\ub2e8\"",
        "author": "\uacbd\ud5a5\uc2e0\ubb38",
        "preview_text": "[\uacbd\ud5a5\uc2e0\ubb38] \ubb38\uc7ac\uc778 \ub300\ud1b5\ub839\uc740 13\uc77c \ucf54\ub85c\ub09819 \ud655\uc9c4\uc790\uac00 \uae09\ub4f1\uc138\ub97c \ubcf4\uc774\ub294 \uac83\uacfc \uad00\ub828, \u201c\uc9c0\uae08 \ud655\uc0b0\uc138\ub97c \uaebe\uc9c0 \ubabb\ud558\uba74 \uc0ac\ud68c\uc801 \uac70\ub9ac\ub450\uae30 3\ub2e8\uacc4 \uaca9\uc0c1\ub3c4 \uac80\ud1a0\ud574\uc57c \ud558\ub294 \uc911\ub300\ud55c \uad6d...",
        "preview_image": "https://img1.daumcdn.net/thumb/S95x77ht.u/?fname=https%3A%2F%2Ft1.daumcdn.net%2Fnews%2F202012%2F13%2Fkhan%2F20201213154335225ujgt.jpg&scode=media"
    },
    ..... 생략 .....
]

출력 결과를 알아보기 쉽게 한글로 표현하기 위해서는 settings.py에 출력결과가 utf-8로 인코딩될 수 있도록 설정을 추가 해주면 된다.

FEED_EXPORT_ENCODING = 'utf-8'

설정 내용을 저장하고 다시한번 newsBot을 실행 시켜보자.

다시 작업을 실행하고 결과로 출력된 JSON 파일을 열어보면 한글로 잘 출력된 것을 확인 할 수 있다. 그리고 실제 사이트와 데이터를 비교해 보면 다음과 같이 잘 수집되었음을 확인 할 수 있을 것이다.

실제 사이트와 JSON 결과 파일 비교

데이터 수집 결과 까지 확인했으니 이제 남은 것은 주기적으로 실행되도록 하는 것인데, CRON Job을 사용하면 쉽게 Scheduling을 할 수 있다.

그런데… CRON은 무엇이 길래 Scheduling을 해준다는 것일까?

CRON이란, Unix system OS의 시간기반 Job scheduler다. 고정된 시간, 날짜, 간격에 맞춰 주기적으로 실행 할 수 있도록 scheduling을 할 수 있게 해주는데 여기에 수행할 Job(작업)을 지정해 주면 scheduling된 시점에 주기적으로 Job이 실행 되는 것이다.
(좀 더 자세한 CRON에 대한 설명을 원한다면, WiKi를 참고하길 바란다.)

CRON

CRON Job이 어떤 것인지 알아보았으니 만들어 사용해 보자.

먼저, Job으로 실행될 bash script file(crawl.sh)을 아래와 같이 만들어 준다.

#!/bin/sh
# spider project가 있는 프로젝트로 이동
cd newsCrawler/spiders

# scrapy가 설치된 python의 가상환경에서 spider 실행
pipenv run scrapy crawl newsBot -o ./newsCrawler/json/result.json

그 다음 만든 Script를 아래와 같이 CRON에 추가해 주면 Crawler에 대한 Scheduling 작업이 완료된다.

# 매일 0시 0분에 Crawling 작업을 한다.
0 0 * * * /Users/Python/newsCrawler/crawl.sh

정상적으로 CRON에 등록 되었다면 매일 0시 0분에 Cralwer가 동작 할 것이고 실행 결과는 json 폴더에 업데이트 될 것이다.

참고로, CRON Job이 정상적으로 동작했다면 아래와 같은 Syslog를 확인 할 수 있다.

Dec 14 00:00:00 DESKTOP CRON[1327]: (root) CMD (/Users/Python/newsCrawler/crawl.sh)

여기까지 Scrapy 오픈소스 라이브러리를 사용하여 Web Crawling 작업을 해 보았다.

간단히 사용법을 알아보는 정도에서 구성한 것이라 좀더 자세한 설명이나 추가적인 설명이 필요하다면, Scrapy에 대한 정보는 공식문서를 참고하길 바란다.

Web Crawling with Scrapy(1)

인터넷 상에는 무수히 많은 데이터가 있다. 그리고 우리는 그것을 수집하여 활용하고 싶지만 쉽지가 않다.

예를 들어 최근 뉴스를 수집하여 트랜드를 분석한다고 한다면, 뉴스 데이터를 어디서, 어떻게 얻을 것인가?

이미 잘 정리해서 제공하는 곳이 있다면 참 좋겠지만, 현실적으로 내가 원하는 데이터가 딱맞춰 제공되는 경우는 없다고 보는게 맞다. 그렇다면 원하는 데이터를 직접 수집을 해야한다는 말인데… 어떻게 할 수 있을까?

가장 단순하게는 인터넷 포털 사이트에서 하나하나 검색해서 수집할 수도 있지만, 수집에만 들어가는 시간과 노력이 만만치 않게 들어갈 것이다.

이런 데이터 수집에 대한 어려움을 프로그래밍으로 해결할 수 있다. 그 방법은 바로 Crawling(혹은 Scraping)이란 것이다.

Crawling을 하기위한 방법들은 여러가지가 있지만, 여기서는 Python 오픈소스 라이브러리 제공되고 쉽게 사용할 수 있는 Scrapy를 사용하여 Web Crawling을 하는 방법에 대해서 알아 보겠다.

Scrapy 라이브러리를 사용하기 위해서 다음과 같이 Scrpay 패키지를 설치해야 한다.

$ pip install scrapy

설치가 완료되면 Scrapy에서 제공하는 Shell을 이용할 수 가 있다. Shell에서는 간단히 명령문으로 만으로도 쉽게 Crawling을 실행 해 볼 수 있는데, 본격적으로 Crawling 프로그래밍을 하기 전에 수집할 데이터에 대한 이해를 하기 위해서 먼저 탐색적 접근을 해 볼 수 있다는 장점이 있다.

그럼, Shell을 이용하여 데이터를 탐색하고 수집해 보겠다.

# Scrapy Shell 실행
$ scrapy shell

Shell이 실행 되었으면, 데이터 수집을 시작 할 웹 사이트 위치를 지정해 준다.

# Daum 랭킹뉴스 - 많이 본 뉴스
$ fetch('https://news.daum.net/ranking/popular')
2020-12-08 00:10:23 [scrapy.core.engine] INFO: Spider opened
2020-12-08 00:10:23 [scrapy.core.engine] DEBUG: Crawled (200)  (referer: None)

정상적으로 실행 됬다면, Crawled라는 메시지와 함께 Response Code가 200으로 떨어지는 것을 확인 할 수 있다.

Crawler가 받은 데이터는 로컬 임시폴더(%userprofile%/AppData/Local/Temp)에 저장되어 지는데 다음과 같이 보기 명령문을 통해 데이터를 확인해 볼 수 있다.

$ view(response)

위 보기 명령문이 실행되면, HTML 페이지가 브라우저로 열릴 것이다. 그리고 해당 HTML 페이지는 실제 사이트가 아닌 로컬주소로 나타나는 것을 확인 할 수 있다. 이를 통해서 Scrapy가 웹 사이트를 Crawling하여 수집한 데이터는 HTML 페이지라는 것을 알 수 있다. 그리고 이 HTML 페이지 중에서 필요한 데이터 위치를 찾아서 추출 및 가공을 하여 유용한 데이터로 만들어 내면 되는 것이다.

그런데… HTML 페이지에서 어떻게 필요한 데이터 위치를 찾을까?

대부분의 HTML 페이지는 일종의 Document라고 할 수 있다. 그리고 Document는 DOM(Document Object Model)형태로 표현된다. 때문에 DOM을 활용하면 필요한 데이터 위치를 추적할 수 있다.

여기서 수집 하려고 하는 데이터는 다음과 같다고 정의해 보자.

  1. 제목
  2. 출처
  3. 미리보기(이미지, 글)

브라우저의 개발자 도구(F12)를 실행시켜 DOM 구조를 살펴보자.

DOM 구조와 데이터 위치

모든 뉴스는 “list_news2”라는 클래스를 속성 값으로 가진 UL Tag안에 모여 있는 것을 확인 할 수 있다. 그리고 각 수집 할 데이터 들은 그 하위 LI Tag 안에 위의 색으로 표시해둔대로 위치해 있는 것을 알 수 있다.

이제, 알아낸 데이터 위치 정보를 XPath 함수에 입력하여 필요한 데이터를 수집하면 된다.

첫 번째 수집 대상인 뉴스 기사 제목 부터 수집해 보자. XPath에 뉴스 제목의 위치 정보를 넘기기 위해서 다음과 같이 표현 할 수 있다.

'//ul[@class="list_news2"]/li/div[2]/strong/a/text()'

이 것의 의미는 “UL Tag 중에서 list_news2라는 클래스 속성 값을 갖는 객체를 Root로 한다. Root 밑에 개별 기사는 LI Tag에 담겨 있고, 그 밑에 두 번째 DIV 밑에 STRONG 밑에 A Tag Text에 기사 제목이 있다.” 라는 것이다.

위 표현 값을 XPath 함수에 넣어 실행해 보자.

# 뉴스 기사 제목
$ response.xpath('//ul[@class="list_news2"]/li/div[2]/strong/a/text()').extract()

실행 결과로 50개의 모든 뉴스 기사 제목을 리스트 형태로 반환한 것을 확인 할 수 있다.

['[날씨] 겨울 한파 찾아온다..9일 밤부터 곳곳 눈·비',
  '잘린 손가락 들고 20개 병원 전전 "코로나 아니면 치료도 못 받나요"',
  '"문 대통령 취임 초기 기대 컸지만.. 지금은 아니다"',
  "오보라던 '그들의 술자리'..총장도 검사들도 '조용'",
  '소형 오피스텔까지 싹쓸이.."막을 방법 없다"',
  .... 생략 ....
]

같은 방법으로 나머지 데이터도 수집해 보자.

# 뉴스 출처(언론사)
$ response.xpath('//ul[@class="list_news2"]/li/div[2]/strong/span/text()').extract()

# 미리 보기 글
$ response.xpath('//ul[@class="list_news2"]/li/div[2]/div[1]/span/text()').extract()

# 미리 보기 이미지 주소
$ response.xpath('//ul[@class="list_news2"]/li/a/img/@src').extract()

여기까지 잘 실행이 되었다면, Shell를 통해서 수집하려고한 대상 데이터에 대해서 Crawling이 가능하다는 것을 확인한 샘이다.

Shell 명령 코드로 수행해본 Crawling 작업이 1회성으로 데이터를 수집하고 끝나는 것이 라면 이대로 끝내면 되겠지만, 데이터를 주기적으로 추가 수집하거나 업데이트가 필요하다면, 매번 Shell 명령코드로 수행하기 어려울 것이다.

이런 부분은 Shell 명령 코드를 Crawler 모듈로 만들어서 주기적으로 실행 할 수 있으면 좋을 것이다.

다음 포스트에서는 이번 포스트에서 사용한 Shell 명령 코드를 그대로 활용하여 Spider Project를 만들고 주기적으로 데이터를 업데이트 할 수 있는 Crawler를 만들어 보겠다.

[공유]정보 시각화의 아름다움

오늘날 우리 주변에 대부분의 것들이 데이터로 표현되고 있다. 이러한 정보는 계속 누적되고 정보 과잉 상태로 이어져서 혼란스러워 보일 수 있다. 이런 문제점들은 정보의 시각화를 통해서 해소 될 수 있다. 다양하게 시각화된 그래프를 보고 고유한 패턴을 찾고 새로운 통찰력을 얻는 것이 중요한 것 같다.

The Beauty of data visualization

출처:TED

MS-SQL Cursor 사용하기

SQL 작업을 하다보면 조회된 쿼리 결과에 대해서 행 단위 작업이 필요할때가 있다. 이때, Cursor를 사용하면 효율적으로 처리 할 수 있다.

Cursor Command

  • DECLARE: Cursor에 관련된 선언을 하는 명령
  • OPEN: Cursor가 Query결과의 첫번째 Tuple을 포인트로 하도록 설정하는 명령
  • FETCH: Query 결과의 Tuple들 중 현재의 다음 Tuple로 커서를 이동시키는 명령
  • CLOSE: Query 수행을 모두 마친 후 Cursor를 닫기 위한 명령
  • DEALLOCATE: Close된 Cursor의 자원을 반환하는 명령

Cursor life cycle

Cursor Example

DECLARE @pColum_1 NVARCHAR(100), @pColum_2 INT, @pColum_3 BIT
DEClARE pCursor CURSOR
FOR
   select * from [Target Table]

OPEN pCursor

FETCH NEXT FROM pCursor INTO @pColum_1, @pColum_2, @pColum_3

WHILE(@@FETCH_STATUS <> -1)
   BEGIN
      update [Target Table] SET Colum = @Colum_1 + 1
      where Colum_2 = @pColum_2 and Colum_3 = @pColum_3
   END

CLOSE pCursor
DEALLOCATE pCursor

-유의사항-

Cursor를 사용하게 되면 내부적인 임시테이블을 사용하기 때문에 많이 사용하게 되면 DB성능에 영향을 미치게 된다. 되도록 사용량이 적은 시간때이거나 적은양의 데이터를 처리할 때 사용하는 것이 바람직 하다.

인공지능 프로그램 이해와 비즈니스 적용에 관하여

최근 인공지능이 실제 비즈니스에 적용되면서 많은 산업의 전반에 영향을 미치고 있다.
Statista에 따르면 세계적으로 인공지능에 대한 시장 전망이 2018년 약 95억달러에서 연 평균 43%씩 성장하여 2025년에는 1,186억달러 규모로 이를 것이라고 한다.

Revenues from the artificial intelligence (AI) software market worldwide from 2018 to 2025

AI를 포함한 글로벌 소프트웨어 서비스 전체 시장이 2018년부터 2025년까지 매년 10% 성장하여 3,229억 달러 규모가 될 것이라는 것을 생각해 보면 엄청난 투자와 성장이 이루어지고있다는 것을 알 수 있다.

이런 이유로 사업을 하는 사람이라면 누구나 기업 비즈니스에 어떻게든 하루 빨리 인공지능을 도입하고 싶을 것이다.

“그런데 정말 인공지능을 도입하면 비즈니스의 매출이 성공적으로 올라갈까?”
“기존의 소프트웨어 프로그램들로는 할 수 없는 것인가?”

이것에 대해 이야기하기 전에 먼저 기존의 소프트웨어 프로그램들이 어떠했는지 생각해 볼 필요가 있다.

그 동안의 프로그램들은 연속적이지 않고 구분되어진 이산 논리를 가지고 나오는 경우 수들을 공식화하여 만든 것들이다.

우리의 일상생활을 살펴 보자.

아침에 일어나야 하기 때문에 매일 아침 7시가 되면 알람이 울리도록 알람을 맞춘다. 시간은 사실 연속적이지만 그 시간을 시, 분, 초로 이산화 시켜 표기하고 아침 7시라는 경우가 되면 알림이 울리도록 되어 있는 것이다.

이것 저것 분주히 준비한 다음 집을 나서면 엘리베이터를 마주하게 된다. 엘리베이터의 한쪽 벽에 표시된 층수를 누르면 엘리베이터는 해당 층수로 이동한다. 공간 또한 마찬가지로 연속적이지만 층이라는 규격화된 높이로 이산화 시켜 표시하고 눌려진 버튼에 입력된 층의 위치로 이동하는 것이다.

예시에서 알 수 있듯이 이산 논리는 확실하게 구분된다. 어떤 경우에 해당되는지 그렇지 않은 것인지 확실한 선을 긋는 것이다. 이 선들이 조건(Rule)이 되고 조건들을 조합하여 공식을 만든 것이 프로그램이 되는 것이다.

일상에서 쉽게 볼 수 있는 간단한 프로그램들을 예시로 들었지만 사업에 사용되는 프로그램들도 마찬가지다. 단지, 관련 분야의 도메인 전문가가 문제를 해결하기 위해서 좀 더 세분화된 조건(Rule)들을 도출해 냈을 뿐이다.

예를 들어, 어느 과수원에서는 사과를 중량으로만 선별 하고 중량을 나누는 작업을 자동화 시스템으로 개발 한다고 가정해 보자. 먼저, 각 사과들의 중량을 측정할 것이다. 그리고 측정된 중량들을 이산화 된 등급의 조건으로 만들어 준다. 가령 200~350g이면 가정용, 351~400g이면 선물용 , 401g 이상은 제수용으로 등급을 만들어 주면 이 시스템을 통해서 사과들은 3개의 등급으로 구분되게 된다.

이 시스템에서는 사과의 무게가 350g이라면 가정용으로 분류할 것이다. 그리고 351g은 선물용으로 분류가 될 것이다. 그러면 1g 차이로 가정용과 선물용으로 분류 되는데 이 것이 합리적인 것일까? 350g이 351g보다 실제로 선물용으로 가치가 더 있다면?

실제로 사과를 제대로 선별하기 위해서는 중량 외에 빛깔, 형상, 과육 등등 기준들이 더 많이 있어야 한다. 때문에 사과를 좀 더 잘 선별하기 위해서는 ‘사과’라는 여러 속성을 갖는 객체를 만들고 각 속성에 값을 측정하여 입력하고 특정 조건이 만족할 경우 분류 되게 해야 한다.

그럼 다시 질문해 보자. 전 보다 조건이 많아 졌으니 이제는 합리적으로 나눌 수 있는 것일까?

글쎄다. 어디까지나 이산 논리에 대한 조건들이 세분화 된 것일 뿐이지 경계가 불분명한 예외사항은 언제나 발생 하고, 발생한 예외는 결국 사람이 처리해야 한다. 이것이 인공지능 이전의 프로그램 방식들인 것이다.

“그렇다면, 인공지능이 도입된 프로그램 방식은 무엇 일까?”

1(참)과 0(거짓)으로만 나누는 이산적인 방식에서 0~1 사이의 모든 실수로 확장된 것을 의미한다. 다시 말하면 어떤 등급에 속할 가능성으로 나타내는 것이다.

예를 들어, 사과의 중량은 350g이지만 다른 조건들로 인해 이 사과가 선물용으로 적합하다는 가능성이 0.86으로 정의 할 수 있다면 이 사과는 가정용이 아니라 선물용이 되는 것이다. 이처럼 경계선이 명확하지 않은 대상을 다룰 수 있는 것이 인공지능이 도입된 프로그램 방식이다.

이렇게 간단하게 설명하면 신기하게 들릴 수도 있지만 이것은 그 동안 잘 처리하지 못한 불분명한 예외사항을 기계가 효율적으로 나누기 위한 추론 기법일 뿐이다.

사람은 350~351g의 애매한 중량의 사과라면 손으로 만져보고 눈으로 보고 향을 맡아본 뒤 직관적으로 분류했을 것이다. 이렇게 사람이 분류 하던 데이터들을 기계에게 학습시키면, 기계는 데이터에서 패턴을 찾고 그 패턴을 추론로직으로 사용하는 것이다.

결국, 완전한 인공지능이라기 보단 사람의 직관을 흉내낼 수 있어서 사람의 인지적인 부분을 도와 줄 수 있는 형태인 것이다.

그런데 왜 이렇게 사람들이 관심을 갖고 열광하는 것일까?

그 이유는 최근 몇 년 사이 그 흉내내는 수준이 단순 흉내 이상의 가치를 만들고 시작했기 때문이다. 가장 가깝게는 스마트 폰으로 사진을 찍으면 사진을 자동으로 보정하고 분류해준다. 공장에서는 제품의 상태를 사람 보다 더 잘 예측하고, 병원에서는 환자의 영상데이터를 의사보다 더 정확히 분석하고 있다.

인지능력으로는 이미 인간의 수준을 넘어선 것있다.

이런 기능이 물리적인 제약 없이 24시간 365일 쉬지 않고 동작 할 수 있기 때문에 완전한 인공지능이 아님에도 불구하고 비즈니스 매출에 성공적인 상승 가져다 주는 것이다.

“그렇다면, 어떻게 하면 인공지능을 비즈니스에 적용 할 수 있을까?”

인공지능을 비즈니스에 적용하기 위해서는 많은 것들이 필요하지만 꼭 필요한 3가지가 있다.

첫째로 비즈니스에서 해결하고자 하는 문제점을 정확히 알아야 한다.
위에서 설명했듯이 최근의 인공지능은 완전한 인공지능이 아니기 때문에 그저 ‘도입하면 무엇이든 되겠지’라고 생각 하는 순간 실패사례로 남게 된다. 문제점을 잘 파악하기 위해서 비즈니스에 대한 프로세스를 잘 정립하고 프로세스 간의 절차와 관계를 정의하여 해결하려고 하는 문제점을 정확히 이해하고 도출해야 한다.

두번째로, 인공지능이 학습 가능한 데이터로 기존 데이터를 가공하고 수집해야 한다.
인공지능에 대한 환상으로 인해 생긴 오해 중 하나인데, 무작정 데이터가 있다고 해서 바로 인공지능에게 데이터를 학습시킬 수 있는 것이 아니다. 데이터에는 생각지도 못한 많은 노이즈 정보들이 있으며, 현재의 인공지능은 이런 정보까지 분별하지 못 한다. 특히, 데이터가 비정형 데이터라면 전처리 기술을 통해서 정형화 혹은 반정형화 작업을 해주어야 학습에 사용할 수 있다. 때문에 인공지능이 학습 가능한 형태로 데이터를 새롭게 만들어 가야 한다.

마지막으로 오픈소스 소프트웨어를 잘 활용해야 한다.
일반 기업에서 인공지능을 처음부터 개발한다는 것은 불가능에 가깝고, 투자가 가능하더라도 너무 뒤쳐지는 발상이다. 이미 잘 개발된 인공지능에 관련한 오픈소스들이 너무 많다. 국내 최고 기술 회사인 삼성, LG는 물론이고 글로벌 선두 IT 기업인 AMG(Amazon, MS, Google)도 인공지능 만큼은 오픈소스를 활용한다.
우리는 거인의 어깨에 올라탈 필요가 있다. 이미 글로벌 기업들이 자신들의 비즈니스로 검증한 오픈소스를 이용하는 것이 비용을 아끼면서 빠르게 성장할 수 있는 발판이 되는 것이다. 오픈소스에 기존 비즈니스를 잘 녹여낼 수 있다면 손쉽게 인공지능 서비스를 제공할 수 있음과 동시에 글로벌 기업의 인공지능 기술을 같이 공유하게 되는 것이다.

그 동안 공상과학 영화에서나 나오던 인공지능에 대한 것들이 점점 현실로 다가 오고 있다. 아직 사회적 부작용도 많고 완성도에서도 완전한 인공지능은 아니지만 인공지능 시장의 성장와 규제 대응 속도를 가만해 보면 향후 5~10년 안에는 우리 생활 속에 정착할 것으로 보인다. 그 때에 앞서가는 비즈니스를 하고 있으려면, 기존 비즈니스를 인공지능을 통해서 어떤 새로운 가치를 만들어 낼 것인가를 고민하는 것이 중요할 것 같다.

Python connect to MS-SQL with pymssql

Python에서 MS-SQL을 사용하려면 일단, MS-SQL DB를 지원하는 Python 모듈을 설치해야 한다. MS-SQL에 대한 모듈은 크게 pyodbc와 pymssql 두가지가 있는데 여기서는 pymssql을 사용 할 것이다.

(DB에 관련된 모듈은 무수히 많은 것들이 있다. 참고: https://www.lfd.uci.edu/~gohlke/pythonlibs/)

다음과 같이 pymssql을 설치한다.

(설치 방법은 Ubuntu Linux대상 이다. 다른 OS를 사용하는 경우는 여기를 참고하면 된다.)

$ apt-get --assume-yes update
$ apt-get --assume-yes install freetds-dev freetds-bin
$ pip install pymssql

이제 Python에서 설치한 모듈을 가지고 MS-SQL에 접근해 보자.

import json
import pymssql 

#[Tip]json 문자열을 환경변수 파일로 저장하여 사용한다면 서버정보를 노출 하지 않을 수 있다.
json_string = 
'{
    "host":"Server Address",
    "port":1433,
    "user":"User ID@Server Name",
    "password":"P@ssW0rd",
    "database":"Database Name"
}'
json_data = json.load(json_string)

#pymssql 모듈을 이용하여 Connection 생성을 한다.
conn = pymssql.connect(host=json_data['host'], port=json_data['port'], user=json_data['user'], password=json_data['password'], database=json_data['database'])

여기까지 하면 MS-SQL서버에 접근(Connection 완료) 한 것이다.
다음으로 Select query문을 실행하여 데이터를 가져와 보자.

#Connection으로부터 cursor 생성
cursor = conn.cursor() 

#Select Query 실행
cursor.execute('select * from [Target Table Name]') 

#결과 데이터를 데이터프레임에 저장
df = pd.DataFrame(cursor.fetchall())

#실행이 끝나면 항상 연결 객체를 닫아 주어야 한다.
conn.close() 

잘 실행 되었다면 결과를 담은 데이터프레임을 출력 해보자.

#결과 출력
print(df)

실행한 Select Query한 결과를 확인 할 수 있을 것이다.

MS-SQL Table Copy

학습 데이터를 준비 하려다 보면 기존의 데이터를 변형해야 될 때가 있다. 이때 원본 테이블을 가지고 바로 작업을 하게 되면 데이터가 손실 될 수 있다.
백업 데이터가 있다고 하면 그나마 다행이지만 보통 학습에 사용되는 데이터는 양이 많기 때문에 100% 복구하려면 시간이 걸린다.
이런 점들 때문에 될 수 있으면 테이블(혹은 데이터)을 복사해서 사용하면 좋다.

  1. 새 테이블을 생성 하면서 데이터 복사
select * into [New Table Name] from [Source Data]
  1. 테이블 구조만 복사
select * into [New Table Name] from [Source Table Name] where 1=2
  1. 기존 테이블에 데이터만 복사
insert into [Destination Table Name] select * from [Source Table Name]

MS-SQL Select random rows from Table

머신러닝 혹은 딥 러닝 학습을 하기 위해서는 우선 학습할 데이터를 탐색해 보아야 한다. 만약, 많은 양의 Row 데이터를 가지고 있는 SQL Table을 가지고 해야 한다면 일부 표본만 추출해서 테스트를 해보는 것이 필요하다.

이런 경우 테이블에서 랜덤으로 데이터를 추출할 때 다음 Query를 사용하면, 간단하게 일정 비율로 랜덤한 데이터를 추출해 낼 수 있다.

select top 10 percent * from [Table Name] order by newid()