본문 바로가기

Programming/Project

네이버 검색API로 정보보안 뉴스 수집(with Python)

정보보안 실무에서는 정책, 실제점검, 운영 등도 중요하지만 보안사고나 이슈를 빨리 확인하는 부분도 중요하다. 사고나 이슈 관련 뉴스를 통해 현재 운영하는 조직이나 시스템에 해당 문제점이 있진 않는지 파악하고 적시에 조치를 해야 하기 때문이다. 또한 사고사례를 재가공하여 임직원을 대상 내부 교육 자료로 활용 할 수 있다.

때문에 보안담당자, 실무자들은 메일링 서비스나 뉴스레터를 구독하고 있는 경우가 많다. 하지만 특정 업체나, 언론사 뉴스레터 서비스는 광고등에 의해 리포트 내용이 달라지는 경우가 있다. 이럴경우 담당자가 전체 언론사를 대상으로 자체적으로 뉴스를 수집하여 관련 정보를 취합 할 수 있다면 다양한 각도에서 생각해 볼 수 있는 좋은 토대가 될것이다.

지난 포스팅에서 작성한 코로나, 부동산 관련 뉴스 수집 코드를 조금 변경해 보안뉴스를 수집하는 코드를 만들었다. 이번엔 해당 코드를 조금 바꾸어 하루치(24시간)의 정보보안, 정보보호 뉴스를 수집하는 코드를 작성했다. 지난번과 똑같이 네이버 검색 API를 사용했으며 개발과정에서 달라지거나 추가된 부분들은 아래와 같다

  • Naver 검색 API 1회 Response 값인 100개를 초과하는 기사들에 대한 수집코드 추가
  • 실행시간 기준 하루치의 기사만 수집 할 수 있도록 기사 작성 시간을 판별하는 Calc_Date 함수
  • Response JSON 값에서 원하는 데이터만 선별처리 하는 Get_Data 함수 (검색어, 기사타이틀, 기사요약, 링크, 날짜)
  • 선별된 JSON 값을 DataFrame을 사용해 정제하여 출력

해당 코드를 스케줄러에 등록하여 매일 새벽에 돌아가게 한다면 매일 관련 뉴스들을 수집 할 수 있다. 정규식으로 제외 키워드를 설정하고 엑셀, 메일로 발송하는 코드를 추가해 고도화 하면 더 효과적으로 사용 할 수 있다.

수집대상 세팅 : 정보보안, 정보보호 키워드와 출력갯수, 정렬방법, 카테고리 설정 코드

def Security_Main():
    json_result = []
    req_query = ['정보보안', '정보보호']
    req_display = '100'
    req_sort = 'date'
    req_target = ['news']  # 네이버 뉴스

    Search_Main(req_target, req_query, req_display, req_sort, json_result)

수집기능 Main : 정보보안 관련 뉴스 수집을 위한 값들을 요청하고 편집하는 main 코드

def Search_Main(req_target, req_query, req_display, req_sort, json_result):
    nStart = 0

    for target_url in req_target:  # 검색섹션을 정한다
        json_result.clear()

        for target_query in req_query:  # 검색 키워드를 정한다
            check_today = 0
            target_query = target_query.rstrip('\n')
            print("\nKeyword is " + target_url + "_" + target_query + ".......")
            json_search = Set_Search_Option(target_url, target_query, 1, req_display, req_sort)
            if (json_search == None):
                json_result.append({'Keyword': "", 'Title': "", 'Description': "", 'Link': "", 'Date': ""})
                continue

            while ((json_search != None) and (json_search['display'] != 0)):
                for post_data in json_search['items']:
                    if (post_data['originallink'] != None):
                        date_result = Calc_Date(post_data)

                        if (date_result == 0):
                            Get_Data(post_data, json_result, target_query)
                        else:
                            pd.set_option('display.max_columns', 5)
                            pd.set_option('display.width', 5000)
                            df = pd.DataFrame(json_result)
                            print(df)
                            check_today = 1
                            break

                tmp_nStart = nStart
                nStart = json_search['start'] + json_search['display']
                if (nStart == 1001 or (
                        nStart - json_search['start']) < 100 or tmp_nStart == nStart or check_today == 1):
                    break
                json_search = Set_Search_Option(target_url, target_query, nStart, req_display, req_sort)

