안경잡이개발자

728x90
반응형

다변인 선형회귀를 활용한 배추 가격 예측 AI 개발하기 5강 - 기초 데이터 시각화하기

나동빈


  지난 시간에는 간단히 저장된 학습 모델을 이용해 바로 결과를 예측해보는 방법에 대해 알아보는 시간을 가졌습니다. 이번 시간에는 엑셀(Excel)을 이용해서 기초 데이터를 시각화하는 방법에 대해 알아보는 시간을 가져보도록 하겠습니다.


※ 기초 데이터 시각화의 필요성 ※


  다양한 데이터를 수집해서 인공지능 모델을 돌려 보아도 입력 값과 결과 값의 상관 관계를 찾아내는 것은 쉽지 않을 수 있습니다. 그래서 만약에 많은 시행 착오를 거치고 있는 상황이라면 다양한 데이터를 수집해 보고, 데이터 시각화를 통해서 상관 관계를 유추하는 방법이 사용될 수도 있습니다. 특히 데이터의 개수가 많을 때는 한 눈에 데이터가 보이지 않을 수 있으므로 유용한 방법이 될 수 있습니다.


※ 엑셀로 시각화 해보기 ※


  우리가 학습 데이터로 사용했던 엑셀 파일을 열어 봅시다.



  저는 데이터 정제 과정에서 연도(Year) 정보를 단순한 숫자 형태로 넣었는데요, 엑셀 내에서 시간에 따른 데이터 시각화를 위해서는 '텍스트 나누기' 과정이 필요합니다.



  기본적인 설정대로 따르면 됩니다.





  위와 같이 '날짜'로 서식을 설정해주시면 자동으로 날짜 형태로 변환되는 것을 알 수 있습니다.



  이제 날짜(Year)와 평균 온도(Average Temp)를 설정해서 '데이터' -> '꺾은선 그래프'를 만들어 봅시다.



  그럼 위와 같이 날짜에 따라서 기온이 왔다갔다 하는 것을 시각화해서 확인할 수 있습니다.



  이후에 날짜와 가격을 기준으로 시각화를 진행해 봅시다.



  그럼 위와 같이 가격 그래프도 왔다갔다 봉우리 형태로 존재하는 것을 알 수 있습니다.



  위 그래프는 날짜에 따른 '강수량' 그래프입니다.


  위와 같은 그래프의 형태들을 확인했을 때 저는 온도 및 강수량이 배추 가격에 영향을 미치는 요인이 될 수 있다는 직감을 얻을 수 있었습니다. 이와 같이 기초 데이터를 시각화 하는 과정에서 다양한 인사이트를 얻을 수도 있다는 점을 유의해 주세요. 특정한 결과(Result)에 영향을 미치는 변인을 분석하는 과정에서 이러한 시각화는 큰 도움을 줄 수 있습니다.

728x90
반응형

728x90
반응형

다변인 선형회귀를 활용한 배추 가격 예측 AI 개발하기 4강 - 저장된 학습 모델로 배추 가격 예측하기

나동빈


  지난 시간에는 다변인 선형회귀 기본 예제를 이용해 배추 가격을 예측하는 학습 모델을 만들어 보았습니다. 이번 시간에는 그렇게 저장된 학습 모델을 필요할 때 불러와서 즉시 배추 가격을 예측할 수 있도록 해보겠습니다.


※ 학습 모델을 저장하는 이유 ※


  학습 모델을 저장하는 이유는 간단합니다. 만약 학습 모델을 저장하지 않고 사용자로부터 배추 가격 예측 요청(Request)이 발생할 때마다 매 번 학습을 해서 결과를 돌려준다면 시간이 오래 걸리고 많은 리소스가 소모 될 것입니다.


  따라서 오프라인(Offline)에서 주기적으로 데이터를 이용해 학습을 진행한 뒤에, 그 결과를 저장해서 서버에서는 실시간 요청에 따라 이미 저장된 학습 모델로 배추 가격을 예측하는 것이 효율적입니다.


※ 배추 가격 예측 테스트 소스코드 ※


  따라서 실제 웹 서버의 기능을 구현하기 전에 간단히 배추 가격을 예측하는 테스트 소스코드를 작성해봅시다.


import tensorflow as tf

import numpy as np


# 플레이스 홀더를 설정합니다.

X = tf.placeholder(tf.float32, shape=[None, 4])

Y = tf.placeholder(tf.float32, shape=[None, 1])


W = tf.Variable(tf.random_normal([4, 1]), name="weight")

b = tf.Variable(tf.random_normal([1]), name="bias")


