본문 바로가기
Study/data

[빅데이터처리] 파이썬 크롤링 - API

by hapuripo_po 2022. 9. 8.

네이버 API를 이용한 크롤링


 

1. 네이버 개발자 센터(https://developers.naver.com) 접속

    네이버 개발자 가입 > 서비스 API 클릭

 

2. 오픈 API 이용 신청

    검색 > 오픈 API 이용 신청 클릭

 

3. 애플리케이션 등록

    원하는 이름으로 애플리케이션 이름 입력합니다.

    사용자 API에서 검색을 선택 합니다.

    환경 추가에서 WEB 설정 을 선택 합니다.

    웹 서비스 URL 저는 https://localhost로 설정 해 두었습니다.

 

4. 애플리케이션 정보 확인

    Client IDClient Secret에 대한 정보가 나옵니다. 해당 페이지를 벗어나도 다시 볼 수 있습니다.

    파이썬을 통해 크롤링 할 때 Client IDClient Secret이 필요합니다.

 

5. 검색 API 이용 안내 페이지 확인

    아래의 링크를 통해서 들어가셔도 됩니다.

    샘플 코드를 확인할 수 있습니다.

    https://developers.naver.com/docs/serviceapi/search/blog/blog.md#%EB%B8%94%EB%A1%9C%EA%B7%B8

 

6. 크롤링

    아래 코드를 실행하면 원하는 검색어를 입력 해 크롤링 할 수 있습니다.

    아래의 코드는 블로그를 대상으로 크롤링하는 코드입니다.

    블로그 외에 뉴스, 책, 영화 등 다른 대상으로 크롤링 하고싶다면, 사용되는 변수가 다를 수 있습니다.

    네이버 개발자 > Documents > 서비스 API > 검색에서 원하는 대상에 대한 정보를 확인할 수 있습니다.

import os
import sys
import urllib.request
import datetime
import time
import json


client_id = '[클라이언트 아이디]'
client_secret = '[클라이언트 비밀번호]'



#[CODE 1]
def getRequestUrl(url):    
    req = urllib.request.Request(url)
    req.add_header("X-Naver-Client-Id", client_id)
    req.add_header("X-Naver-Client-Secret", client_secret)
    
    try: 
        response = urllib.request.urlopen(req)
        if response.getcode() == 200:
            print ("[%s] Url Request Success" % datetime.datetime.now())
            return response.read().decode('utf-8')
    except Exception as e:
        print(e)
        print("[%s] Error for URL : %s" % (datetime.datetime.now(), url))
        return None

#[CODE 2]
def getNaverSearch(node, srcText, start, display):    
    base = "https://openapi.naver.com/v1/search"
    node = "/%s.json" % node
    parameters = "?query=%s&start=%s&display=%s" % (urllib.parse.quote(srcText), start, display)
    
    url = base + node + parameters    
    responseDecode = getRequestUrl(url)   #[CODE 1]
    
    if (responseDecode == None):
        return None
    else:
        return json.loads(responseDecode)

#[CODE 3]
def getPostData(post, jsonResult, cnt):    
    title = post['title']
    description = post['description']
    link = post['link']
    
    jsonResult.append({'cnt':cnt, 'title':title, 'description': description})
    return    

#[CODE 0]
def main():
    node = 'blog'   # 크롤링 할 대상
    srcText = input('검색어를 입력하세요: ')
    cnt = 0
    jsonResult = []

    jsonResponse = getNaverSearch(node, srcText, 1, 100)  #[CODE 2]
    total = jsonResponse['total']
 
    while ((jsonResponse != None) and (jsonResponse['display'] != 0)):         
        for post in jsonResponse['items']:
            cnt += 1
            getPostData(post, jsonResult, cnt)  #[CODE 3]       
        
        start = jsonResponse['start'] + jsonResponse['display']
        jsonResponse = getNaverSearch(node, srcText, start, 100)  #[CODE 2]
       
    print('전체 검색 : %d 건' %total)
    
    with open('%s_naver_%s.json' % (srcText, node), 'w', encoding='utf8') as outfile:
        jsonFile = json.dumps(jsonResult,  indent=4, sort_keys=True,  ensure_ascii=False)
                        
        outfile.write(jsonFile)
        
    print("가져온 데이터 : %d 건" %(cnt))
    print ('%s_naver_%s.json SAVED' % (srcText, node))
    
if __name__ == '__main__':
    main()

 

 

공공데이터 API를 이용한 크롤링


 

1. 공공데이터포털(https://www.data.go.kr/) 접속

    공공데이터포털 접속 > 회원가입

 

2. 크롤링 대상 검색

    크롤링 하고싶은 대상 검색

 

3. Open API 탭에서 대상 선택

    대상 선택 > 활용신청 클릭

 

4. Open API 개발계정 신청

    활용목적 / 상세기능정보를 알맞게 적고, 라이선스 표시에 동의합니다.

    활용신청 클릭

 

 

5. Open API 개발계정 발급

    처리상태가 승인 상태가 되면 활용기간동안 사용할 수 있습니다.

    크롤링 할 때 인증키가 필요합니다.

 

6. Open API 사용방법 확인

    개발계정 발급 > 기본정보 > 상세보기를 통해 들어갈 수 있습니다.

    해당 API에서 사용하는 요청변수를 통해 크롤링합니다.

    크롤링 할 때, 서비스URL이 필요합니다.

 

7. 크롤링

    아래 코드를 실행하면 원하는 검색어를 입력 해 크롤링 할 수 있습니다.

    아래의 코드는출입국관광통계서비스를 대상으로 크롤링하는 코드입니다.

    크롤링 대상마다 다른 요청변수를 사용하고 개발계정 발급 > 기본정보 > 상세보기를 통해 알 수 있습니다.

import os
import sys
import urllib.request
import datetime
import time
import json
import pandas as pd


ServiceKey="[일반 인증키(Encoding)]"

#[CODE 1]
def getRequestUrl(url):    
    req = urllib.request.Request(url)    
    try: 
        response = urllib.request.urlopen(req)
        if response.getcode() == 200:
            print ("[%s] Url Request Success" % datetime.datetime.now())
            return response.read().decode('utf-8')
    except Exception as e:
        print(e)
        print("[%s] Error for URL : %s" % (datetime.datetime.now(), url))
        return None


#[CODE 2]
def getTourismStatsItem(yyyymm, national_code, ed_cd):    
    service_url = "[해당 서비스 URL]"
    parameters = "?_type=json&serviceKey=" + ServiceKey   #인증키
    parameters += "&YM=" + yyyymm
    parameters += "&NAT_CD=" + national_code
    parameters += "&ED_CD=" + ed_cd
    url = service_url + parameters
    
    retData = getRequestUrl(url)   #[CODE 1]
    
    if (retData == None):
        return None
    else:
         return json.loads(retData)

#[CODE 3]
def getTourismStatsService(nat_cd, ed_cd, nStartYear, nEndYear):
    jsonResult = []
    result = []
    natName=''
    dataEND = "{0}{1:0>2}".format(str(nEndYear), str(12)) #데이터 끝 초기화
    isDataEnd = 0 #데이터 끝 확인용 flag 초기화    
    
    for year in range(nStartYear, nEndYear+1):        
        for month in range(1, 13):
            if(isDataEnd == 1): break #데이터 끝 flag 설정되어있으면 작업 중지.
            yyyymm = "{0}{1:0>2}".format(str(year), str(month))            
            jsonData = getTourismStatsItem(yyyymm, nat_cd, ed_cd) #[CODE 2]
            
            if (jsonData['response']['header']['resultMsg'] == 'OK'):               
                # 입력된 범위까지 수집하지 않았지만, 더이상 제공되는 데이터가 없는 마지막 항목인 경우 -------------------
                if jsonData['response']['body']['items'] == '': 
                    isDataEnd = 1 #데이터 끝 flag 설정
                    dataEND = "{0}{1:0>2}".format(str(year), str(month-1))
                    print("데이터 없음.... \n 제공되는 통계 데이터는 %s년 %s월까지입니다."                          
                          %(str(year), str(month-1)))                    
                    break                
                #jsonData를 출력하여 확인......................................................
                print (json.dumps(jsonData, indent=4, 
                         sort_keys=True, ensure_ascii=False))          
                natName = jsonData['response']['body']['items']['item']['natKorNm']
                natName = natName.replace(' ', '')
                num = jsonData['response']['body']['items']['item']['num']
                ed = jsonData['response']['body']['items']['item']['ed']
                print('[ %s_%s : %s ]' %(natName, yyyymm, num))
                print('----------------------------------------------------------------------')                
                jsonResult.append({'nat_name': natName, 'nat_cd': nat_cd,
                                 'yyyymm': yyyymm, 'visit_cnt': num})
                result.append([natName, nat_cd, yyyymm, num])
                
    return (jsonResult, result, natName, ed, dataEND)

#[CODE 0]
def main():
    jsonResult = []
    result = []
    natName=''
    print("<< 국내 입국한 외국인의 통계 데이터를 수집합니다. >>")
    nat_cd = input('국가 코드를 입력하세요(중국: 112 / 일본: 130 / 미국: 275) : ')
    nStartYear =int(input('데이터를 몇 년부터 수집할까요? : '))
    nEndYear = int(input('데이터를 몇 년까지 수집할까요? : '))
    ed_cd = "E"     #E : 방한외래관광객, D : 해외 출국
    
    jsonResult, result, natName, ed, dataEND =getTourismStatsService(nat_cd,
                                            ed_cd, nStartYear, nEndYear) #[CODE 3]

    if (natName=='') : #URL 요청은 성공하였지만, 데이터 제공이 안된 경우
        print('데이터가 전달되지 않았습니다. 공공데이터포털의 서비스 상태를 확인하기 바랍니다.')
    else:
        #파일저장 1 : json 파일       
        with open('./%s_%s_%d_%s.json' % (natName, ed, nStartYear, dataEND), 'w', 
                    encoding='utf8') as outfile:
            jsonFile  = json.dumps(jsonResult, indent=4, sort_keys=True, ensure_ascii=False)
            outfile.write(jsonFile)
        #파일저장 2 : csv 파일   
        columns = ["입국자국가", "국가코드", "입국연월", "입국자 수"]
        result_df = pd.DataFrame(result, columns = columns)
        result_df.to_csv('./%s_%s_%d_%s.csv' % (natName, ed, nStartYear, dataEND),
                    index=False, encoding='cp949')
    
if __name__ == '__main__':
    main()

 

 

 

[참조]

데이터 과학 기반의 파이썬 빅데이터 분석 - 한빛 아카데미

인하공업전문대학 컴퓨터정보과