날짜계산 : 현재시간으로부터 1일(24시간 기준)으로 작성된 기사 수집 코드

def Calc_Date(post_data):
    date_result = datetime.strptime(post_data['pubDate'], '%a, %d %b %Y %H:%M:%S +0900')
    now_time = datetime.now()
    calc_time = now_time - date_result

    if (calc_time.days == 0 and math.floor(calc_time.seconds / 3600) < 24):
        ret_calc = 0
    else:
        ret_calc = 1
    return ret_calc

검색 요청 URL 옵션 세팅 : MAIN에서 받아온 정보로 요청 URL을 만들어 주고 json 형식으로 리턴해주는 코드

def Set_Search_Option(target_url, search_keyword, page_start, display, sort):
    sleep(0.1)
    url = furl('https://openapi.naver.com/v1/search/' + target_url)
    url.args['query'] = search_keyword
    url.args['display'] = display
    url.args['sort'] = sort
    url.args['start'] = page_start

    ret_data = Get_Search_Result(url)

    if (ret_data == None):
        return None
    else:
        return json.loads(ret_data)

검색 Request : 위에서 최종적으로 세팅된 모든 결과를 취합하여 Request를 보내는 코드

def Get_Search_Result(req_url):
    request = urllib.request.Request(req_url)
    request.add_header("X-Naver-Client-Id", client_id)
    request.add_header("X-Naver-Client-Secret", client_secret)
    try:
        response = urllib.request.urlopen(request)
        rescode = response.getcode()

        if (rescode == 200):
            return response.read().decode('utf-8')
    except Exception as e:
        print(e)
        print("Error Code:" + str(req_url))
        return None

데이터 선별 : 요청에 의해 Response 되는 값중 필요한 부분만 선별하는 코드

def Get_Data(post, jsonResult, query):
    title_result = post['title']
    description_result = post['description']
    link_result = post['link']

    date_result = datetime.strptime(post['pubDate'], '%a, %d %b %Y %H:%M:%S +0900')
    col_date = date_result.strftime('%Y-%m-%d %H:%M')

    jsonResult.append({'Keyword': query, 'Title': title_result,
    'Description': description_result, 'Link': link_result, 'Date': col_date})

    return

[정보보안 기사 수집 Code]

import urllib.request
from furl import furl
import json
import math
from time import sleep

import pandas as pd

# 날짜, 파일명 세팅을 위한 import
import datetime
from datetime import datetime

# Navet API KEY
client_id = "YOUR_CLIENT_ID"
client_secret = "YOUR_CLIENT_SECRET"

def Security_Main():
    json_result = []
    req_query = ['정보보안', '정보보호']
    req_display = '100'
    req_sort = 'date'
    req_target = ['news']  # 네이버 뉴스

    Search_Main(req_target, req_query, req_display, req_sort, json_result)


def Search_Main(req_target, req_query, req_display, req_sort, json_result):
    nStart = 0

    for target_url in req_target:  # 검색섹션을 정한다
        json_result.clear()

        for target_query in req_query:  # 검색 키워드를 정한다
            check_today = 0
            target_query = target_query.rstrip('\n')
            print("\nKeyword is " + target_url + "_" + target_query + ".......")
            json_search = Set_Search_Option(target_url, target_query, 1, req_display, req_sort)
            if (json_search == None):
                json_result.append({'Keyword': "", 'Title': "", 'Description': "", 'Link': "", 'Date': ""})
                continue

            while ((json_search != None) and (json_search['display'] != 0)):
                for post_data in json_search['items']:
                    if (post_data['originallink'] != None):
                        date_result = Calc_Date(post_data)

                        if (date_result == 0):
                            Get_Data(post_data, json_result, target_query)
                        else:
                            pd.set_option('display.max_columns', 5)
                            pd.set_option('display.width', 5000)
                            df = pd.DataFrame(json_result)
                            print(df)
                            check_today = 1
                            break

                tmp_nStart = nStart
                nStart = json_search['start'] + json_search['display']
                if (nStart == 1001 or (
                        nStart - json_search['start']) < 100 or tmp_nStart == nStart or check_today == 1):
                    break
                json_search = Set_Search_Option(target_url, target_query, nStart, req_display, req_sort)