# 가설을 설정합니다.

hypothesis = tf.matmul(X, W) + b


# 저장된 모델을 불러오는 객체를 선언합니다.

saver = tf.train.Saver()

model = tf.global_variables_initializer()


# 4가지 변수를 입력 받습니다.

avg_temp = float(input('평균 온도: '))

min_temp = float(input('최저 온도: '))

max_temp = float(input('최고 온도: '))

rain_fall = float(input('강수량: '))


with tf.Session() as sess:

    sess.run(model)


    # 저장된 학습 모델을 파일로부터 불러옵니다.

    save_path = "./saved.cpkt"

    saver.restore(sess, save_path)


    # 사용자의 입력 값을 이용해 배열을 만듭니다.

    data = ((avg_temp, min_temp, max_temp, rain_fall), )

    arr = np.array(data, dtype=np.float32)


    # 예측을 수행한 뒤에 그 결과를 출력합니다.

    x_data = arr[0:4]

    dict = sess.run(hypothesis, feed_dict={X: x_data})

    print(dict[0])



  이후에 파일을 위와 같이 저장된 학습 모델 파일과 동일한 경로에 두고 실행하시면 됩니다.



  위와 같의 임의로 넣어 본 데이터에서 학습 결과를 정상적으로 출력한 것을 알 수 있습니다.


- 평균 온도: 10

- 최저 온도: -5

- 최고 온도: 20

- 강수량: 0.8


예측된 배추 가격: 5946원

728x90
반응형

728x90
반응형

다이얼로그 플로우(Dialog Flow)에 엑셀 파일(csv) 등의 데이터를 한 번에 넣는 방법

나동빈


  구글의 다이얼로그 플로우를 이용할 때 우리는 기본적으로 자신이 직접 하나씩 입력(Input) 및 출력(Output)을 넣어서 챗봇(Chat Bot)을 개발해야 합니다. 


  하지만 챗봇을 위해 사전에 많은 양의 데이터를 준비하여 한 번에 넣어야 할 때가 있습니다. 예를 들어 저는 매우 많은 양의 영어 대화(English Conversation) 정보를 한 번에 다이얼로그 플로우에 삽입을 해야 하는 경우가 있었습니다.



  저는 이렇게 엑셀 형태로 챗봇에 들어갈 데이터가 약 3,000 개가 넘는 상황이었습니다.


  다이얼로그 플로우는 대용량 csv 파일을 한 번에 삽입할 수 있는 기능을 제공하고 있지 않습니다. 대신에 JSON 형태의 문서를 삽입할 수 있습니다. 그러므로 csv 파일을 다이얼로그 플로우에 맞는 전용 JSON 형식으로 바꾸어서 업로드(Upload) 해야 합니다. 이번 강에서는 다이얼로그 플로우 전용 JSON 형식으로 바꾸는 방법에 대해서 소개하고자 합니다.



  일단 하나의 에이전트(Agent)를 만들어 봅시다.



  그리고 일단 위와 같이 기본적으로 존재하는 두 개의 인텐트(Intent)를 지워줍니다.



  이제 위와 같이 'Test Intent'라는 이름으로 하나의 인텐트를 만든 뒤에 2개의 입력(Input)을 넣어보겠습니다.



  또한 하나의 출력(Output)을 가지도록 해보겠습니다.



  이후에 저장(Save)을 하고 해당 챗봇 프로젝트를 내보내기(EXPORT AS ZIP) 해봅시다.



  이후에 압축을 풀어 보면 위와 같이 폴더가 구성되어 있는 것을 확인할 수 있습니다. 여기에서 인텐트(Intent) 파일 정보는 intents에 담깁니다.



  위와 같이 intents 폴더에 들어가 보면 두 개의 JSON 파일이 존재하는 것을 알 수 있습니다. 먼저 'Test Intent.json'을 열어봅시다.



  우리가 바꾸어야 할 부분은 두 가지 입니다. 바로 이름(name)과 메시지(message)입니다. 이 부분을 바꾸어서 다시 Import 시키면, 그에 맞는 인텐트가 다이얼로그 플로우에 적용 될 것입니다. 다음으로는 'Test Intent_usersays_ko.json'를 열어 봅시다. 이 파일에는 사용자의 입력(Input) 데이터가 들어가 있습니다.



  위와 같이 입력 값의 개수에 맞게 텍스트(Text) 부분만 바꾸어주면 된 다는 것을 쉽게 이해할 수 있습니다.


  여기에서부터는 자신이 처한 환경에 따라서 구현 방법이 서로 다릅니다. 쉽지 않을 수 있다는 점을 감안하세요! 저는 파이썬(Python)을 이용해서 작업해보았습니다.


