diff --git a/config.ini b/config.ini deleted file mode 100644 index c9c0c9a..0000000 --- a/config.ini +++ /dev/null @@ -1,18 +0,0 @@ -[Settings] -maxweightset = 10 -maxlengthset = 100 -maxvolumeset = 155 -addfeeinterval = 6 -addfeesetting = 3 -addfee = 2000 -fontsize = 14 -weightinterval = 0.5 -setsavesetting = True -favoritedelv = - -[Kipris] -use_kipris = True -usage_mode = api -api_key = X9Tz3JqC/JcCwxnNewA6qdloIN6QFIitVBgS1a2KVDYk1AmddaDTvzr6+t3dyLZV3gh2TPXdNhxsRQwaKP673Q== -set_status = ['°ÅÀý', 'µî·Ï'] - diff --git a/config.json b/config.json index 302b194..f215ed7 100644 --- a/config.json +++ b/config.json @@ -6,19 +6,17 @@ "addFeeInterval": 5, "addFeeSetting": 20, "addFee": 1000, - "fontSize": 10, + "fontSize": 12, "weightInterval": 0.5, "setSaveSetting": true, "favoriteDelv": "\ub178\ube60\uafb8\ud574\uc6b4(\ubc30\uc1a1\ube44)" }, "Kipris": { "use_kipris": true, - "usage_mode": "web", - "api_key": "", + "usage_mode": "api", + "api_key": "X9Tz3JqC/JcCwxnNewA6qdloIN6QFIitVBgS1a2KVDYk1AmddaDTvzr6+t3dyLZV3gh2TPXdNhxsRQwaKP673Q==", "set_status": [ - "\ub4f1\ub85d", - "\ucde8\ud558", - "\ud3ec\uae30" + "\ub4f1\ub85d" ] } } \ No newline at end of file diff --git a/delv.py b/delv.py index 8fafa46..cd16ea2 100644 --- a/delv.py +++ b/delv.py @@ -14,9 +14,9 @@ from src.kipris_settingUI import SettingsDialog from src.kipris_api_from_publicdata import Kipris_API # from src.kipris_web_from_playwright import Kipris_WEB from src.kiprisThread import * -from src.search_display import TrademarkSearchDisplay +# from src.search_display import TrademarkSearchDisplay from src.result_widget import ResultWidget - +from src.currencyInfo import ExchangeRateScraper def minimize_console(): """ 콘솔 ì°½ì„ ìµœì†Œí™”í•˜ëŠ” 함수 """ @@ -40,7 +40,8 @@ class DeliveryFeeCalculator(QtWidgets.QWidget): self.asyncWorker = None self.search_keyword = None self.set_status =[] - + self.web_scraper = None # ì›¹ë°©ì‹ Playwright ê°ì²´ 미리 초기화 + self.currentURL = "" self.config_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'config.json') self.maxWeightSet = 25 @@ -58,12 +59,12 @@ class DeliveryFeeCalculator(QtWidgets.QWidget): self.addFeeSetting = 20 self.addFeeInterval = 5 - self.setUSD = None self.setCNY = None - self.searchDisplay = TrademarkSearchDisplay() + self.currentCurrency = None + # self.searchDisplay = TrademarkSearchDisplay() self.searchDisplayWidget = ResultWidget() - + self.currencyInfoObject = ExchangeRateScraper() self.favoriteDelv = "" @@ -108,6 +109,14 @@ class DeliveryFeeCalculator(QtWidgets.QWidget): } self.settingDialog = SettingsDialog(parent=self, initial_settings=self.user_settings) + currencis = ['USD','CNY'] + self.currencyInfoObject.getCurrency(currencis) + self.setUSD = self.currencyInfoObject.currencyInfo['USD']['basePrice'] + logger.debug(f"setUSD : {self.setUSD}") + self.setCNY = self.currencyInfoObject.currencyInfo['CNY']['basePrice'] + logger.debug(f"setCNY : {self.setCNY}") + self.currentCurrency = self.setCNY + def saveSettings(self): """ ì„¤ì •ì„ JSON 파ì¼ì— 저장합니다. """ try: @@ -220,7 +229,7 @@ class DeliveryFeeCalculator(QtWidgets.QWidget): # self.api_key = self.config.get('Kipris', 'api_key', fallback="") # self.set_status = self.config.get('Kipris', 'set_status', fallback="[등ë¡]") - # # print(f"use_kipris : {self.use_kipris}, usage_mode : {self.usage_mode}, api_key : {self.api_key}") + # # logger.debug(f"use_kipris : {self.use_kipris}, usage_mode : {self.usage_mode}, api_key : {self.api_key}") # except Exception as e: # logger.error(f"ì„¤ì •ì„ ë¶ˆëŸ¬ì˜¤ëŠ” 중 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤: {e}", exc_info=True) @@ -283,17 +292,17 @@ class DeliveryFeeCalculator(QtWidgets.QWidget): if keyword: if keyword and keyword not in self.history: # ì¤‘ë³µëœ ê²€ìƒ‰ì–´ê°€ 아니면 추가 self.history.append(keyword) - print(f"검색어 [{keyword}] ížˆìŠ¤í† ë¦¬ì— ì¶”ê°€") + logger.debug(f"검색어 [{keyword}] ížˆìŠ¤í† ë¦¬ì— ì¶”ê°€") def load_history(self): try: with open("search_history.json", "r") as file: self.history = json.load(file) - print(f"self.history file loaded{self.history}") + logger.debug(f"self.history file loaded{self.history}") except (FileNotFoundError, json.JSONDecodeError): self.history = [] - print(f"self.history{self.history}") + logger.debug(f"self.history{self.history}") def save_history(self): with open("search_history.json", "w") as file: @@ -599,7 +608,7 @@ class DeliveryFeeCalculator(QtWidgets.QWidget): self.kipris_layout = QtWidgets.QHBoxLayout(self.kiprisWidget) self.kiprisWidget.setLayout(self.kipris_layout) self.kiprisWidget.setVisible(False) - self.kipris_label = QtWidgets.QLabel("키프리스 검색") + self.kipris_label = QtWidgets.QLabel(f"키프리스 검색") self.kipris_edit = QtWidgets.QLineEdit() self.kipris_btn = QtWidgets.QPushButton("검색") self.kipris_btn.clicked.connect(self.kipris_btn_clicked) @@ -620,8 +629,8 @@ class DeliveryFeeCalculator(QtWidgets.QWidget): self.addInfo_vlayout = QtWidgets.QVBoxLayout(self.addInfoWidget) self.addInfo_h1layout = QtWidgets.QHBoxLayout() self.addInfo_h2layout = QtWidgets.QHBoxLayout() - self.addInfo_vlayout.addLayout(self.addInfo_h1layout) self.addInfo_vlayout.addLayout(self.addInfo_h2layout) + self.addInfo_vlayout.addLayout(self.addInfo_h1layout) self.addInfoWidget.setLayout(self.addInfo_vlayout) self.addInfoWidget.setVisible(True) self.setUSD_label = QtWidgets.QLabel(f"[{self.setUSD}]USD/KRW") @@ -647,9 +656,11 @@ class DeliveryFeeCalculator(QtWidgets.QWidget): self.addInfo2_btn.clicked.connect(self.addInfo2_btn_clicked) self.addInfo_h2layout.addWidget(self.addInfo2_btn) self.addInfo3_btn = QtWidgets.QPushButton("타ëƒì–´ë¡") + self.addInfo3_btn.setEnabled(False) self.addInfo3_btn.clicked.connect(self.addInfo3_btn_clicked) self.addInfo_h2layout.addWidget(self.addInfo3_btn) self.addInfo4_btn = QtWidgets.QPushButton("딥러ë‹ë²ˆì—­") + self.addInfo4_btn.setEnabled(False) self.addInfo4_btn.clicked.connect(self.addInfo4_btn_clicked) self.addInfo_h2layout.addWidget(self.addInfo4_btn) # self.addInfo_layout.setStretch(0,3) @@ -659,6 +670,35 @@ class DeliveryFeeCalculator(QtWidgets.QWidget): self.setting_layout.addWidget(self.addInfoWidget) # self.addInfoWidget 설정 ë ˆì´ì•„ì›ƒì— ì¶”ê°€ + # ê²½ë™íƒë°° 무게기준 ì¡°ì • 스핀박스 + self.changeCurreny_btn = QtWidgets.QPushButton("CNY/KRW") + self.changeCurreny_btn.clicked.connect(self.changeCurreny_btn_clicked) + + self.calcCurrency_label = QtWidgets.QLabel("") + self.calcCurrency_label.setText(" ì›") + self.calcCurrency_label.setAlignment(QtCore.Qt.AlignCenter) + calcCurrency_label_font = QFont() + calcCurrency_label_font.setBold(True) # 굵게 + calcCurrency_label_font.setUnderline(True) # 밑줄 + calcCurrency_label_font.setWeight(16) # í°íЏí¬ê¸° + self.calcCurrency_label.setFont(calcCurrency_label_font) + + self.currency_calc_box = QtWidgets.QSpinBox() + self.currency_calc_box.setRange(0, 1000000) + self.currency_calc_box.setSingleStep(10) + self.currency_calc_box.setValue(100) + self.currency_calc_box.setSuffix(" CNY") + self.currency_calc_box.setAlignment(QtCore.Qt.AlignRight) # ê°€ìš´ë° ì •ë ¬ + self.currency_calc_box.valueChanged.connect(self.calcCurrency) + self.currency_calc_box_layout = self.create_label_and_spin("환율", self.currency_calc_box) + self.currency_calc_box_layout.addWidget(self.calcCurrency_label) + self.currency_calc_box_layout.addWidget(self.changeCurreny_btn) + self.currency_calc_box_layout.setStretch(0,2) + self.currency_calc_box_layout.setStretch(1,4) + self.currency_calc_box_layout.setStretch(2,4) + self.currency_calc_box_layout.setStretch(3,2) + self.setting_layout.addLayout(self.currency_calc_box_layout) + # í•­ìƒ ìœ„ì— í† ê¸€ 스위치 self.alwaysOnTopSwitch = ToggleSwitch(self.setting_frame) self.alwaysOnTopSwitch.move(10, 10) @@ -694,17 +734,17 @@ class DeliveryFeeCalculator(QtWidgets.QWidget): # if current_type is not target_type: # # 기존 ê°ì²´ê°€ 다른 타입ì´ë©´ 삭제하고 새로 ìƒì„± - # print(f"기존 {self.kiprisAPI} ê°ì²´ë¥¼ 삭제하고 새 ê°ì²´ë¥¼ ìƒì„±í•©ë‹ˆë‹¤.") + # logger.debug(f"기존 {self.kiprisAPI} ê°ì²´ë¥¼ 삭제하고 새 ê°ì²´ë¥¼ ìƒì„±í•©ë‹ˆë‹¤.") # self.kiprisAPI.close_Kipris() # 기존ê°ì²´ 리소스 정리 # del self.kiprisAPI # 기존 ê°ì²´ 참조 제거 # self.kiprisAPI = target_type(self.api_key) # 새 ê°ì²´ ìƒì„± - # print(f"{self.usage_mode.upper()} ë°©ì‹ kiprisAPI ê°ì²´ ìƒì„±: {self.kiprisAPI}") + # logger.debug(f"{self.usage_mode.upper()} ë°©ì‹ kiprisAPI ê°ì²´ ìƒì„±: {self.kiprisAPI}") # else: - # print(f"ê¸°ì¡´ì— ì ì ˆí•œ {self.kiprisAPI} ê°ì²´ê°€ ì´ë¯¸ 존재합니다.") + # logger.debug(f"ê¸°ì¡´ì— ì ì ˆí•œ {self.kiprisAPI} ê°ì²´ê°€ ì´ë¯¸ 존재합니다.") # else: # # ê°ì²´ê°€ 없으면 새로 ìƒì„± # self.kiprisAPI = Kipris_API(self.api_key) if self.usage_mode == 'api' else Kipris_WEB(self.api_key) - # print(f"{self.usage_mode.upper()} ë°©ì‹ kiprisAPI ê°ì²´ ìƒì„±: {self.kiprisAPI}") + # logger.debug(f"{self.usage_mode.upper()} ë°©ì‹ kiprisAPI ê°ì²´ ìƒì„±: {self.kiprisAPI}") def initSettings_for_kipris(self): if self.kiprisAPI: @@ -714,7 +754,7 @@ class DeliveryFeeCalculator(QtWidgets.QWidget): if current_type is not target_type: # 기존 ê°ì²´ê°€ 다른 타입ì´ë©´ 삭제하고 새로 ìƒì„± - print(f"기존 {self.kiprisAPI} ê°ì²´ë¥¼ 삭제하고 새 ê°ì²´ë¥¼ ìƒì„±í•©ë‹ˆë‹¤.") + logger.debug(f"기존 {self.kiprisAPI} ê°ì²´ë¥¼ 삭제하고 새 ê°ì²´ë¥¼ ìƒì„±í•©ë‹ˆë‹¤.") if isinstance(self.kiprisAPI, AsyncWebSearchWorker): self.kiprisAPI.deleteLater() # 비ë™ê¸° 작업ìžëŠ” Qt ê°ì²´ë¡œ 관리ë˜ë¯€ë¡œ deleteLater 사용 self.kiprisAPI = None @@ -722,18 +762,20 @@ class DeliveryFeeCalculator(QtWidgets.QWidget): self.kiprisAPI = Kipris_API(self.api_key) # 새 ê°ì²´ ìƒì„± else: web_scraper = WebScraper() # WebScraper ì¸ìŠ¤í„´ìŠ¤ ìƒì„± - self.kiprisAPI = AsyncWebSearchWorker(web_scraper, "") # 초기 키워드는 비워ë‘기 - print(f"{self.usage_mode.upper()} ë°©ì‹ kiprisAPI ê°ì²´ ìƒì„±: {self.kiprisAPI}") + self.web_scraper = web_scraper + self.kiprisAPI = AsyncWebSearchWorker(self.web_scraper, "") # 초기 키워드는 비워ë‘기 + logger.debug(f"{self.usage_mode.upper()} ë°©ì‹ kiprisAPI ê°ì²´ ìƒì„±: {self.kiprisAPI}") else: - print(f"ê¸°ì¡´ì— ì ì ˆí•œ {self.kiprisAPI} ê°ì²´ê°€ ì´ë¯¸ 존재합니다.") + logger.debug(f"ê¸°ì¡´ì— ì ì ˆí•œ {self.kiprisAPI} ê°ì²´ê°€ ì´ë¯¸ 존재합니다.") else: # ê°ì²´ê°€ 없으면 새로 ìƒì„± if self.usage_mode == 'api': self.kiprisAPI = Kipris_API(self.api_key) else: web_scraper = WebScraper() # WebScraper ì¸ìŠ¤í„´ìŠ¤ ìƒì„± + self.web_scraper = web_scraper self.kiprisAPI = AsyncWebSearchWorker(web_scraper, "") # 초기 키워드는 비워ë‘기 - print(f"{self.usage_mode.upper()} ë°©ì‹ kiprisAPI ê°ì²´ ìƒì„±: {self.kiprisAPI}") + logger.debug(f"{self.usage_mode.upper()} ë°©ì‹ kiprisAPI ê°ì²´ ìƒì„±: {self.kiprisAPI}") def addInfo1_btn_clicked(self): pass @@ -761,6 +803,7 @@ class DeliveryFeeCalculator(QtWidgets.QWidget): if self.use_kipris: self.kiprisWidget.setVisible(True) self.initSettings_for_kipris() + self.kipris_label.setText(f"키프리스 검색({self.usage_mode})") else: self.kiprisWidget.setVisible(False) @@ -1061,6 +1104,26 @@ class DeliveryFeeCalculator(QtWidgets.QWidget): self.addFeeInterval = value self.updateDeliveryFee() + def changeCurreny_btn_clicked(self): + selected = self.changeCurreny_btn.text() + if selected == 'CNY/KRW': + self.currency_calc_box.setSuffix(" USD") + self.changeCurreny_btn.setText('USD/KRW') + self.currentCurrency = self.setUSD + else: + self.currency_calc_box.setSuffix(" CNY") + self.changeCurreny_btn.setText('CNY/KRW') + self.currentCurrency = self.setCNY + self.calcCurrency(100) + + def calcCurrency(self,value): + result = value * self.currentCurrency + result = round(result,0) + result = '{0:,}'.format(result) + # logger.debug(f"result{result}") + # logger.debug(f"round(result,2){str(round(result,0))}") + self.calcCurrency_label.setText(result+' ì›') + def isSaveSetting(self, state): if state: self.setSaveSetting = True @@ -1075,10 +1138,10 @@ class DeliveryFeeCalculator(QtWidgets.QWidget): logger.debug(f"키프리스 검색버튼 í´ë¦­ : 키워드 = [{self.search_keyword}]") # result = self.kiprisAPI.run(self.search_keyword, self.set_status) - # print(f"result {result}") + # logger.debug(f"result {result}") if self.search_keyword.strip(): # 검색어가 비어있지 ì•Šì€ ê²½ìš°ì—ë§Œ 검색 수행 - print(f"검색 í˜¸ì¶œë°©ì‹ : {self.usage_mode}") + logger.debug(f"검색 í˜¸ì¶œë°©ì‹ : {self.usage_mode}") if self.usage_mode == 'web': self.handle_search_for_web(self.search_keyword) if self.usage_mode == 'api': @@ -1089,16 +1152,17 @@ class DeliveryFeeCalculator(QtWidgets.QWidget): if self.asyncWorker: # ê¸°ì¡´ì— ë¹„ë™ê¸° 작업ìžê°€ 존재한다면 self.asyncWorker.thread.quit() # 기존 스레드 종료 - print(f"키프리스 검색버튼 í´ë¦­ : 키워드 = [{keyword}]") + logger.debug(f"키프리스 검색버튼 í´ë¦­ : 키워드 = [{keyword}]") self.asyncWorker = AsyncWebSearchWorker(keyword, self.set_status) # 새 비ë™ê¸° ìž‘ì—…ìž ìƒì„± self.asyncWorker.finished.connect(self.display_results_for_web) # 완료 시그ë„ì„ ê²°ê³¼ 표시 í•¨ìˆ˜ì— ì—°ê²° self.asyncWorker.start() # 비ë™ê¸° 작업 시작 - print("비ë™ê¸° 검색 시작") + logger.debug("비ë™ê¸° 검색 시작") def display_results_for_web(self, result, elapsed_time): - print(f"result : {result}") - - self.searchDisplayWidget.show_results(result) + # logger.debug(f"result : {result}") + searchType = 'web' + logger.debug(f"display_results_for_web - currentURL : {self.web_scraper.currentURL}") + self.searchDisplayWidget.show_results(result, searchType, elapsed_time, self.web_scraper.currentURL) # self.searchDisplay.display_web_results(result, elapsed_time) # self.searchDisplay.show() @@ -1113,28 +1177,31 @@ class DeliveryFeeCalculator(QtWidgets.QWidget): if self.searchThread is not None and self.searchThread.isRunning(): self.searchThread.quit() # ì´ì „ 스레드가 실행 중ì´ë¼ë©´ 안전하게 종료 - print("기존 쓰레드가 존재하므로 기존 쓰레드 종료") - print(f"키프리스 검색버튼 í´ë¦­ : 키워드 = [{keyword}]") + logger.debug("기존 쓰레드가 존재하므로 기존 쓰레드 종료") + logger.debug(f"키프리스 검색버튼 í´ë¦­ : 키워드 = [{keyword}]") worker = APISearchWorker(self.kiprisAPI, keyword, self.set_status) # worker = SearchWorker(self.kiprisAPI, keyword, self.set_status) - print("워커 ìƒì„±") + logger.debug("워커 ìƒì„±") self.searchThread = SearchThread(worker) - print("쓰레드 ìƒì„±") + logger.debug("쓰레드 ìƒì„±") worker.finished.connect(self.display_results_for_api) self.searchThread.finished.connect(self.clear_thread_reference) self.searchThread.start_search() - print("검색 시작") + logger.debug("검색 시작") def clear_thread_reference(self): # 스레드 종료 후 참조를 제거하여 ë‹¤ìŒ ê²€ìƒ‰ì„ ìœ„í•´ 준비 self.searchThread = None def display_results_for_api(self, result, elapsed_time): + searchType = 'api' + logger.debug(f"display_results_for_api result: {result}") + self.searchDisplayWidget.show_results(result, searchType, elapsed_time) message = f"검색 ê²°ê³¼ : {result}\nê²€ìƒ‰ì— ê±¸ë¦° 시간: {elapsed_time:.1f}ì´ˆ" - QtWidgets.QMessageBox.information(self, "Search Results", message) + # QtWidgets.QMessageBox.information(self, "Search Results", message) def reset_action(self): self.lengthInput.setValue(1) @@ -1171,7 +1238,7 @@ if __name__ == '__main__': minimize_console() app = QtWidgets.QApplication(sys.argv) - logger = setup_logger('default_logger', 'delivery_calc.log', level=logging.INFO) + logger = setup_logger('default_logger', 'delivery_calc.log', level=logging.DEBUG) ex = DeliveryFeeCalculator(logger) ex.show() sys.exit(app.exec_()) diff --git a/delv.xlsx b/delv.xlsx index 12d1379..59dfc16 100644 Binary files a/delv.xlsx and b/delv.xlsx differ diff --git a/delv_py.spec b/delv_py.spec index 1313aee..038af49 100644 --- a/delv_py.spec +++ b/delv_py.spec @@ -3,12 +3,10 @@ a = Analysis( ['delv.py'], - pathex=['H:\\py\\delvfee'], + pathex=[], binaries=[], datas=[], - hiddenimports=[ - 'sip', 'jinja2' - ], + hiddenimports=[], hookspath=[], hooksconfig={}, runtime_hooks=[], diff --git a/src/Kiprismain.py b/src/Kiprismain.py index 125ab77..558b358 100644 --- a/src/Kiprismain.py +++ b/src/Kiprismain.py @@ -3,7 +3,10 @@ from PyQt5.QtWidgets import QApplication, QMessageBox, QSizePolicy, QWidget, QVB from PyQt5.QtGui import QPixmap from PyQt5.QtCore import Qt, QByteArray, QBuffer, QIODevice from kipris_web_from_playwright import WebScraper +import logging +# 로거 ì¸ìŠ¤í„´ìŠ¤ 가져오기 +logger = logging.getLogger('default_logger') class MainApp(QWidget): def __init__(self): super().__init__() @@ -163,7 +166,7 @@ class MainApp(QWidget): self.results_widget.show() except Exception as e: - print(f"Error displaying results: {e}") + logger.debug(f"Error displaying results: {e}") def close_results_widget(self): diff --git a/src/currencyInfo.py b/src/currencyInfo.py new file mode 100644 index 0000000..b05f4f1 --- /dev/null +++ b/src/currencyInfo.py @@ -0,0 +1,63 @@ +import requests +import logging + +# 로거 ì¸ìŠ¤í„´ìŠ¤ 가져오기 +logger = logging.getLogger('default_logger') + +class ExchangeRateScraper: + def __init__(self): + super().__init__() + + self.currencyInfo = {} + + self.initUI() + + def initUI(self): + pass + + + def getCurrency(self, currencies): + headers = { + 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36' + } + + # ë™ì ìœ¼ë¡œ URL 구성하기 + codes = ','.join([f'FRX.KRW{currency}' for currency in currencies]) + url = f'https://quotation-api-cdn.dunamu.com/v1/forex/recent?codes={codes}' + + # url = 'https://quotation-api-cdn.dunamu.com/v1/forex/recent?codes=FRX.KRWUSD,FRX.KRWCNY' + response = requests.get(url, headers=headers) + + if response.status_code == 200: + exchange_rates = response.json() + for rate in exchange_rates: + currency_code = rate['currencyCode'] + if currency_code in currencies: + # 해당 통화 ì •ë³´ 저장 + self.currencyInfo[currency_code] = { + 'basePrice': rate['basePrice'], + 'modifiedAt': rate['modifiedAt'], + 'provider': rate['provider'] + } + logger.debug("Exchange rates updated.") + else: + logger.error("Failed to retrieve data") + + + def get_Currency_Info(self, currency): + # 특정 통화 ì •ë³´ 출력 메서드 + if currency in self.currencyInfo: + info = self.currencyInfo[currency] + + logger.debug(f"Currency: {currency}") + logger.debug(f"Base Price: {info['basePrice']}") + logger.debug(f"Modified At: {info['modifiedAt']}") + logger.debug(f"Provider: {info['provider']}") + else: + logger.debug(f"No data available for {currency}") + +# # í´ëž˜ìФ 메서드 사용 예제 +# scraper = ExchangeRateScraper() +# scraper.getCurrency(['USD', 'CNY']) # USD와 CNY 환율 정보를 요청 +# scraper.get_Currency_Info('USD') +# scraper.get_Currency_Info('CNY') diff --git a/src/kiprisThread.py b/src/kiprisThread.py index 7f8f92f..7492168 100644 --- a/src/kiprisThread.py +++ b/src/kiprisThread.py @@ -1,9 +1,12 @@ from PyQt5.QtCore import QThread, pyqtSignal, QObject import time from src.web_scraper_async import * +import logging +# 로거 ì¸ìŠ¤í„´ìŠ¤ 가져오기 +logger = logging.getLogger('default_logger') class APISearchWorker(QObject): - finished = pyqtSignal(list, float) + finished = pyqtSignal(dict, float) def __init__(self, kiprisObject, keyword, set_status): super().__init__() @@ -13,9 +16,9 @@ class APISearchWorker(QObject): def run(self): start_time = time.time() # 검색 시작 시간 - print(f"Search keyword : [{self.keyword}], self.set_status : [{self.set_status}]") + logger.debug(f"Search keyword : [{self.keyword}], self.set_status : [{self.set_status}]") result = self.kiprisObject.run(self.keyword, self.set_status) - print(f"Search finished | result \n [{result}]") + logger.debug(f"Search finished | result \n {result}") elapsed_time = time.time() - start_time # 경과 시간 계산 self.finished.emit(result, elapsed_time) @@ -36,7 +39,7 @@ class SearchThread(QThread): def handle_finished(self, result, elapsed_time): # 검색 ìž‘ì—…ì´ ì™„ë£Œë˜ë©´ ì´ ì‹œê·¸ë„ì´ ë°œìƒí•©ë‹ˆë‹¤. - print(f"Search finished : [{elapsed_time}]ì´ˆ 경과") + logger.debug(f"Search finished : [{elapsed_time}]ì´ˆ 경과") class AsyncWebSearchWorker(QObject): @@ -68,7 +71,7 @@ class AsyncWebSearchWorker(QObject): elapsed_time = time.time() - self.start_time # 소요 시간 계산 self.finished.emit(result, elapsed_time) # 작업 완료 신호 전송 except Exception as e: - print(f"Error in AsyncWebSearchWorker: {e}") + logger.debug(f"Error in AsyncWebSearchWorker: {e}") self.finished.emit(None, 0) # ì—러 ë°œìƒ ì‹œ None 전송 finally: await self.scraper.close_Kipris() # 리소스 정리 diff --git a/src/kipris_api_from_publicdata.py b/src/kipris_api_from_publicdata.py index d35755c..6f48205 100644 --- a/src/kipris_api_from_publicdata.py +++ b/src/kipris_api_from_publicdata.py @@ -1,11 +1,17 @@ import xml.etree.ElementTree as ET -import requests +import requests, json +import logging + +# 로거 ì¸ìŠ¤í„´ìŠ¤ 가져오기 +logger = logging.getLogger('default_logger') class Kipris_API: def __init__(self, apikey=None): self.url = 'http://kipo-api.kipi.or.kr/openapi/service/trademarkInfoSearchService/getWordSearch' self.apikey = apikey - self.results = [] + self.results = {} + filename = 'categories.json' + self.category_description = self.load_category_descriptions(filename) def fetch_and_decode(self, params): # API 요청 ë° ì‘답 받기 @@ -14,7 +20,7 @@ class Kipris_API: decoded_data = response.content.decode('utf-8') return decoded_data except Exception as e: - print(f"키프리스 요청 중 ì—ëŸ¬ë°œìƒ : {e}") + logger.error(f"키프리스 요청 중 ì—ëŸ¬ë°œìƒ : {e}") def parse_xml(self, xml_data, status): # XML ë°ì´í„° 파싱 @@ -24,10 +30,15 @@ class Kipris_API: status_published = 0 # 'body/items/item' ê²½ë¡œì— ë§žì¶° 'item' 태그를 순회하면서 필요한 ë°ì´í„° 추출 - for item in root.findall('.//body/items/item'): + for i, item in enumerate(root.findall('.//body/items/item')): total_items += 1 application_status = item.find('applicationStatus').text if item.find('applicationStatus') is not None else None + product_category = item.find('classificationCode').text if item.find('classificationCode') is not None else None + if product_category: + category_desc = self.add_category_description(product_category) if product_category else "No category description" + else: + category_desc = None # ê° ìƒíƒœì˜ 개수를 카운트 if application_status == "등ë¡": status_registered += 1 @@ -36,7 +47,8 @@ class Kipris_API: # if application_status in ["등ë¡", "공개"]: if application_status in status: # status는 self.set_status 리스트를 참조 - result = { + + self.results[f"result_{i+1}"] = { "index_no": item.find('indexNo').text if item.find('indexNo') is not None else None, "application_number": item.find('applicationNumber').text if item.find('applicationNumber') is not None else None, "application_date": item.find('applicationDate').text if item.find('applicationDate') is not None else None, @@ -51,14 +63,16 @@ class Kipris_API: "big_drawing_url": item.find('bigDrawing').text if item.find('bigDrawing') is not None else None, "full_text": item.find('fullText').text if item.find('fullText') is not None else None, "application_status": application_status, - "classification_code": item.find('classificationCode').text if item.find('classificationCode') is not None else None + "classification_code": item.find('classificationCode').text if item.find('classificationCode') is not None else None, + "category_description": category_desc } - self.results.append(result) + # self.results.append(result) # ìƒíƒœ 개수와 ì´ ì•„ì´í…œ 개수 출력 - print(f"ê²€ìƒ‰ëœ item ì´ ê°œìˆ˜: {total_items}") - print(f"ë“±ë¡ ìƒíƒœì¸ item 개수: {status_registered}") - print(f"공개 ìƒíƒœì¸ item 개수: {status_published}") + logger.debug(f"ê²€ìƒ‰ëœ item ì´ ê°œìˆ˜: {total_items}") + self.results['total_count'] = total_items + logger.debug(f"ë“±ë¡ ìƒíƒœì¸ item 개수: {status_registered}") + logger.debug(f"공개 ìƒíƒœì¸ item 개수: {status_published}") def get_results(self): return self.results @@ -73,9 +87,25 @@ class Kipris_API: 'drawing': '', 'bigDrawing': '' } - xml_data = self.fetch_and_decode(params) - self.parse_xml(xml_data, status) + logger.debug(f" Search params : {params}") + try: + xml_data = self.fetch_and_decode(params) + self.parse_xml(xml_data, status) + except Exception as e: + logger.error(f"API 요청 중 ì—ëŸ¬ë°œìƒ : {e}") + return self.get_results() def close_Kipris(self): - pass \ No newline at end of file + pass + + def load_category_descriptions(self, filename): + """JSON 파ì¼ì—서 카테고리 ì„¤ëª…ì„ ë¡œë“œí•©ë‹ˆë‹¤.""" + with open(filename, 'r', encoding='utf-8') as file: + return json.load(file) + + def add_category_description(self, category_code): + """주어진 카테고리 ì½”ë“œì— ë”°ë¼ ì„¤ëª…ì„ ë°˜í™˜í•©ë‹ˆë‹¤.""" + logger.debug(f"add_category_description => category_code: {category_code}") + return self.category_description.get(category_code, "카테고리 ì„¤ëª…ì„ ì°¾ì„ ìˆ˜ 없습니다.") + diff --git a/src/kipris_image/4019850019868.jpg b/src/kipris_image/4019850019868.jpg deleted file mode 100644 index 1d74bb3..0000000 Binary files a/src/kipris_image/4019850019868.jpg and /dev/null differ diff --git a/src/kipris_image/4020060031901.jpg b/src/kipris_image/4020060031901.jpg deleted file mode 100644 index 1d74bb3..0000000 Binary files a/src/kipris_image/4020060031901.jpg and /dev/null differ diff --git a/src/kipris_image/4020100044795.jpg b/src/kipris_image/4020100044795.jpg deleted file mode 100644 index 3bbd78e..0000000 Binary files a/src/kipris_image/4020100044795.jpg and /dev/null differ diff --git a/src/kipris_image/4020180008447.jpg b/src/kipris_image/4020180008447.jpg deleted file mode 100644 index 1722774..0000000 Binary files a/src/kipris_image/4020180008447.jpg and /dev/null differ diff --git a/src/kipris_image/4020180057525.jpg b/src/kipris_image/4020180057525.jpg deleted file mode 100644 index dacdaee..0000000 Binary files a/src/kipris_image/4020180057525.jpg and /dev/null differ diff --git a/src/kipris_image/4020200194865.jpg b/src/kipris_image/4020200194865.jpg deleted file mode 100644 index c86ce79..0000000 Binary files a/src/kipris_image/4020200194865.jpg and /dev/null differ diff --git a/src/kipris_image/4020200194866.jpg b/src/kipris_image/4020200194866.jpg deleted file mode 100644 index c86ce79..0000000 Binary files a/src/kipris_image/4020200194866.jpg and /dev/null differ diff --git a/src/kipris_image/4020210039825.jpg b/src/kipris_image/4020210039825.jpg deleted file mode 100644 index 4cf3b20..0000000 Binary files a/src/kipris_image/4020210039825.jpg and /dev/null differ diff --git a/src/kipris_image/4020227013143.jpg b/src/kipris_image/4020227013143.jpg deleted file mode 100644 index 1d74bb3..0000000 Binary files a/src/kipris_image/4020227013143.jpg and /dev/null differ diff --git a/src/kipris_image/4020230000430.jpg b/src/kipris_image/4020230000430.jpg deleted file mode 100644 index 1fe1dd7..0000000 Binary files a/src/kipris_image/4020230000430.jpg and /dev/null differ diff --git a/src/kipris_image/4020230000431.jpg b/src/kipris_image/4020230000431.jpg deleted file mode 100644 index 1fe1dd7..0000000 Binary files a/src/kipris_image/4020230000431.jpg and /dev/null differ diff --git a/src/kipris_image/4120080018739.jpg b/src/kipris_image/4120080018739.jpg deleted file mode 100644 index 5498c5a..0000000 Binary files a/src/kipris_image/4120080018739.jpg and /dev/null differ diff --git a/src/kipris_settingUI.py b/src/kipris_settingUI.py index 8551f45..b64b097 100644 --- a/src/kipris_settingUI.py +++ b/src/kipris_settingUI.py @@ -3,7 +3,10 @@ from PyQt5.QtCore import QUrl from PyQt5.QtGui import QDesktopServices from src.toggleSwitch import ToggleSwitch +import logging +# 로거 ì¸ìŠ¤í„´ìŠ¤ 가져오기 +logger = logging.getLogger('default_logger') class SettingsDialog(QtWidgets.QDialog): def __init__(self, parent=None, initial_settings=None): super().__init__(parent) @@ -42,6 +45,7 @@ class SettingsDialog(QtWidgets.QDialog): def setupUI(self): + logger.debug(f"setupUI 시작") # ì…‹ì—… ë©”ì¸ ë ˆì´ì•„웃 self.mainLayout = QtWidgets.QVBoxLayout(self) @@ -207,7 +211,9 @@ class SettingsDialog(QtWidgets.QDialog): self.accept() def loadSettings(self, settings): - # print(f"SettingsDialog settings : {settings}") + logger.debug(f"loadSettings 시작") + + # logger.debug(f"SettingsDialog settings : {settings}") self.use_kipris = settings.get('use_kipris', False) # 기본값 False로 설정 self.usage_mode = settings.get('usage_mode', 'web') # 기본값 'web'로 설정 @@ -215,10 +221,10 @@ class SettingsDialog(QtWidgets.QDialog): self.set_status = settings.get('set_status', []) # 기본값 빈 리스트로 설정 # ìƒíƒœ ì—…ë°ì´íЏ 로그 출력 - # print(f"SettingsDialog Loaded settings: use_kipris={self.use_kipris}, usage_mode={self.usage_mode}, api_key={self.api_key}") + # logger.debug(f"SettingsDialog Loaded settings: use_kipris={self.use_kipris}, usage_mode={self.usage_mode}, api_key={self.api_key}") - # print(f"SettingsDialog self.use_kipris : {self.use_kipris}") + # logger.debug(f"SettingsDialog self.use_kipris : {self.use_kipris}") # UI ì—…ë°ì´íЏ self.isUseKiprisSwitch.setChecked(self.use_kipris) self.apikeySwitch.setChecked(self.usage_mode == 'api') @@ -246,17 +252,19 @@ class SettingsDialog(QtWidgets.QDialog): def toggleCNYexchange(self, checked): self.exchangeCNYSwitch.setChecked(checked) self.setCNY = checked - print(f"self.setCNY : {self.setCNY}") - def toggleUSDexchange(self, checked): + logger.debug(f"self.setCNY : {self.setCNY}") + def toggleUSDexchange(self, checked): self.exchangeUSDSwitch.setChecked(checked) self.setUSD = checked - print(f"self.setUSD : {self.setUSD}") + logger.debug(f"self.setUSD : {self.setUSD}") def toggleKiprisUsage(self, checked): self.settingKiprisWidget.setVisible(checked) self.checkWidget.setVisible(checked) self.use_kipris = checked + logger.debug(f"self.use_kipris : {self.use_kipris}") + # self.kiprisFrame.setVisible(False) def toggleAPIUsage(self, checked): @@ -264,12 +272,14 @@ class SettingsDialog(QtWidgets.QDialog): self.useWebSwitch.setChecked(not checked) self.editAPIWidget.setVisible(checked) self.usage_mode = 'api' if checked else 'web' + logger.debug(f"self.usage_mode : {self.usage_mode}") def toggleWebUsage(self, checked): self.useWebSwitch.setChecked(checked) self.apikeySwitch.setChecked(not checked) self.editAPIWidget.setVisible(not checked) self.usage_mode = 'web' if checked else 'api' + logger.debug(f"self.usage_mode : {self.usage_mode}") def create_label_and_switch(self, widget, label_text, target_switch): layout = QtWidgets.QHBoxLayout() @@ -306,36 +316,51 @@ class SettingsDialog(QtWidgets.QDialog): if status in self.set_status: self.set_status.remove(status) - # print("Current Status List:", self.set_status) + logger.debug(f"self.set_status : {self.set_status}") + + # logger.debug("Current Status List:", self.set_status) def handle_all_checked(self, state): if state == QtCore.Qt.Checked: - for checkbox in self.checkboxes: - checkbox.setChecked(True) + self.right_rejected_checkbox.setChecked(True) + self.right_registered_checkbox.setChecked(True) + self.right_expiration_checkbox.setChecked(True) + self.right_void_checkbox.setChecked(True) + self.right_Withdrawal_checkbox.setChecked(True) + self.right_remise_checkbox.setChecked(True) + self.right_Disclosure_checkbox.setChecked(True) + elif state == QtCore.Qt.Unchecked: - for checkbox in self.checkboxes[1:]: # "등ë¡" ì²´í¬ë°•스 제외 - checkbox.setChecked(False) - self.checkboxes[0].setChecked(True) # "등ë¡" ì²´í¬ë°•스는 í•­ìƒ ì²´í¬ + self.right_rejected_checkbox.setChecked(False) + self.right_expiration_checkbox.setChecked(False) + self.right_void_checkbox.setChecked(False) + self.right_Withdrawal_checkbox.setChecked(False) + self.right_remise_checkbox.setChecked(False) + self.right_Disclosure_checkbox.setChecked(False) - def handle_checkbox_state_changed(self): - for checkbox in self.checkboxes: - # 글ìžë¥¼ 진하게 만들기 - font = checkbox.font() - font.setBold(checkbox.isChecked()) - checkbox.setFont(font) + self.right_registered_checkbox.setChecked(True) # "등ë¡" ì²´í¬ë°•스는 í•­ìƒ ì²´í¬ - # ì „ì²´ ì²´í¬ ìƒíƒœ ì—…ë°ì´íЏ - all_checked = all(checkbox.isChecked() for checkbox in self.checkboxes) - all_unchecked = all(not checkbox.isChecked() for checkbox in self.checkboxes[1:]) # "등ë¡" 제외 + logger.debug(f"all_checked : {state}") - self.all_checkbox.blockSignals(True) # ì‹œê·¸ë„ ì¼ì‹œ 중지 - if all_checked: - self.all_checkbox.setCheckState(QtCore.Qt.Checked) - elif all_unchecked: - self.all_checkbox.setCheckState(QtCore.Qt.Unchecked) - else: - self.all_checkbox.setCheckState(QtCore.Qt.PartiallyChecked) - self.all_checkbox.blockSignals(False) # ì‹œê·¸ë„ ìž¬ê°œ + # def handle_checkbox_state_changed(self): + # for checkbox in self.checkboxes: + # # 글ìžë¥¼ 진하게 만들기 + # font = checkbox.font() + # font.setBold(checkbox.isChecked()) + # checkbox.setFont(font) + + # # ì „ì²´ ì²´í¬ ìƒíƒœ ì—…ë°ì´íЏ + # all_checked = all(checkbox.isChecked() for checkbox in self.checkboxes) + # all_unchecked = all(not checkbox.isChecked() for checkbox in self.checkboxes[1:]) # "등ë¡" 제외 + + # self.all_checkbox.blockSignals(True) # ì‹œê·¸ë„ ì¼ì‹œ 중지 + # if all_checked: + # self.all_checkbox.setCheckState(QtCore.Qt.Checked) + # elif all_unchecked: + # self.all_checkbox.setCheckState(QtCore.Qt.Unchecked) + # else: + # self.all_checkbox.setCheckState(QtCore.Qt.PartiallyChecked) + # self.all_checkbox.blockSignals(False) # ì‹œê·¸ë„ ìž¬ê°œ class HelpDialog(QtWidgets.QDialog): @@ -354,9 +379,14 @@ class HelpDialog(QtWidgets.QDialog): ) else: self.resize(400, 300) # ë‹¨ë… ì‹¤í–‰ 시 í¬ê¸° 설정 + + logger.debug(f"HelpDialog 초기화") + self.setupUI() def setupUI(self): + logger.debug(f"HelpDialog setupUI 로드") + layout = QtWidgets.QVBoxLayout(self) textBrowser = QtWidgets.QTextBrowser(self) textBrowser.setOpenExternalLinks(False) # 외부 ë§í¬ ìžë™ 열기 비활성화 @@ -387,10 +417,6 @@ class HelpDialog(QtWidgets.QDialog): QDesktopServices.openUrl(url) - - - - # ※ 행정 ìƒíƒœ ë„ì›€ë§ # ê±°ì ˆ : ì¶œì› í›„ 특허 심사과정ì—서 실체ì ì¸ 특허 등ë¡ìš”ê±´ì„ ë§Œì¡±í•˜ì§€ 못할 ê²½ìš°ì— ì‹¬ì‚¬ê´€ì´ ì·¨í•˜ëŠ” 행정처분 # ë“±ë¡ : ì‹¬ì‚¬ê´€ì´ ì‹¬ì‚¬í•œ ê²°ê³¼ 등ë¡ìš”ê±´ì— ì í•©í•˜ì—¬ 설정등ë¡ì„ ë°›ì„ ìˆ˜ 있다는 ë‚´ìš©ì˜ í–‰ì •ì²˜ë¶„ diff --git a/src/kipris_web_from_playwright.py b/src/kipris_web_from_playwright.py index 7a23890..23e89e9 100644 --- a/src/kipris_web_from_playwright.py +++ b/src/kipris_web_from_playwright.py @@ -3,7 +3,10 @@ import random, requests, json from PIL import Image import os from io import BytesIO +import logging +# 로거 ì¸ìŠ¤í„´ìŠ¤ 가져오기 +logger = logging.getLogger('default_logger') class Kipris_WEB: def __init__(self, apikey=None): self.apikey = apikey @@ -42,45 +45,45 @@ class Kipris_WEB: def run(self, term, status): """검색어로 검색하고 ê²°ê³¼ 수집""" - print(f"Playwright 검색시작 : 키워드 : [{term}]") + logger.debug(f"Playwright 검색시작 : 키워드 : [{term}]") try: self.page.fill("#queryText", term) self.page.click(".input_btn") # JavaScriptì— ì˜í•´ 결과가 ë™ì ìœ¼ë¡œ 로드ë˜ê¸°ë¥¼ 기다립니다. loaded = self.page.wait_for_function("document.querySelector('form#listForm section.search_section article') != null") - print("검색페ì´ì§€ 로드 완료") + logger.debug("검색페ì´ì§€ 로드 완료") if not loaded: - print("검색 결과가 시간 ë‚´ì— ë¡œë“œë˜ì§€ 않았습니다.") + logger.debug("검색 결과가 시간 ë‚´ì— ë¡œë“œë˜ì§€ 않았습니다.") return None # 검색 결과가 없는지 í™•ì¸ nodata_info = self.page.query_selector(".nodata_info") if nodata_info: - print("검색 결과가 없습니다.") + logger.debug("검색 결과가 없습니다.") # 특정 메서드 호출 ë° í•¨ìˆ˜ 종료 # self.handle_no_search_results() return None - print("검색 ê²°ê³¼ 로딩 후 실제 요소 수집 시작") + logger.debug("검색 ê²°ê³¼ 로딩 후 실제 요소 수집 시작") # ê²°ê³¼ ë¡œë”©ì´ í™•ì¸ëœ 후, 실제 요소를 수집 self.page.wait_for_selector("form#listForm section.search_section", state="visible", timeout=10000) - print("listForm") + logger.debug("listForm") total_count = self.page.text_content("form#listForm section.search_section div p span.total") - print(f"total_count : {total_count}") + logger.debug(f"total_count : {total_count}") if total_count: self.results['total_count'] = total_count.strip() articles = self.page.query_selector_all("form#listForm section.search_section article") - print(f"articles : {len(articles)}") + logger.debug(f"articles : {len(articles)}") for i, article in enumerate(articles): id_and_name_element = article.query_selector("div:nth-child(1) span input[type='checkbox']") trademark_name = id_and_name_element.get_attribute("title") if id_and_name_element else "No name found" - print(f"trademark_name : {trademark_name}") + logger.debug(f"trademark_name : {trademark_name}") applno = id_and_name_element.get_attribute("value") if id_and_name_element else "No ID found" if applno: trademark_image_url_by_id = f"http://kdtj.kipris.or.kr/kdtj/remoteFile.do?method=bigImageTM&applno={applno}&no={applno}_tm000001.jpg" - print(f"applno : {applno}") + logger.debug(f"applno : {applno}") img_element = article.query_selector("div:nth-child(2) div a img") trademark_image = img_element.get_attribute("src") if img_element else "No image found" @@ -107,7 +110,7 @@ class Kipris_WEB: # Use the title attribute of the checkbox input for the trademark name # name_element = article.query_selector("div:nth-child(1) span input[type='checkbox']") # trademark_name = name_element.get_attribute("title") if name_element else "No name found" - print(f"ì•„ì´í…œ ì •ë³´ 변수 만들기") + logger.debug(f"ì•„ì´í…œ ì •ë³´ 변수 만들기") # if not admin_status == "소멸": if admin_status in status: @@ -123,12 +126,12 @@ class Kipris_WEB: "publication_date": publication_date, "registration_date": registration_date, } - print("리턴") + logger.debug("리턴") return self.results else: - print("No total count element found, possibly incorrect selector or page structure has changed.") + logger.debug("No total count element found, possibly incorrect selector or page structure has changed.") except Exception as e: - print(f"오류 ë°œìƒ : {e}") + logger.debug(f"오류 ë°œìƒ : {e}") return None def download_image(url, applno): @@ -138,9 +141,9 @@ class Kipris_WEB: filename = f"{applno}.jpeg" # íŒŒì¼ ì´ë¦„ì„ ID로 설정 with open(filename, 'wb') as file: file.write(response.content) - print(f"ì´ë¯¸ì§€ê°€ 성공ì ìœ¼ë¡œ 저장ë˜ì—ˆìŠµë‹ˆë‹¤: {filename}") + logger.debug(f"ì´ë¯¸ì§€ê°€ 성공ì ìœ¼ë¡œ 저장ë˜ì—ˆìŠµë‹ˆë‹¤: {filename}") else: - print(f"ì´ë¯¸ì§€ 다운로드 실패: HTTP {response.status_code}") + logger.debug(f"ì´ë¯¸ì§€ 다운로드 실패: HTTP {response.status_code}") def load_category_descriptions(self, filename): """JSON 파ì¼ì—서 카테고리 ì„¤ëª…ì„ ë¡œë“œí•©ë‹ˆë‹¤.""" @@ -167,10 +170,10 @@ class Kipris_WEB: image.save(buffer, 'JPEG') # 예시로 JPEG í¬ë§·ì„ 사용 return buffer.getvalue() except Exception as e: - print(f"ì´ë¯¸ì§€ 변환 실패: {e}") + logger.debug(f"ì´ë¯¸ì§€ 변환 실패: {e}") return None else: - print(f"ì´ë¯¸ì§€ 다운로드 실패: HTTP {response.status_code}") + logger.debug(f"ì´ë¯¸ì§€ 다운로드 실패: HTTP {response.status_code}") return None def close_Kipris(self): diff --git a/src/result_widget.py b/src/result_widget.py index d2ac4c4..d9210a8 100644 --- a/src/result_widget.py +++ b/src/result_widget.py @@ -2,11 +2,16 @@ import sys from PyQt5.QtWidgets import QSizePolicy, QWidget, QVBoxLayout, QHBoxLayout, QLabel, QPushButton, QGridLayout from PyQt5.QtGui import QPixmap from PyQt5.QtCore import Qt +# from PyQt5.Qt import QDesktopServices +import webbrowser import requests from PIL import Image from io import BytesIO import asyncio, aiofiles, aiohttp +import logging +# 로거 ì¸ìŠ¤í„´ìŠ¤ 가져오기 +logger = logging.getLogger('default_logger') class ResultWidget(QWidget): def __init__(self): super().__init__() @@ -15,64 +20,82 @@ class ResultWidget(QWidget): def initUI(self): self.setWindowFlags(self.windowFlags() | Qt.WindowStaysOnTopHint) - def show_results(self, results): + def show_results(self, results, searchType, elapsed_time, currentURL=''): + searchType = searchType + elapsed_time = elapsed_time + currentURL = currentURL + logger.debug(f"show_results - searchType : {searchType}") + logger.debug(f"show_results - elapsed_time : {elapsed_time}") + # try: + # ê²°ê³¼ 위젯 ìƒì„± + self.results_widget = QWidget() + layout = QVBoxLayout() + self.results_widget.setLayout(layout) - try: - # ê²°ê³¼ 위젯 ìƒì„± - self.results_widget = QWidget() - layout = QVBoxLayout() - self.results_widget.setLayout(layout) + # ê²°ê³¼ 갯수 í™•ì¸ ë° ë ˆì´ì•„웃 ë™ì  ìƒì„± + total_count = int(results['total_count']) + set_count = min(total_count, 10) + grid_layout = QGridLayout() + layout.addLayout(grid_layout) + grid_index = 0 + grid_columns = 5 + logger.debug(f"show_results - set_count : {set_count}") - # ê²°ê³¼ 갯수 í™•ì¸ ë° ë ˆì´ì•„웃 ë™ì  ìƒì„± - total_count = int(results['total_count']) - set_count = min(total_count, 10) - grid_layout = QGridLayout() - layout.addLayout(grid_layout) - grid_index = 0 - grid_columns = 5 + for i in range(1, set_count + 1): + result_key = f"result_{i}" + if result_key in results: + result = results[result_key] + logger.debug(f"show_results - result_key : {result_key}") - for i in range(1, set_count + 1): - result_key = f"result_{i}" - if result_key in results: - result = results[result_key] + # í…Œë‘리 설정 + border_style = '' + if result['application_status'] == '등ë¡': + border_style = 'border: 4px solid red;' + elif result['application_status'] == '공고': + border_style = 'border: 3px solid black;' + + # ê° ê²°ê³¼ì— ëŒ€í•œ ë ˆì´ì•„웃 ìƒì„± + item_layout = QVBoxLayout() + item_widget = QWidget() # 위젯 ìƒì„± - # í…Œë‘리 설정 - border_style = '' - if result['application_status'] == '등ë¡': - border_style = 'border: 4px solid red;' - elif result['application_status'] == '공고': - border_style = 'border: 3px solid black;' - - # ê° ê²°ê³¼ì— ëŒ€í•œ ë ˆì´ì•„웃 ìƒì„± - item_layout = QVBoxLayout() - item_widget = QWidget() # 위젯 ìƒì„± + # item_layoutì˜ í¬ê¸° ì •ì±… 설정 + item_widget.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.MinimumExpanding) - # item_layoutì˜ í¬ê¸° ì •ì±… 설정 - item_widget.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.MinimumExpanding) + # ì´ë¯¸ì§€ 처리 + image_label = QLabel() + image_label.setFixedSize(150, 150) + image_data = self.fetch_image_data(result['drawing_url']) + pixmap = QPixmap() + pixmap.loadFromData(image_data) + # QLabelì˜ í¬ê¸°ì— 맞게 ì´ë¯¸ì§€ í¬ê¸° ì¡°ì • + scaled_pixmap = pixmap.scaled(image_label.size(), Qt.KeepAspectRatio, Qt.SmoothTransformation) + image_label.setPixmap(scaled_pixmap) + # QLabelì˜ ê°€ë¡œ 세로 ì¤‘ì•™ì— ì´ë¯¸ì§€ 표시 + image_label.setAlignment(Qt.AlignCenter) + # ì´ë¯¸ì§€ 표시 ìœ„ì ¯ì˜ í¬ê¸° ì¡°ì • ì •ì±… 설정 + image_label.setScaledContents(True) - # ì´ë¯¸ì§€ 처리 - image_label = QLabel() - image_label.setFixedSize(150, 150) - image_data = self.fetch_image_data(result['drawing_url']) - pixmap = QPixmap() - pixmap.loadFromData(image_data) - # QLabelì˜ í¬ê¸°ì— 맞게 ì´ë¯¸ì§€ í¬ê¸° ì¡°ì • - scaled_pixmap = pixmap.scaled(image_label.size(), Qt.KeepAspectRatio, Qt.SmoothTransformation) - image_label.setPixmap(scaled_pixmap) - # QLabelì˜ ê°€ë¡œ 세로 ì¤‘ì•™ì— ì´ë¯¸ì§€ 표시 - image_label.setAlignment(Qt.AlignCenter) - # ì´ë¯¸ì§€ 표시 ìœ„ì ¯ì˜ í¬ê¸° ì¡°ì • ì •ì±… 설정 - image_label.setScaledContents(True) + #ì´ë¯¸ì§€ 중앙배치를 위해 + horizontal_layout = QHBoxLayout() + horizontal_layout.addWidget(image_label) + horizontal_layout.setAlignment(Qt.AlignCenter) + item_layout.addLayout(horizontal_layout) - #ì´ë¯¸ì§€ 중앙배치를 위해 - horizontal_layout = QHBoxLayout() - horizontal_layout.addWidget(image_label) - horizontal_layout.setAlignment(Qt.AlignCenter) - item_layout.addLayout(horizontal_layout) + # item_layout.addWidget(image_label) - # item_layout.addWidget(image_label) - - # ì •ë³´ í…스트 + if searchType =='api': + # API ì •ë³´ í…스트 + # info_text = f"ìƒí‘œê¶Œëª…: {result['title']}\n등ë¡ìƒíƒœ: {result['admin_status']}\nCategory: {result['product_category']}\nApplicant: {result['applicant']}\nPublication Date: {result['publication_date']}\nRegistration Date: {result['registration_date']}" + info_text = f"ìƒí‘œê¶Œëª…: {result['title']}
\n" \ + f"등ë¡ìƒíƒœ: {result['application_status']}
\n" \ + f"카테고리: {result['classification_code']}
\n" \ + f"권리ìž: {result['applicant_name']}
\n" \ + f"ì¶œì›ì¼ìž {result['application_date']}
\n" \ + f"공고ì¼ìž {result['publication_date']}
\n" \ + f"등ë¡ì¼ìž {result['registration_date']}\n" \ + f"전문 {result['full_text']}
\n" + elif searchType =='web': + # WEB ì •ë³´ í…스트 # info_text = f"ìƒí‘œê¶Œëª…: {result['title']}\n등ë¡ìƒíƒœ: {result['admin_status']}\nCategory: {result['product_category']}\nApplicant: {result['applicant']}\nPublication Date: {result['publication_date']}\nRegistration Date: {result['registration_date']}" info_text = f"ìƒí‘œê¶Œëª…: {result['title']}
\n" \ f"등ë¡ìƒíƒœ: {result['application_status']}
\n" \ @@ -81,38 +104,49 @@ class ResultWidget(QWidget): f" {result['publication_date']}
\n" \ f" {result['registration_date']}" - info_label = QLabel(info_text) - info_label.setToolTip(self.wrap_text(result['category_description'], 50)) - image_label.setToolTip(self.wrap_text(result['category_description'], 50)) - item_layout.addWidget(info_label) + info_label = QLabel(info_text) + if searchType =='web': + currentURL_btn = QPushButton("웹 열기") + # currentURL_btn.clicked.connect(self.openCurrentPage(currentURL)) + info_label.setToolTip(self.wrap_text(result['category_description'], 50)) + image_label.setToolTip(self.wrap_text(result['category_description'], 50)) + item_layout.addWidget(info_label) - image_label.setStyleSheet(border_style) - info_label.setStyleSheet(border_style) + image_label.setStyleSheet(border_style) + info_label.setStyleSheet(border_style) - # ë ˆì´ì•„ì›ƒì— ìœ„ì ¯ 추가 - row = grid_index // grid_columns - col = grid_index % grid_columns - grid_layout.addLayout(item_layout, row, col) - grid_index += 1 + # ë ˆì´ì•„ì›ƒì— ìœ„ì ¯ 추가 + row = grid_index // grid_columns + col = grid_index % grid_columns + grid_layout.addLayout(item_layout, row, col) + grid_index += 1 - # ê²°ê³¼ ìœ„ì ¯ì— ë‹«ê¸° 버튼 추가 - close_button = QPushButton("Close") - close_button.clicked.connect(self.close_results_widget) - layout.addWidget(close_button) + # ê²°ê³¼ ìœ„ì ¯ì— ë‹«ê¸° 버튼 추가 + close_button = QPushButton("Close") + close_button.clicked.connect(self.close_results_widget) + layout.addWidget(close_button) + + # e + elapsed_time_Label = QLabel(f"Elapsed Time : {elapsed_time}") + layout.addWidget(elapsed_time_Label) - # ê²°ê³¼ ìœ„ì ¯ì„ ë©”ì¸ ìœˆë„ìš°ì— ì¶”ê°€ - self.results_widget.setGeometry(300, 300, 600, 300) # 위치와 í¬ê¸° 설정 - self.results_widget.setWindowTitle('Search Results') # 타ì´í‹€ 설정 - self.results_widget.show() - - except Exception as e: - print(f"Error displaying results: {e}") + # ê²°ê³¼ ìœ„ì ¯ì„ ë©”ì¸ ìœˆë„ìš°ì— ì¶”ê°€ + self.results_widget.setGeometry(300, 300, 600, 300) # 위치와 í¬ê¸° 설정 + self.results_widget.setWindowTitle('Search Results') # 타ì´í‹€ 설정 + self.results_widget.show() + # except Exception as e: + # logger.debug(f"Error displaying results: {e}") def close_results_widget(self): # ê²°ê³¼ 위젯닫기 함수를 호출할 때 사용하는 메서드 self.results_widget.close() + def openCurrentPage(self, currentURL): + logger.debug(f"open the page : {currentURL}") + webbrowser.open('currentURL') + pass + # QDesktopServices.openUrl(self.currentURL) def wrap_text(self, text, width=40): """주어진 ë„ˆë¹„ì— ë§žê²Œ í…스트를 줄바꿈합니다.""" @@ -133,31 +167,31 @@ class ResultWidget(QWidget): async def fetch_image_data_async(self, url): """주어진 URL로부터 ì´ë¯¸ì§€ ë°ì´í„°ë¥¼ 비ë™ê¸°ì ìœ¼ë¡œ 가져와 반환합니다.""" async with aiohttp.ClientSession() as session: - # print(f"download_image session Start!!") + # logger.debug(f"download_image session Start!!") async with session.get(url) as response: - print(f"download_image url : {url}") + logger.debug(f"download_image url : {url}") if response.status == 200: - # print(f"response : {response}") + # logger.debug(f"response : {response}") content_type = response.headers.get('Content-Type', '') # await 제거 - print(f"content_type : {content_type}") + logger.debug(f"content_type : {content_type}") if 'image' in content_type or 'octet-stream' in content_type: - # print(f"image content type or octet-stream : {content_type}") + # logger.debug(f"image content type or octet-stream : {content_type}") return await response.read() else: try: # Content-Typeì´ ì´ë¯¸ì§€ê°€ 아니면, ë°ì´í„°ë¥¼ ì´ë¯¸ì§€ë¡œ 변환 data = await response.read() - # print(f"Content-Typeì´ ì´ë¯¸ì§€ê°€ 아님 : {data}") + # logger.debug(f"Content-Typeì´ ì´ë¯¸ì§€ê°€ 아님 : {data}") image = Image.open(BytesIO(data)) with BytesIO() as buffer: image.save(buffer, 'JPEG') - print(f"image 를 JPEG로 저장") + logger.debug(f"image 를 JPEG로 저장") return buffer.getvalue() except Exception as e: - print(f"ì´ë¯¸ì§€ 변환 실패: {e}") + logger.debug(f"ì´ë¯¸ì§€ 변환 실패: {e}") return None else: - print(f"ì´ë¯¸ì§€ 다운로드 실패: HTTP {response.status}") + logger.debug(f"ì´ë¯¸ì§€ 다운로드 실패: HTTP {response.status}") return None @@ -177,8 +211,8 @@ class ResultWidget(QWidget): image.save(buffer, 'JPEG') # 예시로 JPEG í¬ë§·ì„ 사용 return buffer.getvalue() except Exception as e: - print(f"ì´ë¯¸ì§€ 변환 실패: {e}") + logger.debug(f"ì´ë¯¸ì§€ 변환 실패: {e}") return None else: - print(f"ì´ë¯¸ì§€ 다운로드 실패: HTTP {response.status_code}") + logger.debug(f"ì´ë¯¸ì§€ 다운로드 실패: HTTP {response.status_code}") return None diff --git a/src/search_display.py b/src/search_display.py index 6ff8351..befd710 100644 --- a/src/search_display.py +++ b/src/search_display.py @@ -2,6 +2,11 @@ import requests, os from PyQt5.QtWidgets import QWidget, QTextBrowser, QVBoxLayout from PyQt5.QtCore import Qt from PIL import Image +import logging + +# 로거 ì¸ìŠ¤í„´ìŠ¤ 가져오기 +logger = logging.getLogger('default_logger') + class TrademarkSearchDisplay(QWidget): def __init__(self, parent=None): super().__init__() @@ -69,22 +74,22 @@ class TrademarkSearchDisplay(QWidget): self.text_browser.append(html_content) def display_web_results(self, data, elapsed_time): - print(f"Processing results... Elapsed time: {elapsed_time}s") + logger.debug(f"Processing results... Elapsed time: {elapsed_time}s") # data 딕셔너리 ë‚´ì˜ í‚¤ 중 'result_'로 시작하는 키를 찾아 ê·¸ ê°’ì„ ì²˜ë¦¬ for key, item in data.items(): - print(f"Checking key: {key}") # 로그 추가 + logger.debug(f"Checking key: {key}") # 로그 추가 if key.startswith('result_'): # 'result_'로 시작하는 키 í™•ì¸ - print(f"Found valid key: {key}, Processing item...") # 로그 추가 + logger.debug(f"Found valid key: {key}, Processing item...") # 로그 추가 if isinstance(item, dict): # itemì´ ë”•ì…”ë„ˆë¦¬ì¸ì§€ í™•ì¸ - print(f"Item is a dictionary. Generating HTML for item with title: {item.get('title')}") # 로그 추가 + logger.debug(f"Item is a dictionary. Generating HTML for item with title: {item.get('title')}") # 로그 추가 # ì´ë¯¸ì§€ 다운로드 ì‹œë„ downloaded_image_path = self.download_image(item.get("drawing_url"), item.get("ID")) if downloaded_image_path: - print(f"Image downloaded and saved to {downloaded_image_path}") + logger.debug(f"Image downloaded and saved to {downloaded_image_path}") image_html = f'' else: - print("Failed to download image.") + logger.debug("Failed to download image.") image_html = 'Image not available' # HTML 콘í…츠 ìƒì„± @@ -123,11 +128,11 @@ class TrademarkSearchDisplay(QWidget): ''' self.text_browser.append(html_content) - print("HTML content appended to QTextBrowser.") # 로그 추가 + logger.debug("HTML content appended to QTextBrowser.") # 로그 추가 else: - print(f"Error: Item associated with {key} is not a dictionary.") # 오류 로그 + logger.debug(f"Error: Item associated with {key} is not a dictionary.") # 오류 로그 else: - print(f"Ignored key: {key}") # ë¬´ì‹œëœ í‚¤ 로그 + logger.debug(f"Ignored key: {key}") # ë¬´ì‹œëœ í‚¤ 로그 def download_image(self, image_url, identifier): @@ -160,7 +165,7 @@ class TrademarkSearchDisplay(QWidget): img_resized.save(image_path) return image_path except Exception as e: - print(f"Error resizing image: {e}") + logger.debug(f"Error resizing image: {e}") return None diff --git a/src/test_api.py b/src/test_api.py deleted file mode 100644 index 26ae570..0000000 --- a/src/test_api.py +++ /dev/null @@ -1,42 +0,0 @@ -from kipris_api_from_publicdata import Kipris - -# 테스트를 위한 URL ë° íŒŒë¼ë¯¸í„° 설정 -apikey = 'X9Tz3JqC/JcCwxnNewA6qdloIN6QFIitVBgS1a2KVDYk1AmddaDTvzr6+t3dyLZV3gh2TPXdNhxsRQwaKP673Q==' -search_keyword = "ì¨ì§€ì˜¤" -url = 'http://kipo-api.kipi.or.kr/openapi/service/trademarkInfoSearchService/getWordSearch' - -params = { - 'serviceKey': apikey, - 'searchString': search_keyword, - 'searchRecentYear': '0', - 'title': '', - 'fullText': '', - 'drawing': '', - 'bigDrawing': '' -} - -# XMLParser ì¸ìŠ¤í„´ìŠ¤ ìƒì„± ë° ì‹¤í–‰ -parser = Kipris(url, params) -results = parser.run() - -# 모든 ì•„ì´í…œì˜ ê²°ê³¼ 출력 -if results: - print("결과가 있는 ì•„ì´í…œ 목ë¡:") - for index, item in enumerate(results, start=1): - print(f"\nì•„ì´í…œ {index} ì •ë³´:") - for key, value in item.items(): - print(f"{key}: {value}") -else: - print("결과가 없습니다.") - - -# ※ 행정 ìƒíƒœ ë„ì›€ë§ -# ê±°ì ˆ : ì¶œì› í›„ 특허 심사과정ì—서 실체ì ì¸ 특허 등ë¡ìš”ê±´ì„ ë§Œì¡±í•˜ì§€ 못할 ê²½ìš°ì— ì‹¬ì‚¬ê´€ì´ ì·¨í•˜ëŠ” 행정처분 -# ë“±ë¡ : ì‹¬ì‚¬ê´€ì´ ì‹¬ì‚¬í•œ ê²°ê³¼ 등ë¡ìš”ê±´ì— ì í•©í•˜ì—¬ 설정등ë¡ì„ ë°›ì„ ìˆ˜ 있다는 ë‚´ìš©ì˜ í–‰ì •ì²˜ë¶„ -# 소멸 : íŠ¹í—ˆë“±ë¡ í›„ ì¡´ì†ê¸°ê°„ì´ ë§Œë£Œë˜ì–´ 권리가 ì†Œë©¸ëœ ìƒíƒœ -# 무효 : ì¶œì› ë˜ëŠ” 등ë¡ëœ ìƒíƒœì— 대하여 특정 사유로 ì¸í•´ ê·¸ 권리나 행위가 무효화 ëœ ìƒíƒœ -# 취하 : ì¶œì›í•œ 특허가 등ë¡ë˜ê¸°ì „ 여러 사유로 ì¸í•˜ì—¬ ì¶œì›ì´ ì·¨ì†Œëœ ìƒíƒœ -# í¬ê¸° : ì¶œì›ì¸ì˜ í¬ê¸°ì„œ 제출, 등ë¡ë£Œ 불납 등으로 등ë¡ê²°ì •ì´ë‚˜ 권리를 í¬ê¸°í•œ ìƒíƒœ -# 공개 : ì¶œì›ì´ë‚˜ 등ë¡ì‚¬ì‹¤ì´ ì¼ë°˜ 공중ì—게 ê³µí‘œëœ ìƒíƒœë¡œ ì¶œì› í›„ 18ê°œì›”ì´ ì§€ë‚œ ê±´ -# *조기공개신청시 18개월 ë¯¸ë§Œë„ ê³µê°œê°€ëŠ¥ -# \ No newline at end of file diff --git a/src/toggleSwitch.py b/src/toggleSwitch.py index 69c4b8c..b10d13e 100644 --- a/src/toggleSwitch.py +++ b/src/toggleSwitch.py @@ -1,6 +1,10 @@ from PyQt5.QtCore import Qt, QRect, QPropertyAnimation, pyqtProperty, pyqtSignal, QPoint from PyQt5.QtGui import QPainter, QColor from PyQt5.QtWidgets import QWidget +import logging + +# 로거 ì¸ìŠ¤í„´ìŠ¤ 가져오기 +logger = logging.getLogger('default_logger') class ToggleSwitch(QWidget): clicked = pyqtSignal(bool) diff --git a/src/web_scraper_async.py b/src/web_scraper_async.py index 73158bd..134ae7e 100644 --- a/src/web_scraper_async.py +++ b/src/web_scraper_async.py @@ -4,7 +4,10 @@ import random, requests, json from PIL import Image from io import BytesIO import os +import logging +# 로거 ì¸ìŠ¤í„´ìŠ¤ 가져오기 +logger = logging.getLogger('default_logger') class WebScraper: def __init__(self): self.results = {} @@ -12,6 +15,7 @@ class WebScraper: self.browser = None self.context = None self.page = None + self.currentURL = '' filename = 'categories.json' self.category_description = self.load_category_descriptions(filename) self.url = "http://kdtj.kipris.or.kr/kdtj/searchLogina.do?method=loginTM#page1" @@ -42,9 +46,9 @@ class WebScraper: try: await self.page.goto(self.url, wait_until='networkidle') self.is_page_loaded = True - print("Page loaded successfully.") + logger.debug("Page loaded successfully.") except Exception as e: - print(f"Failed to load the page: {e}") + logger.debug(f"Failed to load the page: {e}") self.is_page_loaded = False # 로드 실패 처리 @@ -52,9 +56,9 @@ class WebScraper: try: await self.page.goto(url, wait_until='networkidle') self.is_page_loaded = True - print("Page loaded successfully.") + logger.debug("Page loaded successfully.") except Exception as e: - print(f"Failed to load the page: {e}") + logger.debug(f"Failed to load the page: {e}") self.is_page_loaded = False # 로드 실패 처리 @@ -65,23 +69,23 @@ class WebScraper: # await self.page.fill("#queryText", term) await self.page.fill("#keywordTextarea", term) - print(f"검색어 ìž…ë ¥ : {term}") + logger.debug(f"검색어 ìž…ë ¥ : {term}") await self.page.click(".input_btn") - print(f"검색버튼 í´ë¦­") + logger.debug(f"검색버튼 í´ë¦­") # JavaScriptì— ì˜í•´ 결과가 ë™ì ìœ¼ë¡œ 로드ë˜ê¸°ë¥¼ 기다립니다. loaded = await self.page.wait_for_function( "document.querySelector('form#listForm section.search_section article') != null" ) if not loaded: - print("검색 결과가 시간 ë‚´ì— ë¡œë“œë˜ì§€ 않았습니다.") + logger.debug("검색 결과가 시간 ë‚´ì— ë¡œë“œë˜ì§€ 않았습니다.") return None - print(f"결과가 ë™ì ìœ¼ë¡œ 로드ë˜ê¸°ë¥¼ 기다림 : {loaded}") + logger.debug(f"결과가 ë™ì ìœ¼ë¡œ 로드ë˜ê¸°ë¥¼ 기다림 : {loaded}") # 검색 결과가 없는지 í™•ì¸ nodata_info = await self.page.query_selector(".nodata_info") if nodata_info: - print("검색 결과가 없습니다.") + logger.debug("검색 결과가 없습니다.") return None # ê²°ê³¼ ë¡œë”©ì´ í™•ì¸ëœ 후, 실제 요소를 수집 @@ -89,41 +93,44 @@ class WebScraper: total_count = await self.page.text_content("form#listForm section.search_section div p span.total") total_count = total_count.strip() total_count = int(total_count.replace(',', '')) - print(f"total_count : {total_count}") + logger.debug(f"total_count : {total_count}") + + self.currentURL = self.page.url + logger.debug(f"currentURL : {self.currentURL}") if total_count: self.results['total_count'] = total_count articles = await self.page.query_selector_all("form#listForm section.search_section article") - print(f"articles : {len(articles)} ê°œ") + logger.debug(f"articles : {len(articles)} ê°œ") for i, article in enumerate(articles): id_and_name_element = await article.query_selector("div:nth-child(1) span input[type='checkbox']") trademark_name = await id_and_name_element.get_attribute("title") if id_and_name_element else "No name found" - print(f"trademark_name : {trademark_name}") + logger.debug(f"trademark_name : {trademark_name}") applno = await id_and_name_element.get_attribute("value") if id_and_name_element else "No ID found" trademark_image_url_by_id = ( f"http://kdtj.kipris.or.kr/kdtj/remoteFile.do?method=bigImageTM&applno={applno}&no={applno}_tm000001.jpg" if applno else None ) - print(f"trademark_image_url_by_id : {trademark_image_url_by_id}") + logger.debug(f"trademark_image_url_by_id : {trademark_image_url_by_id}") img_element = await article.query_selector("div:nth-child(2) div a img") trademark_image = await img_element.get_attribute("src") if img_element else "No image found" - print(f"trademark_image : {trademark_image}") + logger.debug(f"trademark_image : {trademark_image}") admin_status_element = await article.query_selector("div:nth-child(1) h1 a:nth-child(1) span") admin_status = await admin_status_element.text_content() if admin_status_element else "No status found" - print(f"admin_status : {admin_status}") + logger.debug(f"admin_status : {admin_status}") product_category_element = await article.query_selector("div:nth-child(2) ul li:nth-child(1) a span") product_category = await product_category_element.text_content() if product_category_element else "No category found" category_desc = self.add_category_description(product_category) if product_category else "No category description" - print(f"product_category : {product_category}") - print(f"category_desc : {category_desc}") + logger.debug(f"product_category : {product_category}") + logger.debug(f"category_desc : {category_desc}") applicant_element = await article.query_selector("div:nth-child(2) ul li:nth-child(2) span[title]") applicant = await applicant_element.get_attribute("title") if applicant_element else "No applicant found" - print(f"applicant : {applicant}") + logger.debug(f"applicant : {applicant}") publication_date_element = await article.query_selector("div:nth-child(2) ul li:nth-child(8)") if publication_date_element: @@ -131,7 +138,7 @@ class WebScraper: publication_date = publication_date_content.strip() if publication_date_content else "No publication date found" else: publication_date = "No publication date found" - print(f"publication_date : {publication_date}") + logger.debug(f"publication_date : {publication_date}") registration_date_element = await article.query_selector("div:nth-child(2) ul li:nth-child(6)") if registration_date_element: @@ -139,9 +146,9 @@ class WebScraper: registration_date = registration_date_content.strip() if registration_date_content else "No registration date found" else: registration_date = "No registration date found" - print(f"registration_date : {registration_date}") - - if not (admin_status == "소멸" or admin_status == "ê±°ì ˆ"): + logger.debug(f"registration_date : {registration_date}") + if admin_status in status: # status는 self.set_status 리스트를 참조 + # if not (admin_status == "소멸" or admin_status == "ê±°ì ˆ"): self.results[f"result_{i+1}"] = { "ID": applno, "title": trademark_name, @@ -154,65 +161,65 @@ class WebScraper: "publication_date": publication_date, "registration_date": registration_date, } - # print(f"results : {self.results}") + # logger.debug(f"results : {self.results}") await self.navigate_to_page(self.url) return self.results else: - print("No total count element found, possibly incorrect selector or page structure has changed.") + logger.debug("No total count element found, possibly incorrect selector or page structure has changed.") except Exception as e: - print(f"오류 ë°œìƒ : {e}") + logger.debug(f"오류 ë°œìƒ : {e}") return None async def download_image(self, url, applno): """ì´ë¯¸ì§€ë¥¼ 비ë™ê¸°ì ìœ¼ë¡œ 다운로드하고 applno를 íŒŒì¼ ì´ë¦„으로 사용하여 저장합니다.""" async with aiohttp.ClientSession() as session: - print(f"download_image session Start!!") + logger.debug(f"download_image session Start!!") async with session.get(url) as response: - print(f"download_image url : {url}") + logger.debug(f"download_image url : {url}") if response.status == 200: filename = f"{applno}.jpeg" async with aiofiles.open(filename, 'wb') as file: content = await response.read() await file.write(content) - print(f"ì´ë¯¸ì§€ê°€ 성공ì ìœ¼ë¡œ 저장ë˜ì—ˆìŠµë‹ˆë‹¤: {filename}") + logger.debug(f"ì´ë¯¸ì§€ê°€ 성공ì ìœ¼ë¡œ 저장ë˜ì—ˆìŠµë‹ˆë‹¤: {filename}") else: - print(f"ì´ë¯¸ì§€ 다운로드 실패: HTTP {response.status}") + logger.debug(f"ì´ë¯¸ì§€ 다운로드 실패: HTTP {response.status}") async def fetch_image_data(self, url): """주어진 URL로부터 ì´ë¯¸ì§€ ë°ì´í„°ë¥¼ 비ë™ê¸°ì ìœ¼ë¡œ 가져와 반환합니다.""" async with aiohttp.ClientSession() as session: - # print(f"download_image session Start!!") + # logger.debug(f"download_image session Start!!") async with session.get(url) as response: - print(f"download_image url : {url}") + logger.debug(f"download_image url : {url}") if response.status == 200: - # print(f"response : {response}") + # logger.debug(f"response : {response}") content_type = response.headers.get('Content-Type', '') # await 제거 - print(f"content_type : {content_type}") + logger.debug(f"content_type : {content_type}") if 'image' in content_type or 'octet-stream' in content_type: - # print(f"image content type or octet-stream : {content_type}") + # logger.debug(f"image content type or octet-stream : {content_type}") return await response.read() else: try: # Content-Typeì´ ì´ë¯¸ì§€ê°€ 아니면, ë°ì´í„°ë¥¼ ì´ë¯¸ì§€ë¡œ 변환 data = await response.read() - # print(f"Content-Typeì´ ì´ë¯¸ì§€ê°€ 아님 : {data}") + # logger.debug(f"Content-Typeì´ ì´ë¯¸ì§€ê°€ 아님 : {data}") image = Image.open(BytesIO(data)) with BytesIO() as buffer: image.save(buffer, 'JPEG') - print(f"image 를 JPEG로 저장") + logger.debug(f"image 를 JPEG로 저장") return buffer.getvalue() except Exception as e: - print(f"ì´ë¯¸ì§€ 변환 실패: {e}") + logger.debug(f"ì´ë¯¸ì§€ 변환 실패: {e}") return None else: - print(f"ì´ë¯¸ì§€ 다운로드 실패: HTTP {response.status}") + logger.debug(f"ì´ë¯¸ì§€ 다운로드 실패: HTTP {response.status}") return None # async def load_category_descriptions(self, filename): # """JSON 파ì¼ì—서 카테고리 ì„¤ëª…ì„ ë¹„ë™ê¸°ì ìœ¼ë¡œ 로드합니다.""" # async with aiofiles.open(filename, 'r', encoding='utf-8') as file: # content = await file.read() - # print(f"JSON 파ì¼ì—서 카테고리 ì„¤ëª…ì„ ë¹„ë™ê¸°ì ìœ¼ë¡œ 로드합니다: {content}") + # logger.debug(f"JSON 파ì¼ì—서 카테고리 ì„¤ëª…ì„ ë¹„ë™ê¸°ì ìœ¼ë¡œ 로드합니다: {content}") # return json.loads(content) def load_category_descriptions(self, filename): @@ -222,7 +229,7 @@ class WebScraper: def add_category_description(self, category_code): """주어진 카테고리 ì½”ë“œì— ë”°ë¼ ì„¤ëª…ì„ ë°˜í™˜í•©ë‹ˆë‹¤.""" - print(f"add_category_description => category_code: {category_code}") + logger.debug(f"add_category_description => category_code: {category_code}") return self.category_description.get(category_code, "카테고리 ì„¤ëª…ì„ ì°¾ì„ ìˆ˜ 없습니다.") diff --git a/src/web_scraper_with_re.py b/src/web_scraper_with_re.py index 447d492..96c85aa 100644 --- a/src/web_scraper_with_re.py +++ b/src/web_scraper_with_re.py @@ -1,7 +1,10 @@ from requests_html import HTMLSession import json import requests +import logging +# 로거 ì¸ìŠ¤í„´ìŠ¤ 가져오기 +logger = logging.getLogger('default_logger') class WebScraper: def __init__(self): self.session = HTMLSession() @@ -23,7 +26,7 @@ class WebScraper: """ì§€ì •ëœ URL로 ì´ë™í•˜ê³  페ì´ì§€ë¥¼ 로드합니다.""" response = self.session.get(url) response.html.render() # í•„ìš” 시 JavaScript 실행 - print("Page loaded successfully.") + logger.debug("Page loaded successfully.") return response def search_for_term(self, term): @@ -43,17 +46,17 @@ class WebScraper: search_response.html.render() return search_response else: - print("í¼ì˜ action URLì„ ì°¾ì„ ìˆ˜ 없습니다.") + logger.debug("í¼ì˜ action URLì„ ì°¾ì„ ìˆ˜ 없습니다.") else: - print("검색 í¼ì„ ì°¾ì„ ìˆ˜ 없습니다.") + logger.debug("검색 í¼ì„ ì°¾ì„ ìˆ˜ 없습니다.") except Exception as e: - print(f"검색 실행 중 오류 ë°œìƒ: {e}") + logger.debug(f"검색 실행 중 오류 ë°œìƒ: {e}") # response.html.render(script=script, reload=False) # # response.html.find('#keywordTextarea', first=True).fill(term) # self.page.evaluate(f"document.querySelector('#keywordTextarea').value = '{term}';") - # print(f"검색어 ìž…ë ¥: {term}") + # logger.debug(f"검색어 ìž…ë ¥: {term}") # input_field = response.html.find('#keywordTextarea', first=True) # script = f"document.querySelector('#keywordTextarea').value = '{term}';" # response.html.page.evaluate(script) # JavaScript 실행 @@ -64,7 +67,7 @@ class WebScraper: articles = response.html.find('form#listForm section.search_section article') if not articles: - print("검색 결과가 없습니다.") + logger.debug("검색 결과가 없습니다.") return None # Store results in a structured format @@ -87,9 +90,9 @@ class WebScraper: filename = f"{applno}.jpeg" with open(filename, 'wb') as file: file.write(response.content) - print(f"ì´ë¯¸ì§€ê°€ 성공ì ìœ¼ë¡œ 저장ë˜ì—ˆìŠµë‹ˆë‹¤: {filename}") + logger.debug(f"ì´ë¯¸ì§€ê°€ 성공ì ìœ¼ë¡œ 저장ë˜ì—ˆìŠµë‹ˆë‹¤: {filename}") else: - print(f"ì´ë¯¸ì§€ 다운로드 실패: HTTP {response.status_code}") + logger.debug(f"ì´ë¯¸ì§€ 다운로드 실패: HTTP {response.status_code}") def fetch_image_data(self, url): """주어진 URL로부터 ì´ë¯¸ì§€ ë°ì´í„°ë¥¼ ì§ì ‘ 가져와 반환합니다.""" @@ -97,7 +100,7 @@ class WebScraper: if response.status_code == 200: return response.content else: - print(f"ì´ë¯¸ì§€ 다운로드 실패: HTTP {response.status_code}") + logger.debug(f"ì´ë¯¸ì§€ 다운로드 실패: HTTP {response.status_code}") return None def close_browser(self): @@ -107,4 +110,4 @@ class WebScraper: # # 사용 예시 # scraper = WebScraper() # results = scraper.search_for_term("특허") -# print(results) +# logger.debug(results)