def Calc_Date(post_data):
    date_result = datetime.strptime(post_data['pubDate'], '%a, %d %b %Y %H:%M:%S +0900')
    now_time = datetime.now()
    calc_time = now_time - date_result

    if (calc_time.days == 0 and math.floor(calc_time.seconds / 3600) < 24):
        ret_calc = 0
    else:
        ret_calc = 1
    return ret_calc

# 검색 결과를 얻어옴
def Set_Search_Option(target_url, search_keyword, page_start, display, sort):
    sleep(0.1)
    url = furl('https://openapi.naver.com/v1/search/' + target_url)
    url.args['query'] = search_keyword
    url.args['display'] = display
    url.args['sort'] = sort
    url.args['start'] = page_start

    ret_data = Get_Search_Result(url)

    if (ret_data == None):
        return None
    else:
        return json.loads(ret_data)

# 검색 요청 보냄
def Get_Search_Result(req_url):
    request = urllib.request.Request(req_url)
    request.add_header("X-Naver-Client-Id", client_id)
    request.add_header("X-Naver-Client-Secret", client_secret)
    try:
        response = urllib.request.urlopen(request)
        rescode = response.getcode()

        if (rescode == 200):
            return response.read().decode('utf-8')
    except Exception as e:
        print(e)
        print("Error Code:" + str(req_url))
        return None

# 필요한 데이터만 선별
def Get_Data(post, jsonResult, query):
    title_result = post['title']
    description_result = post['description']
    link_result = post['link']

    date_result = datetime.strptime(post['pubDate'], '%a, %d %b %Y %H:%M:%S +0900')
    col_date = date_result.strftime('%Y-%m-%d %H:%M')

    jsonResult.append({'Keyword': query, 'Title': title_result, 'Description': description_result, 'Link': link_result, 'Date': col_date})

    return

Security_Main()

[실행결과]

Keyword is news_정보보안.......
    Keyword                                            Title                                        Description                                               Link              Date
0      정보보안  컴퓨터학원 코리아IT아카데미, ‘뜻밖의 특템’ 이벤트로 31,000여 개의 무료...  <b>정보보안</b>학원 코리아IT아카데미 관계자는 “따즈아 온라인 강의는 코리아교...  http://edu.donga.com/?p=article&ps=view&at_no=...  2020-04-29 12:00
1      정보보안                       서울시 2022년까지 와이파이6 공공생활권 설치  장비 성능평가시험(BMT)에 참여를 희망하는 업체는 5월11일(월)~12일(화) 서...  http://www.newsmaker.or.kr/news/articleView.ht...  2020-04-29 11:58
2      정보보안         쌍용차 리스펙 코란도·티볼리···&quot;CJ오쇼핑에서 판매&quot;  안전 및 <b>보안</b>, 비서, <b>정보</b>, 즐길거리, 원격제어, 차량관...  http://www.seoulfn.com/news/articleView.html?i...  2020-04-29 11:55
3      정보보안        모질라, 인기 높은 화상 회의 앱 15개의 <b>보안</b>성 검사해 발표  많은 사람들이 찾는 유명 앱들이며, 사용자들이 궁금해 하는 <b>보안</b> 관련 ...  http://www.boannews.com/media/view.asp?idx=879...  2020-04-29 11:54
4      정보보안            서울 S-NET 핵심 와이파이6 구축 돌입...BMT 참여기업 공모  장비 성능평가시험(BMT)에 참여를 희망하는 업체는 5월 11일~12일 서울시청 <...  https://news.naver.com/main/read.nhn?mode=LSD&...  2020-04-29 11:40
..      ...                                              ...                                                ...                                                ...               ...
132    정보보안          롤스로이스, COVID-19 데이터 연합 구축…비즈니스·경제 회복 지원  데이터 출판물과 라이선스, 개인<b>정보</b>보호 및 <b>보안</b>, 데이터 ...  http://www.efnews.co.kr/news/articleView.html?...  2020-04-28 12:55
133    정보보안                      인텔, 마이크로소프트 애저 DCsv2-시리즈 출시  애저는 클라우드에서 데이터를 처리하는 동시에 <b>보안</b> 및 개인 <b>정보<...  http://www.it-b.co.kr/news/articleView.html?id...  2020-04-28 12:42
134    정보보안                             인텔, 애저 기밀 컴퓨팅의 기반 마련  애저는 클라우드에서 데이터를 처리하는 동시에 <b>보안</b> 및 개인 <b>정보<...  http://sports.news.naver.com/esports/news/read...  2020-04-28 12:40
135    정보보안          포스트 코로나19 시대를 준비하는 유망기술은? 29일 온라인 포럼 개최  □ (2단계 : 영역별 변화상) 두 번째 단계로,향후 4대 환경변화에 의해서 큰 변...  https://news.naver.com/main/read.nhn?mode=LSD&...  2020-04-28 12:20
136    정보보안   &quot;포스트코로나 원격의료·비대면 서비스 향상…글로벌 공급망도 재편&quot;  두 번째 단계로, 향후 4대 환경변화에 의해서 큰 변화가 예상되는 사회·경제 영역으...  http://www.topstarnews.net/news/articleView.ht...  2020-04-28 12:13