import openpyxl


# 한 건의 대화에 대한 정보를 담는 객체입니다.

class Conversation:

    

    # 질문(Question), 응답(Answer) 두 변수로 구성됩니다.

    def __init__(self, contentName, contentType, question, answer):

        self.contentName = contentName

        self.contentType = contentType

        self.question = question

        self.answer = answer


    def __str__(self):

        return "질문: " + self.question + "\n답변: " + self.answer + "\n"


# 영어 대화 데이터가 담긴 엑셀 파일을 엽니다.

wb = openpyxl.load_workbook('Conversation Data.xlsx')

 

# 활성 시트를 얻습니다.

ws = wb.active


conversations = []


# 시트 내에 존재하는 모든 영어 대화 데이터를 객체로 담습니다.

for r in ws.rows:

    c = Conversation(r[0].value, r[1].value, r[2].value, r[3].value)

    conversations.append(c)

    

wb.close()


for c in conversations:

    print(str(c))

    

# 모든 대화 내용을 출력합니다.

for c in conversations:

    print(str(c))

    

print('총 ', len(conversations), '개의 대화가 존재합니다.')



  저는 일단 위와 같이 파이썬을 이용해 엑셀에서 전체 데이터를 뽑아내 리스트(List)에 담았습니다.


# -*- coding: utf-8 -*-


# 파일로 출력하기

i = 1

# 출력, 입력 값 JSON 파일을 생성합니다.

prev = str(conversations[0].contentName) + str(conversations[0].contentType)

f = open(prev + '.json', 'w', encoding='UTF-8')

f.write('{ "id": "10d3155d-4468-4118-8f5d-15009af446d0", "name": "' + prev + '", "auto": true, "contexts": [], "responses": [ { "resetContexts": false, "affectedContexts": [], "parameters": [], "messages": [ { "type": 0, "lang": "ko", "speech": "' + conversations[0].answer + '" } ], "defaultResponsePlatforms": {}, "speech": [] } ], "priority": 500000, "webhookUsed": false, "webhookForSlotFilling": false, "fallbackIntent": false, "events": [] }')

f.close()

f = open(prev + '_usersays_ko.json', 'w', encoding='UTF-8')

f.write("[")

f.write('{ "id": "3330d5a3-f38e-48fd-a3e6-000000000001", "data": [ { "text": "' + conversations[0].question + '", "userDefined": false } ], "isTemplate": false, "count": 0 },')


while True:

    if i >= len(conversations):

        f.write("]")

        f.close()

        break;

    c = conversations[i]

    if prev == str(c.contentName) + str(c.contentType):

        f.write('{ "id": "3330d5a3-f38e-48fd-a3e6-000000000001", "data": [ { "text": "' + c.question + '", "userDefined": false } ], "isTemplate": false, "count": 0 },')

    else:

        f.write("]")

        f.close()

        # 출력, 입력 값 JSON 파일을 생성합니다.

        prev = str(c.contentName) + str(c.contentType)

        f = open(prev + '.json', 'w', encoding='UTF-8')

        f.write('{ "id": "10d3155d-4468-4118-8f5d-15009af446d0", "name": "' + prev + '", "auto": true, "contexts": [], "responses": [ { "resetContexts": false, "affectedContexts": [], "parameters": [], "messages": [ { "type": 0, "lang": "ko", "speech": "' + c.answer + '" } ], "defaultResponsePlatforms": {}, "speech": [] } ], "priority": 500000, "webhookUsed": false, "webhookForSlotFilling": false, "fallbackIntent": false, "events": [] }')

        f.close()

        f = open(prev + '_usersays_ko.json', 'w', encoding='UTF-8')

        f.write("[")

        f.write('{ "id": "3330d5a3-f38e-48fd-a3e6-000000000001", "data": [ { "text": "' + c.question + '", "userDefined": false } ], "isTemplate": false, "count": 0 },')

    i = i + 1


  저는 이후에 이렇게 막가파식으로 JSON 데이터를 생성하는 소스코드를 만들어 보았으며, 여러분은 자신의 입맛대로 소스코드를 작성하시면 됩니다. 제 소스코드는 결과적으로 다음과 같이 모든 영어 대화 내용을 다이얼로그 플로우에 삽입할 수 있는 JSON 파일을 만들어 냅니다.



  재미있는 점은 Intent 파일의 '아이디(id)' 값은 서로 동일하게 해도 다이얼로그 플로우에 적용 될 때 알아서 ID 값이 정상적으로 처리되기 때문에 정말 텍스트(Text) 값만 서로 다르게 해서 적용하면 문제 없이 등록됩니다.



  이제 우리가 처음에 다운로드 받았던 프로젝트 폴더의 intents 폴더 내에 모든 JSON 파일을 넣어주고 다시 압축해줍시다.



  이제 새롭게 만들어 진 챗봇 프로젝트 파일을 다시 삽입해줍시다.




  복구(RESTORE) 버튼을 눌러 프로젝트를 복구하면 다음과 같이 모든 인텐트가 들어가는 것을 알 수 있습니다.



  이로써 대용량 엑셀 파일로부터 다이얼로그 플로우에 인텐트를 삽입하는 방법을 알아보았습니다.


