MiniProject(NaverOpenAPI 뉴스검색)

오윤범·2023년 3월 8일
0

MiniProject

목록 보기
1/8

MiniProject / NaverAPI 뉴스검색

1) QtDesigner을 통한 ui 작성



2) Naver 개발자 센터에서 OpenAPI 받아오기

https://developers.naver.com/main

Client-ID / Client-Secret 발급


3) NaverApi.py 작성(OpenApi를 통해 데이터 전달받음)


#NaverApi 클래스 - OpenApi : 인터넷을 통해 데이터 전달받음
from urllib.request import Request,urlopen
from urllib.parse import quote
import datetime
import json
class NaverApi:
    # 생성자
    def __init__(self) -> None:
        print(f'[{datetime.datetime.now()}] Naver API Search 생성')

    # NaverAPI를 요청
    def getRequestUrl(self,url):
        req=Request(url)
        #NaverAPI 개인 인증
        req.add_header('X-Naver-Client-ID','kflq_q32Q1Q3tf46AKDF')
        req.add_header('X-Naver-Client-Secret','kpYx2Ai7O5')
        try:
            res = urlopen(req) #요청결과 바로 반환
            if res.getcode() ==200: # reponse OK
                print(f'[{datetime.datetime.now()}] NaverAPI 요청 성공')
                return res.read().decode('utf-8') #사용자가 알아볼 수 있게 반환
            else:
                print(f'[{datetime.datetime.now()}]NaverAPI 요청 실패')
                return None

        except Exception as e:
            print(f'[{datetime.datetime.now()}] 예외발생 : {e}')
            return None

    # 호출
    def getNaverSearch(self,node,search,start,display):
        base_url='https://openapi.naver.com/v1/search'
        node_url=f'/{node}.json'
        params=f'?query={quote(search)}&start={start}&display={display}'

        url=base_url+node_url+params #전체 url

        retData=self.getRequestUrl(url)

        if retData==None : return None
        else : return json.loads(retData) # json 으로 return

4) NaverSearchApp.py 작성(NaverApiSearch.ui의 동작을 설정)


# Qt Designer 디자인 사용
import sys
from PyQt5 import uic
from PyQt5.QtWidgets import *
from NaverApi import * #만들어둔 NaverApi 클래스 사용
import webbrowser #웹브라우저 모듈(링크연결 등)
from PyQt5.QtGui import *

# NaverApiSearch.ui의 동작을 설정하는것

class qtApp(QWidget):
    def __init__(self):
        super().__init__()
        uic.loadUi('./PyQt_Practice/NaverApiSearch.ui',self)
        self.setWindowIcon(QIcon('./PyQt_practice/newspaper.png'))
        # 검색버튼 클릭시그널 / 슬롯함수
        self.btnSearch.clicked.connect(self.btnSearchClicked)
        # 텍스트박스에 검색어 입력 후 엔터 처리
        self.txtSearch.returnPressed.connect(self.txtSearchReturned)
        # 링크 더블클릭
        self.tblResult.doubleClicked.connect(self.tblResultDoubleClicked) 

    def tblResultDoubleClicked(self): #링크 더블클릭
        #row=self.tblResult.currentIndex().row()
        #column=self.tblResult.currentIndex().column()
        # print(row,column)
        selected=self.tblResult.currentRow() #선택한 뉴스 행
        url=self.tblResult.item(selected,1).text() #뉴스 기사 링크 뽑아냄 
        webbrowser.open(url) #해당 링크 연결

    def txtSearchReturned(self): # 검색어 입력 후 엔터쳤을 때 처리 부분
        self.btnSearchClicked()

    def btnSearchClicked(self):
        search=self.txtSearch.text()

        if search=='':
            QMessageBox.warning(self,'경고','검색어를 입력하세요')
            return
        else:
            api=NaverApi() # NaverApi 클래스 객체 생성
            node='news'
            display=100 #검색결과 100개만 뽑아오겠다는 의미

            result=api.getNaverSearch(node,search,1,display)
            #print(result)

            #QTableWidget에 출력하기
            items=result['items'] # json전체 결과 중 items 아래 배열만 잘라오는 의미 
            self.makeTable(items) # 테이블위젯에 데이터들을 할당한다


    # 테이블 위젯에 데이터 표시
    def makeTable(self,items) -> None:
        self.tblResult.setSelectionMode(QAbstractItemView.SingleSelection)# 단일선택모드
        self.tblResult.setColumnCount(2)
        self.tblResult.setRowCount(len(items)) #display값으로 설정하여 나온 결과값 100개 행 생성
        self.tblResult.setHorizontalHeaderLabels(['기사제목','뉴스링크']) #행 제목 변경
        self.tblResult.setColumnWidth(0,310)
        self.tblResult.setColumnWidth(1,260)
        self.tblResult.setEditTriggers(QAbstractItemView.NoEditTriggers) #컬럼데이터 수정금지

        for i,post in enumerate(items): #0,뉴스... / 1,뉴스... 형태
            title=self.replaceHtmlTab(post['title']) # HTMl 특수문자 변환
            originallink=post['originallink']
            #setItem(행,열,넣을데이터)
            self.tblResult.setItem(i,0,QTableWidgetItem(title))
            self.tblResult.setItem(i,1,QTableWidgetItem(originallink))

    # HTMl 특수문자 변환하는 함수
    def replaceHtmlTab(self,sentence) -> str: #->str :함수 끝에서 str을 반환한다는뜻
        #제목에 그대로 출력되는 HTML 기호들을 가독성 좋게 변환
        result=sentence.replace('&lt;', '<').replace('&gt;', '>').replace('<b>', 
        '').replace('</b>', '').replace('&apos;', "'").replace('&quot;', '"') 
        return result

if __name__=='__main__':
    app=QApplication(sys.argv)
    ex=qtApp()
    ex.show()
    sys.exit(app.exec_())
  • 결과화면




  • 소스코드(Github)


https://github.com/OHYUNBEOM/MiniProjects/tree/main/part1

기술스택

1. Python
2. PyQt
3. Qt Designer
  • 어려웠던 부분


  1. NaverAPi.py에서 NaverAPi를 요청하고 실제로 호출한 함수 getNaverSearch에서 전체 url을 json형태로 재변환하는것
  2. NaverSearchApp.py에서 NaverApiSearch.ui 가 하는 동작을 해당 동작에 맞게 함수로 구현해 주는것
  3. json파일로 받아오는 result를 ui에 뿌려줄 때 가독성이 좋을 수 있게 replaceHtmlTab 함수를 통해 HTML 기호를 변환하는것

0개의 댓글