[137 rows x 5 columns]

Keyword is news_정보보호.......
    Keyword                                            Title                                        Description                                               Link              Date
0      정보보안  컴퓨터학원 코리아IT아카데미, ‘뜻밖의 특템’ 이벤트로 31,000여 개의 무료...  <b>정보보안</b>학원 코리아IT아카데미 관계자는 “따즈아 온라인 강의는 코리아교...  http://edu.donga.com/?p=article&ps=view&at_no=...  2020-04-29 12:00
1      정보보안                       서울시 2022년까지 와이파이6 공공생활권 설치  장비 성능평가시험(BMT)에 참여를 희망하는 업체는 5월11일(월)~12일(화) 서...  http://www.newsmaker.or.kr/news/articleView.ht...  2020-04-29 11:58
2      정보보안         쌍용차 리스펙 코란도·티볼리···&quot;CJ오쇼핑에서 판매&quot;  안전 및 <b>보안</b>, 비서, <b>정보</b>, 즐길거리, 원격제어, 차량관...  http://www.seoulfn.com/news/articleView.html?i...  2020-04-29 11:55
3      정보보안        모질라, 인기 높은 화상 회의 앱 15개의 <b>보안</b>성 검사해 발표  많은 사람들이 찾는 유명 앱들이며, 사용자들이 궁금해 하는 <b>보안</b> 관련 ...  http://www.boannews.com/media/view.asp?idx=879...  2020-04-29 11:54
4      정보보안            서울 S-NET 핵심 와이파이6 구축 돌입...BMT 참여기업 공모  장비 성능평가시험(BMT)에 참여를 희망하는 업체는 5월 11일~12일 서울시청 <...  https://news.naver.com/main/read.nhn?mode=LSD&...  2020-04-29 11:40
..      ...                                              ...                                                ...                                                ...               ...
472    정보보호                           개별주택 공시가격 열람 및 이의신청 접수  지난해부터 전자 열람의 보편화, 개인<b>정보보호</b>, 예산 절감 등에 따라 개...  http://www.upkorea.net/news/articleView.html?i...  2020-04-28 12:30
473    정보보호       경기남부경찰, 성 착취물 제작·판매·유포 72명 검거...10대가 가장 많아  경찰은 이들 중 9명을 아동·청소년의 성<b>보호</b>에 관한 법률 위반 등 혐의...  http://www.hg-times.com/news/articleView.html?...  2020-04-28 12:24
474    정보보호             한국환경공단, '가축분뇨 전자인계관리시스템' 사전 알림 기능 강화  액비살포 금지구역 알림 기능은 전국 수변구역 및 상수원 <b>보호</b>구역 위치<...  http://theleader.mt.co.kr/articleView.html?no=...  2020-04-28 12:24
475    정보보호                 서울아산병원, '의료진 손위생' 인공지능(AI) 관리 가능  의료진 개인<b>정보</b>가 안전하게 <b>보호</b>된다는 장점이 있다.서울아산...  http://www.dailymedi.com/detail.php?number=855...  2020-04-28 12:20
476    정보보호      KISA, 중소기업 ‘개인<b>정보</b> 솔루션’ 지원… 점검도구 무료 배포  지난 2015년부터 개인<b>정보보호</b> 종합포털을 통해 배포하고 있다. 특히 ...  http://www.viva100.com/main/view.php?key=20200...  2020-04-28 12:20

[477 rows x 5 columns]