728x90
반응형

728x90
반응형

다변인 선형회귀를 활용한 배추 가격 예측 AI 개발하기 3강 - 다변인 선형회귀 모델 개발하기

나동빈


  이번 시간에는 지난 시간에 수집한 데이터를 이용하여 다변인 선형회귀로 학습 모델을 만들어 볼 것입니다.


※ 데이터 준비하기 ※


  가장 먼저 지난 시간에 정제해 놓은 학습 데이터를 준비합니다.



※ 다변인 선형회귀 ※


  다변인 선형회귀는 모델에 영향을 미치는 변인이 여러 개 일 때 사용하는 모델입니다. 현재 우리의 데이터에서는 변인이 '평균 온도', '최저 온도', '최고 온도', '강수량'이므로 이 모든 변인이 '가격'에 영향을 미친다고 감안해야 합니다. 따라서 가중치(Weight)을 고려했을 때 다음과 같은 수식을 세울 수 있습니다.


  H(x1, x2, x3, x4) = x1w1 + x2w2 + x3w3 + x4w4


  이는 행렬의 곱을 이용하면 다음과 같이 간단하게 표현할 수 있습니다.


  H(X) = XW


  이를 소스코드에 그대로 옮기면 됩니다. 다만 학습의 보폭(Step)을 적절히 선택해야 안정적으로 학습이 가능할 것입니다. 저는 학습률을 0.000005로 설정하여 되도록 짧은 시간에 정확한 결과가 나오도록 구현해보았습니다.


※ 파이썬 소스코드 ※


  파이썬에서 텐서플로우(Tensorflow) 라이브러리를 활용해 다변인 선형회귀 모델을 구현합니다.


import tensorflow as tf

import numpy as np

from pandas.io.parsers import read_csv


model = tf.global_variables_initializer();


data = read_csv('price data.csv', sep=',')


xy = np.array(data, dtype=np.float32)


# 4개의 변인을 입력을 받습니다.

x_data = xy[:, 1:-1]


# 가격 값을 입력 받습니다.

y_data = xy[:, [-1]]


# 플레이스 홀더를 설정합니다.

X = tf.placeholder(tf.float32, shape=[None, 4])

Y = tf.placeholder(tf.float32, shape=[None, 1])


W = tf.Variable(tf.random_normal([4, 1]), name="weight")

b = tf.Variable(tf.random_normal([1]), name="bias")


# 가설을 설정합니다.

hypothesis = tf.matmul(X, W) + b


# 비용 함수를 설정합니다.

cost = tf.reduce_mean(tf.square(hypothesis - Y))


# 최적화 함수를 설정합니다.

optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.000005)

train = optimizer.minimize(cost)


# 세션을 생성합니다.

sess = tf.Session()


# 글로벌 변수를 초기화합니다.

sess.run(tf.global_variables_initializer())


# 학습을 수행합니다.

for step in range(100001):

    cost_, hypo_, _ = sess.run([cost, hypothesis, train], feed_dict={X: x_data, Y: y_data})

    if step % 500 == 0:

        print("#", step, " 손실 비용: ", cost_)

        print("- 배추 가격: ", hypo_[0])


# 학습된 모델을 저장합니다.

saver = tf.train.Saver()

save_path = saver.save(sess, "./saved.cpkt")

print('학습된 모델을 저장했습니다.')



※ 저장된 모델 확인하기 ※


  이제 위 소스코드를 실행하면 됩니다. 결과적으로 향후 사용자가 날씨 정보를 입력했을 때 배추 가격을 바로 보여줄 수 있도록 학습 모델이 파일 형태로 저장된 것을 확인할 수 있습니다.




728x90
반응형

728x90
반응형

다변인 선형회귀를 활용한 배추 가격 예측 AI 개발하기 2강 - 프로젝트 아이디어 및 데이터 수집

나동빈


  지난 시간에는 프로젝트의 개요에 대해 소개하는 시간을 가졌습니다. 이번 시간에는 프로젝트 아이디어를 고려하고 데이터를 수집하는 시간을 가집니다. 다변인 선형회귀는 데이터를 예측할 때 사용할 수 있는 대표적인 모델입니다. 따라서 특정한 대상을 예측해보는 프로젝트 아이디어를 생각해 보면 좋을 것입니다.


※ 프로젝트 아이디어 ※


  최근 태풍이 심해지고 있어 기후 변화가 심한 상태입니다. 이러한 배경에서 채소 중에서 '배추'의 가격은 날씨와 어떠한 변화가 있을지 궁금하여 배추 가격을 예측하는 인공지능을 만들어 보면 어떨까 생각해보았습니다.



  이외에도 우리의 주변에서는 인공지능을 활용해 분석할 수 있는 다양한 주제가 있습니다. 삶을 더욱 윤택하게 만들기 위해 다양한 아이디어를 고민해보는 습관을 기르는 것이 좋을 것 같습니다.


※ 데이터 수집 ※


  기후 데이터와 배추 가격 데이터는 어떻게 수집할 수 있을까요? 우리나라의 정부는 이러한 데이터를 무료로 제공해주고 있답니다. 다만 각 서비스는 데이터를 제공하는 정책이 다를 수 있기 때문에 필요에 따라서 크롤링(Crawling)의 과정이 필요할 수도 있습니다.


기상자료개방포털 다중지점통계: https://data.kma.go.kr/climate/StatisticsDivision/selectStatisticsDivision.do?pgmNo=158



농산물유통정보: https://www.kamis.or.kr/customer/price/retail/period.do?action=daily



※ 데이터 정제 ※


  수집한 데이터는 인공지능 소프트웨어가 인식하기 쉬운 형태로 정제해야 합니다. 배추 가격은 주말에는 책정되지 않는 점이나 몇몇 일자에서 톡톡 튀는 데이터가 있는 점 등을 감안해서 데이터를 쉽게 적용할 수 있는 형태로 바꾸어 주는 작업이 필요합니다.



※ 데이터 파일 ※


  직접 데이터를 추출하고 정제하는 과정이 귀찮으신 분은 다음의 파일을 다운로드 하시면 됩니다.


price data.csv


728x90
반응형

728x90
반응형

다변인 선형회귀를 활용한 배추 가격 예측 AI 개발하기 1강 - 프로젝트 개요 및 데이터 수집 방법

나동빈


  이번에 준비한 시리즈 강의는 <다변인 선형회귀를 활용한 배추 가격 예측 AI 개발하기> 강의 입니다. 본 강의는 초급 수준의 인공지능 프로젝트 강의이며 단순히 인공지능 학습 모델만 개발하는 것이 아니라 웹 서버 개발 과정까지 포함하여 '인공지능이 들어 간 상용 서비스를 만들 수 있을까?'에 대해서까지 인사이트(Insight)를 제공할 수 있는 강의입니다.


대상 독자


- 인공지능이나 웹 서버 동작 원리에 대해 잘 모르지만 따라해보며 빠르게 익히고 싶은 학생

- 인공지능의 기초 과정을 갓 공부한 뒤에 실전 프로젝트를 통해 배운 내용을 다지고 싶은 학생

- 간단한 인공지능을 활용해 기초적인 논문 수준의 실험을 경험 해보고 싶은 학생


다루게 될 기술


- 파이썬(Python)

- 텐서플로우(Tensorflow)

- 학습 모델 저장 및 불러오기

- 플라스크(Flask) 웹 서버

- MDBootstrap 디자인 프레임워크

- 클라우드 호스팅 서비스


시스템 구성도


함께 만들어 볼 결과물


  깃 허브 주소: https://github.com/ndb796/Vegita





728x90
반응형

728x90
반응형

셀레니움(Selenium)을 활용해 네이버 자동 로그인 및 메일 정보 가져오기

나동빈


※ 셀레니움 개요 ※


  셀레니움(Selenium)자동화 웹 사이트 분석 프레임워크로 크롤링(Crawling)을 수행함에 있어서 매우 효과적인 기능을 제공합니다.  특히 구글 크롬(Chrome)과 같은 웹 브라우저와 연동되어 다양한 디버깅을 할 수 있어 편리합니다.


※ 셀레니움 설치 ※


  셀레니움은 PIP 명령어를 이용해 파이썬(Python) 개발환경에 쉽게 설치할 수 있습니다.


  pip install selenium: 파이썬(Python)에서 셀레니움(Selenium)을 설치하는 명령어입니다.



※ 크롬 웹 드라이버 ※


  우리가 개발한 파이썬 크롤링 소프트웨어에서 크롬(Chrome) 브라우저의 기능을 이용하도록 하기 위해서 웹 드라이버(Web Driver)를 설치해야 합니다.


  크롬 드라이버 URL: http://chromedriver.chromium.org/downloads



  위와 같이 드라이버 다운로드 링크를 눌러서 다운로드를 수행할 수 있습니다.



  자신의 운영체제에 맞는 웹 드라이버를 다운로드 해줍니다.



  저는 위와 같이 C 드라이브에 압축을 풀어주었습니다.


※ 셀레니움을 이용해 네이버 자동 로그인 하기 ※



  먼저 위와 같이 네이버 로그인 페이지의 주소를 확인하고 소스코드를 작성합니다.


# 자동화 테스트를 위해 셀레니움(Selenium)을 불러옵니다.

from selenium import webdriver


# 크롬 웹 드라이버의 경로를 설정합니다.

driver = webdriver.Chrome('C:\Chrome Driver\Chrome Driver.exe')


# 크롬을 통해 네이버 로그인 화면에 접속합니다.

driver.get('https://nid.naver.com/nidlogin.login')



  위와 같이 자동으로 크롬(Chrome) 브라우저가 실행되어 네이버에 접속한 것을 알 수 있습니다.



  이후에 위와 같이 '페이지 소스 보기'에서 아이디 및 비밀번호 입력 <input> 태그의 name 속성을 확인합니다.


# 아이디와 비밀번호를 입력합니다. (0.5초씩 기다리기)

time.sleep(0.5)

driver.find_element_by_name('id').send_keys('아이디')

time.sleep(0.5)

driver.find_element_by_name('pw').send_keys('비밀번호')

time.sleep(0.5)


  기본적으로 대형 포털 서비스는 너무 빠르게 다수의 로그인을 시도하면 트래픽 공격으로 판단할 수 있으므로 0.5초씩 대기하는 등의 작업을 별도로 처리해주어야 합니다.



  이제 네이버에 접속한 이후에 자동으로 아이디 및 비밀번호까지 입력된 것을 알 수 있습니다.



  이후에 자동으로 로그인 버튼까지 누를 수 있도록 개발자 도구(F12)에서 로그인 버튼 부분의 XPath를 복사(Copy)합니다.


# XPath를 이용해 로그인을 시도합니다.

driver.find_element_by_xpath('//*[@id="frmNIDLogin"]/fieldset/input').click()



  이제 위와 같이 성공적으로 로그인까지 이루어진 것을 알 수 있습니다. 이후에 메일함으로 이동해 봅시다.


  네이버 메일함 주소: https://mail.naver.com/



  이후에 개발자 도구로 소스코드를 확인한 결과 메일함의 제목 부분은 <strong> 태그의 mail_title 클래스인 것을 확인할 수 있었습니다. 따라서 이를 파싱하여 출력하는 소스코드를 작성하면 됩니다.


# 웹 페이지의 소스코드를 파싱하기 위해 Beautiful Soup 라이브러리를 불러옵니다.

from bs4 import BeautifulSoup


driver.get("https://mail.naver.com/")

html = driver.page_source

soup = BeautifulSoup(html, 'lxml')


# 메일 제목을 하나씩 파싱합니다.

title_list = soup.find_all('strong', 'mail_title')


# 모든 메일 제목을 출력합니다.

for title in title_list:

    print(title.text)



  위와 같이 정상적으로 최근 도착한 메일 제목들을 출력하는 것을 알 수 있습니다.

728x90
반응형

728x90
반응형

웹 크롤러(Web Crawler)로 자동 로그인 및 주요 정보 추출하기

나동빈


  이번 시간에는 실제 웹 사이트를 대상으로 가장 많이 사용되는 기술 중 하나인 자동 로그인(Auto Login) 및 주요 정보 추출 방법에 대해 소개하고자 합니다. 이번 시간에도 제 개인 웹 사이트를 실습 대상으로 설정하겠습니다.


  웹 사이트 URL: http://dowellcomputer.com/member/memberLoginForm.jsp



  웹 사이트에 접속하면 위와 같이 로그인 화면이 등장합니다.



  바로 '페이지 소스 보기'를 통해 어떠한 서버 URL로 파라미터(Parameter)를 전송하는지 확인합니다.



  일단 직접 수동으로 로그인을 수행해보시면 메인(Main) 페이지로 로그인이 된 상태로 이동하는 것을 알 수 있습니다. 따라서 다음과 같이 두 개의 파라미터를 전달하여 로그인 하는 프로그램을 작성해 봅시다.


from bs4 import BeautifulSoup as bs

import requests


MEMBER_DATA = {

    'memberID': 'a',

    'memberPassword': 'a'

}


# 하나의 세션(Session) 객체를 생성해 일시적으로 유지합니다.

with requests.Session() as s:

    # 로그인 페이지로의 POST 요청(Request) 객체를 생성합니다.

    request = s.post('http://dowellcomputer.com/member/memberLoginAction.jsp', data=MEMBER_DATA)

    

print(request.text)



  위 실행 결과를 보면 성공적으로 로그인 되어 메인 페이지로 리다이렉션(Redirection) 시키는 소스코드가 있는 것을 알 수 있습니다.



  로그인 이후에는 위와 같이 '회원 정보 수정' 링크로 들어간 이후에 자신의 이메일 정보를 확인할 수 있는 것을 알 수 있습니다.


request = s.get('http://dowellcomputer.com/member/memberUpdateForm.jsp?ID=a')

soup = bs(request.text, 'html.parser')


result = soup.findAll('input',{"name": "memberEmail"})

print(result[0].get('value'))


  결과적으로 <input> 태그 중에서 'memberEmail'이라는 이름 속성을 가지는 결과를 찾아서 출력해주었습니다.



  실행 결과를 보면 성공적으로 이메일 값이 추출된 것을 알 수 있습니다.

728x90
반응형

728x90
반응형

웹 크롤러(Web Crawler)로 연속적인 크롤링하기

나동빈


  지난 시간에 이어서 웹 크롤러를 이용해 연속적인 크롤링 방법에 대해 알아보는 시간을 가져보겠습니다.


  이번 시간의 실습 대상은 다양한 영어 대화(English Conversation) 스크립트를 제공하는 웹 사이트입니다.


  웹 사이트: https://basicenglishspeaking.com/daily-english-conversation-topics/



  웹 사이트에 접속하면 위와 같이 75개의 주제(Topic)이 나오는 것을 알 수 있습니다. 일단 전체 주제의 개수가 총 몇 개인지 자동으로 세주도록 해봅시다. '페이지 소스 코드'를 보시면 다음과 같이 클래스명에 따라서 내용이 구분되는 것을 확인할 수 있습니다.



  따라서 먼저 전체 주제의 개수를 찾을 수 있도록 프로그램을 작성해보겠습니다.


from bs4 import BeautifulSoup

import requests


# 한 건의 대화에 대한 정보를 담는 객체입니다.

class Conversation:

    # 질문(Question), 응답(Answer) 두 변수로 구성됩니다.

    def __init__(self, question, answer):

        self.question = question

        self.answer = answer

        

    def __str__(self):

        return "질문: " + self.question + "\n답변: " + self.answer + "\n"


# 모든 영어 대화 주제를 추출하는 함수입니다.

def get_subjects():

    subjects = []


    # 전체 주제 목록을 보여주는 페이지로의 요청(Request) 객체를 생성합니다.

    req  = requests.get('https://basicenglishspeaking.com/daily-english-conversation-topics/')

    html = req.text

    soup = BeautifulSoup(html, 'html.parser')


    divs = soup.findAll('div',{"class": "su-column-inner"})

    for div in divs:

        # 내부에 존재하는 <a> 태그들을 추출합니다.

        links = div.findAll('a')


        # <a> 태그 내부의 텍스트를 리스트에 삽입합니다.

        for link in links:

            subject = link.text

            subjects.append(subject)

    

    return subjects


subjects = get_subjects()


print('총 ', len(subjects), '개의 타입을 찾았습니다.')


print(subjects)



  성공적으로 75개의 주제를 찾아서 출력한 것을 확인할 수 있습니다. 이제 이어서 실질적으로 각각의 주제에 포함되어 있는 영어 대화 스크립트를 추출할 수 있는 소스코드를 작성해봅시다.



예를 들어 'Family'로 요청(Request) URL을 설정하여 들어가면 위와 같이 다양한 영어 대화 스크립트가 존재합니다.



마찬가지로 '페이지 소스 보기'를 통해 소스코드를 확인했을 때 일정한 규칙이 존재하는 것을 확인할 수 있습니다.


위에서 제시한 소스코드에 이어서 다음과 같이 소스코드를 작성하여 모든 주제에 대한 대화 스크립트를 가져 올 수 있도록 합니다.


conversations = []

i = 1


# 모든 대화 주제 각각에 접근합니다.

for sub in subjects:

    print('(', i, '/', len(subjects), ') ', sub)

    # 대화 스크립트를 보여주는 페이지로의 요청(Request) 객체를 생성합니다.

    req  = requests.get('http://basicenglishspeaking.com/' + sub)

    html = req.text

    soup = BeautifulSoup(html, 'html.parser')

    

    qnas = soup.findAll('div',{"class": "sc_player_container1"})


    # 각각의 대화 내용에 모두 접근합니다.

    for qna in qnas:

        if qnas.index(qna) % 2 == 0:

            q = qna.next_sibling

        else:

            a = qna.next_sibling

            c = Conversation(q, a)

            conversations.append(c)

            

    i = i + 1

            

print('총 ', len(conversations), '개의 대화를 찾았습니다.')


for c in conversations:

    print(str(c))



728x90
반응형

728x90
반응형

웹 크롤러(Web Crawler)의 개요 및 공지사항 크롤링 해보기

나동빈


※ 웹 크롤러의 개요 ※


  웹 크롤러(Web Crawler)란 자동화된 방법으로 웹(WEB)에서 다양한 정보를 수집하는 소프트웨어를 의미합니다. 예를 들어 특정한 웹 사이트에 주기적으로 올라오는 글을 실시간으로 문자로 알림해주는 서비스 등을 직접 만들고 싶을 때 사용할 수 있습니다.


  웹 크롤러가 매우 유용한 이유는 원하는 서비스로부터 원하는 정보를 편하게 얻어올 수 있기 때문입니다.


  또한 웹 크롤러는 언어를 막론하고 자신이 원하는 언어로 개발할 수 있습니다. 필자는 오래 전부터 Java를 이용해왔으나 최근 Python이 웹 크롤러 기능을 매우 강력하게 지원하는 추세라서 Python으로 강의를 준비해보았습니다.


※ 웹 크롤러 개발환경 구축하기 ※


  웹 크롤러를 개발하기 위해 기본적으로 파이썬(Python) 개발환경을 구축하셔야 합니다. 파이썬 개발환경이 구축되었다면 requests 라이브러리를 이용해 간단히 특정 URL의 HTML 소스코드를 가져오겠습니다. 타겟으로 설정한 사이트는 제 웹 사이트입니다.


  웹 사이트 URL: http://www.dowellcomputer.com/main.jsp


import requests


# 특정 URL에 접속하는 요청(Request) 객체를 생성합니다.

request = requests.get('http://www.dowellcomputer.com/main.jsp')


# 접속한 이후의 웹 사이트 소스코드를 추출합니다.

html = request.text


print(html)



  또한 웹 크롤러 개발을 위해 가장 많이 사용되는 라이브러리는 뷰티풀 수프(Beautiful Soup)입니다. 뷰티풀 수프는 특정 웹 사이트의 소스코드를 가져와 자유자재로 파싱(Parsing)하는 작업에 큰 도움을 줍니다. 저는 '최근 공지사항' 내용을 파싱하는 방법을 소개하고자 합니다.


  한 번 웹 사이트에서 마우스 우클릭 이후에 '페이지 소스 보기(V)'를 눌러서 소스코드를 살펴봅시다.



  이후에 아래와 같이 공지사항의 제목은 <td> 태그 내부의 <a> 태그로 구성되어 있는 것을 알 수 있었습니다.



  따라서 뷰티풀 수프를 이용해서 위에서 작성한 소스코드를 확장해봅시다.


import requests

from bs4 import BeautifulSoup


# 특정 URL에 접속하는 요청(Request) 객체를 생성합니다.

request = requests.get('http://www.dowellcomputer.com/main.jsp')


# 접속한 이후의 웹 사이트 소스코드를 추출합니다.

html = request.text


# HTML 소스코드를 파이썬 객체로 변환합니다.

soup = BeautifulSoup(html, 'html.parser')


# <a> 태그를 포함하는 요소를 추출합니다.

links = soup.select('td > a')


# 모든 링크에 하나씩 접근합니다.

for link in links:

    # 링크가 href 속성을 가지고 있다면

    if link.has_attr('href'):

        # href 속성의 값으로 notice라는 문자가 포함되어 있다면

        if link.get('href').find('notice') != -1:

            print(link.text)



  소스코드 실행 결과 위와 같이 2건의 공지사항 제목이 출력된 것을 알 수 있습니다.



  실제로 웹 사이트에서 보이는 '최근 공지사항' 내용과 정확히 일치합니다. 이상으로 간단한 형태의 웹 크롤러 개발 방법을 알아보았습니다.


728x90
반응형