Compare commits

..

No commits in common. "master" and "v1.1" have entirely different histories.
master ... v1.1

257 changed files with 433 additions and 5859 deletions

8
.gitignore vendored
View File

@ -1,5 +1,4 @@
Lib/
libs/
Scripts/
__pycache__/
dist/
@ -9,10 +8,3 @@ build/
*.log.*
pyvenv.cfg
search_history.json
# user_data 내 모든 파일과 폴더 무시
user_data/**
# Default/Extensions 폴더만 포함시키기
!user_data/Default/
!user_data/Default/Extensions/
!user_data/Default/Extensions/**

18
config.ini Normal file
View File

@ -0,0 +1,18 @@
[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 = ['°ÅÀý', 'µî·Ï']

View File

@ -5,18 +5,20 @@
"maxVolumeSet": 160,
"addFeeInterval": 5,
"addFeeSetting": 20,
"addFee": 5000,
"fontSize": 13,
"addFee": 1000,
"fontSize": 10,
"weightInterval": 0.5,
"setSaveSetting": true,
"favoriteDelv": "\ub178\ube60\uafb8\ud574\uc6b4(\ubc30\uc1a1\ube44)"
},
"Kipris": {
"use_kipris": true,
"usage_mode": "api",
"api_key": "X9Tz3JqC/JcCwxnNewA6qdloIN6QFIitVBgS1a2KVDYk1AmddaDTvzr6+t3dyLZV3gh2TPXdNhxsRQwaKP673Q==",
"usage_mode": "web",
"api_key": "",
"set_status": [
"\ub4f1\ub85d"
"\ub4f1\ub85d",
"\ucde8\ud558",
"\ud3ec\uae30"
]
}
}

383
delv.py
View File

@ -1,11 +1,9 @@
import sys
import configparser
import os, signal
import os
import pandas as pd
import logging
from PyQt5.QtCore import Qt
from qasync import QEventLoop # qasync 이벤트 루프 임포트
from PyQt5 import QtWidgets, QtCore
from PyQt5.QtGui import QFont
import re, json
@ -16,19 +14,15 @@ 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.OptionTranslator import optionTrans
from src.search_display import TrademarkSearchDisplay
from src.result_widget import ResultWidget
from forex_python.converter import CurrencyRates
from currency_converter import CurrencyConverter
from src.kiprisEvent import LineEditWithHistory
from qfluentwidgets import IndeterminateProgressRing, setTheme, toggleTheme, Theme
# def minimize_console():
# """ 콘솔 창을 최소화하는 함수 """
# hwnd = ctypes.windll.kernel32.GetConsoleWindow()
# if hwnd != 0:
# ctypes.windll.user32.ShowWindow(hwnd, 6) # SW_MINIMIZE
def minimize_console():
""" 콘솔 창을 최소화하는 함수 """
hwnd = ctypes.windll.kernel32.GetConsoleWindow()
if hwnd != 0:
ctypes.windll.user32.ShowWindow(hwnd, 6) # SW_MINIMIZE
class DeliveryFeeCalculator(QtWidgets.QWidget):
@ -38,9 +32,6 @@ class DeliveryFeeCalculator(QtWidgets.QWidget):
# self.config = configparser.ConfigParser()
self.config_path = 'config.ini'
self.is_dark_theme = False # 다크 테마 상태 저장
self.dialogs = [] # 열린 다이얼로그와 창들을 저장할 리스트
self.use_kipris = False
self.usage_mode = "web"
self.api_key = ""
@ -49,10 +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.history_model = QtCore.QStringListModel()
self.maxWeightSet = 25
self.maxLengthSet = 100
@ -69,14 +58,11 @@ class DeliveryFeeCalculator(QtWidgets.QWidget):
self.addFeeSetting = 20
self.addFeeInterval = 5
self.setUSD = None
self.setCNY = None
self.currentCurrency = None
# self.searchDisplay = TrademarkSearchDisplay()
self.searchDisplay = TrademarkSearchDisplay()
self.searchDisplayWidget = ResultWidget()
self.currencyInfo = CurrencyRates()
self.currencyConv = CurrencyConverter()
self.favoriteDelv = ""
@ -122,40 +108,6 @@ class DeliveryFeeCalculator(QtWidgets.QWidget):
}
self.settingDialog = SettingsDialog(parent=self, initial_settings=self.user_settings)
currencis = ['USD', 'CNY']
try:
# CurrencyConverter로 환율 정보 가져오기
self.setUSD = int(self.currencyConv.convert(1, 'USD', 'KRW'))
logger.debug(f"CurrencyConverter USD to KRW: {self.setUSD}")
self.setCNY = int(self.currencyConv.convert(1, 'CNY', 'KRW'))
logger.debug(f"CurrencyConverter CNY to KRW: {self.setCNY}")
except Exception as e:
logger.error(f"CurrencyConverter 에서 환율 조회 중 에러발생: {e}")
print(f"CurrencyConverter 에러, forex-python에서 값을 가져옵니다.")
try:
# forex-python으로 환율 정보 가져오기
self.setUSD = int(self.currencyRates.get_rate('USD', 'KRW'))
logger.debug(f"forex-python USD to KRW: {self.setUSD}")
self.setCNY = int(self.currencyRates.get_rate('CNY', 'KRW'))
logger.debug(f"forex-python CNY to KRW: {self.setCNY}")
except Exception as e2:
logger.error(f"forex-python 에서 환율 조회 중 에러발생: {e2}")
print(f"forex-python 에러, 기본값을 사용합니다.")
# 기본 환율 설정
self.setUSD = 1350
self.setCNY = 195
logger.debug(f"기본 USD: {self.setUSD}, 기본 CNY: {self.setCNY}")
# 현재 통화를 CNY로 설정
self.currentCurrency = self.setCNY
def saveSettings(self):
""" 설정을 JSON 파일에 저장합니다. """
try:
@ -246,35 +198,111 @@ class DeliveryFeeCalculator(QtWidgets.QWidget):
logger.info("기본 설정이 생성되었습니다.")
# def loadSettings_ini(self):
# """ 설정 파일을 불러옵니다. """
# try:
# if not os.path.exists(self.config_path):
# self.create_default_settings()
# self.config.read(self.config_path)
# self.maxWeightSet = self.config.getint('Settings', 'maxWeightSet', fallback=25)
# self.maxLengthSet = self.config.getint('Settings', 'maxLengthSet', fallback=100)
# self.maxVolumeSet = self.config.getint('Settings', 'maxVolumeSet', fallback=160)
# self.addFeeInterval = self.config.getint('Settings', 'addFeeInterval', fallback=5)
# self.addFeeSetting = self.config.getint('Settings', 'addFeeSetting', fallback=20)
# self.addFee = self.config.getint('Settings', 'addFee', fallback=1000)
# self.fontSize = self.config.getint('Settings', 'fontSize', fallback=14)
# self.weightInterval = self.config.getfloat('Settings', 'weightInterval', fallback=0.5)
# self.setSaveSetting = self.config.getboolean('Settings', 'setSaveSetting', fallback=False)
# self.favoriteDelv = self.config.get('Settings', 'favoriteDelv', fallback="노빠꾸해운(배송비)")
# self.use_kipris = self.config.getboolean('Kipris', 'use_Kipris', fallback=False)
# self.usage_mode = self.config.get('Kipris', 'usage_mode', fallback="web")
# 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}")
# except Exception as e:
# logger.error(f"설정을 불러오는 중 오류가 발생했습니다: {e}", exc_info=True)
# def saveSettings_ini(self):
# """ 설정을 config.ini 파일에 저장합니다. """
# try:
# if not self.config.has_section('Settings'):
# self.config.add_section('Settings')
# self.config.set('Settings', 'maxWeightSet', str(self.maxWeightSet))
# self.config.set('Settings', 'maxLengthSet', str(self.maxLengthSet))
# self.config.set('Settings', 'maxVolumeSet', str(self.maxVolumeSet))
# self.config.set('Settings', 'addFeeInterval', str(self.addFeeInterval))
# self.config.set('Settings', 'addFeeSetting', str(self.addFeeSetting))
# self.config.set('Settings', 'addFee', str(self.addFee))
# self.config.set('Settings', 'fontSize', str(self.fontSize))
# self.config.set('Settings', 'weightInterval', str(self.weightInterval))
# self.config.set('Settings', 'setSaveSetting', str(self.setSaveSetting))
# self.config.set('Settings', 'favoriteDelv', str(self.favoriteDelv))
# if not self.config.has_section('Kipris'):
# self.config.add_section('Kipris')
# self.config.set('Kipris', 'use_kipris', str(self.use_kipris))
# self.config.set('Kipris', 'usage_mode', str(self.usage_mode))
# self.config.set('Kipris', 'api_key', str(self.api_key))
# self.config.set('Kipris', 'set_status', str(self.set_status))
# with open(self.config_path, 'w') as configfile:
# self.config.write(configfile)
# except Exception as e:
# logger.error(f"설정을 저장하는 중 오류가 발생했습니다: {e}", exc_info=True)
# def create_default_settings_ini(self):
# """ 기본 설정을 생성합니다. """
# self.config['Settings'] = {
# 'maxWeightSet': '25',
# 'maxLengthSet': '100',
# 'maxVolumeSet': '160',
# 'addFeeInterval': '5',
# 'addFeeSetting': '20',
# 'addFee': '1000',
# 'fontSize': '14',
# 'weightInterval': '0.5',
# 'setSaveSetting': 'False',
# 'favoriteDelv': "노빠꾸해운(배송비)",
# }
# self.config['Kipris'] = {
# 'use_kipris': 'False',
# 'usage_mode': 'web',
# 'api_key': '',
# 'set_status': '[등록]',
# }
# with open(self.config_path, 'w') as configfile:
# self.config.write(configfile)
def add_history(self, keyword) :
if keyword:
current_history = self.history_model.stringList()
if keyword not in current_history: # 중복된 검색어가 아니면 추가
current_history.append(keyword)
self.history_model.setStringList(current_history)
logger.debug(f"검색어 [{keyword}] 히스토리에 추가")
if keyword and keyword not in self.history: # 중복된 검색어가 아니면 추가
self.history.append(keyword)
print(f"검색어 [{keyword}] 히스토리에 추가")
def load_history(self):
try:
with open("search_history.json", "r") as file:
history_list = json.load(file)
self.history_model.setStringList(history_list)
logger.debug(f"self.history file loaded: {history_list}")
self.history = json.load(file)
print(f"self.history file loaded{self.history}")
except (FileNotFoundError, json.JSONDecodeError):
self.history_model.setStringList([])
logger.debug(f"self.history: []")
self.history = []
print(f"self.history{self.history}")
def save_history(self):
with open("search_history.json", "w") as file:
json.dump(self.history_model.stringList(), file)
json.dump(self.history, file)
def show_history_menu(self, event):
current_history = self.history_model.stringList()
if current_history:
if self.history:
menu = QtWidgets.QMenu(self)
for keyword in current_history:
for keyword in self.history:
menu.addAction(keyword, lambda k=keyword: self.kipris_edit.setText(k))
menu.exec_(self.kipris_edit.mapToGlobal(event.pos()))
@ -296,16 +324,6 @@ class DeliveryFeeCalculator(QtWidgets.QWidget):
# 이벤트 처리 완료를 알림
event.accept()
# 프로그램 완전히 종료
QtWidgets.QApplication.quit() # Qt 애플리케이션 종료
# 프로세스 강제 종료 (필요 시 사용)
os.kill(os.getpid(), signal.SIGTERM)
def add_dialog(self, dialog):
"""열린 다이얼로그나 창을 리스트에 추가"""
self.dialogs.append(dialog)
def initUI(self):
self.resize(300, 600) # 창 크기 조정
self.center()
@ -581,29 +599,12 @@ 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(f"키프리스 검색")
self.kipris_completer = QtWidgets.QCompleter(self.history_model, self)
self.kipris_completer.setCaseSensitivity(Qt.CaseInsensitive)
self.kipris_completer.setCompletionMode(QtWidgets.QCompleter.PopupCompletion)
self.kipris_label = QtWidgets.QLabel("키프리스 검색")
self.kipris_edit = QtWidgets.QLineEdit()
self.kipris_edit = LineEditWithHistory(self.kipris_completer, self)
self.kipris_edit.setCompleter(self.kipris_completer)
self.kipris_btn = QtWidgets.QPushButton("검색")
self.kipris_btn.clicked.connect(self.kipris_btn_clicked)
self.kipris_edit.returnPressed.connect(self.kipris_btn_clicked)
self.spinner = IndeterminateProgressRing(self)
self.spinner.setFixedSize(50, 50)
self.spinner.setVisible(False)
self.kipris_layout.addWidget(self.spinner)
# self.kipris_edit.mousePressEvent = self.show_history_menu
self.kipris_edit.mousePressEvent = self.show_history_menu
self.kipris_layout.addWidget(self.kipris_label)
self.kipris_layout.addWidget(self.kipris_edit)
self.kipris_layout.addWidget(self.kipris_btn)
@ -619,8 +620,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_h2layout)
self.addInfo_vlayout.addLayout(self.addInfo_h1layout)
self.addInfo_vlayout.addLayout(self.addInfo_h2layout)
self.addInfoWidget.setLayout(self.addInfo_vlayout)
self.addInfoWidget.setVisible(True)
self.setUSD_label = QtWidgets.QLabel(f"[{self.setUSD}]USD/KRW")
@ -646,22 +647,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(True)
self.addInfo4_btn.clicked.connect(self.addInfo4_btn_clicked)
self.addInfo_h2layout.addWidget(self.addInfo4_btn)
# 다크 테마 토글 버튼 추가
self.theme_button = QtWidgets.QPushButton("Dark Theme", self)
self.theme_button.setEnabled(False)
self.theme_button.clicked.connect(self.toggle_theme)
self.addInfo_h2layout.addWidget(self.theme_button, 0, Qt.AlignHCenter)
# self.addInfo_layout.setStretch(0,3)
# self.addInfo_layout.setStretch(1,6)
# self.addInfo_layout.setStretch(2,3)
@ -669,35 +659,6 @@ 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)
@ -725,24 +686,25 @@ class DeliveryFeeCalculator(QtWidgets.QWidget):
self.setWindowTitle('배송비 계산기')
def toggle_theme(self):
if self.is_dark_theme:
try:
# setTheme(Theme.LIGHT)
toggleTheme()
print("라이트 토글")
self.is_dark_theme = False
except Exception as e:
print(f"라이트 토글 중 에러 : {e}")
else:
try:
# setTheme(Theme.DARK)
toggleTheme()
# def initSettings_for_kipris_ori(self):
# if self.kiprisAPI:
# # 현재 객체가 적절한 타입인지 확인
# current_type = type(self.kiprisAPI)
# target_type = Kipris_API if self.usage_mode == 'api' else Kipris_WEB
print("다크 토글")
self.is_dark_theme = True
except Exception as e:
print(f"다크 토글 중 에러 : {e}")
# if current_type is not target_type:
# # 기존 객체가 다른 타입이면 삭제하고 새로 생성
# print(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}")
# else:
# print(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}")
def initSettings_for_kipris(self):
if self.kiprisAPI:
@ -752,7 +714,7 @@ class DeliveryFeeCalculator(QtWidgets.QWidget):
if current_type is not target_type:
# 기존 객체가 다른 타입이면 삭제하고 새로 생성
logger.debug(f"기존 {self.kiprisAPI} 객체를 삭제하고 새 객체를 생성합니다.")
print(f"기존 {self.kiprisAPI} 객체를 삭제하고 새 객체를 생성합니다.")
if isinstance(self.kiprisAPI, AsyncWebSearchWorker):
self.kiprisAPI.deleteLater() # 비동기 작업자는 Qt 객체로 관리되므로 deleteLater 사용
self.kiprisAPI = None
@ -760,20 +722,18 @@ class DeliveryFeeCalculator(QtWidgets.QWidget):
self.kiprisAPI = Kipris_API(self.api_key) # 새 객체 생성
else:
web_scraper = WebScraper() # WebScraper 인스턴스 생성
self.web_scraper = web_scraper
self.kiprisAPI = AsyncWebSearchWorker(self.web_scraper, "") # 초기 키워드는 비워두기
logger.debug(f"{self.usage_mode.upper()} 방식 kiprisAPI 객체 생성: {self.kiprisAPI}")
self.kiprisAPI = AsyncWebSearchWorker(web_scraper, "") # 초기 키워드는 비워두기
print(f"{self.usage_mode.upper()} 방식 kiprisAPI 객체 생성: {self.kiprisAPI}")
else:
logger.debug(f"기존에 적절한 {self.kiprisAPI} 객체가 이미 존재합니다.")
print(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, "") # 초기 키워드는 비워두기
logger.debug(f"{self.usage_mode.upper()} 방식 kiprisAPI 객체 생성: {self.kiprisAPI}")
print(f"{self.usage_mode.upper()} 방식 kiprisAPI 객체 생성: {self.kiprisAPI}")
def addInfo1_btn_clicked(self):
pass
@ -785,10 +745,7 @@ class DeliveryFeeCalculator(QtWidgets.QWidget):
pass
def addInfo4_btn_clicked(self):
# optionTrans 클래스를 사용해 다이얼로그 창을 띄움
self.trans_dialog = optionTrans(self)
self.trans_dialog.show()
self.add_dialog(self.trans_dialog) # 열린 다이얼로그를 리스트에 추가
pass
def showSettingsDialog(self):
@ -797,7 +754,6 @@ class DeliveryFeeCalculator(QtWidgets.QWidget):
self.usage_mode = self.settingDialog.usage_mode
self.api_key = self.settingDialog.api_key
self.set_status = self.settingDialog.set_status
self.add_dialog(self.settingDialog) # 열린 다이얼로그를 리스트에 추가
self.kipris_Visible()
@ -805,7 +761,6 @@ 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)
@ -1106,26 +1061,6 @@ 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
@ -1140,12 +1075,10 @@ class DeliveryFeeCalculator(QtWidgets.QWidget):
logger.debug(f"키프리스 검색버튼 클릭 : 키워드 = [{self.search_keyword}]")
# result = self.kiprisAPI.run(self.search_keyword, self.set_status)
# logger.debug(f"result {result}")
# print(f"result {result}")
if self.search_keyword.strip(): # 검색어가 비어있지 않은 경우에만 검색 수행
self.spinner.setVisible(True) # Show spinner
logger.debug(f"검색 호출방식 : {self.usage_mode}")
print(f"검색 호출방식 : {self.usage_mode}")
if self.usage_mode == 'web':
self.handle_search_for_web(self.search_keyword)
if self.usage_mode == 'api':
@ -1156,20 +1089,16 @@ class DeliveryFeeCalculator(QtWidgets.QWidget):
if self.asyncWorker: # 기존에 비동기 작업자가 존재한다면
self.asyncWorker.thread.quit() # 기존 스레드 종료
logger.debug(f"키프리스 검색버튼 클릭 : 키워드 = [{keyword}]")
print(f"키프리스 검색버튼 클릭 : 키워드 = [{keyword}]")
self.asyncWorker = AsyncWebSearchWorker(keyword, self.set_status) # 새 비동기 작업자 생성
self.asyncWorker.finished.connect(self.display_results_for_web) # 완료 시그널을 결과 표시 함수에 연결
self.asyncWorker.start() # 비동기 작업 시작
logger.debug("비동기 검색 시작")
print("비동기 검색 시작")
def display_results_for_web(self, result, elapsed_time):
# logger.debug(f"result : {result}")
searchType = 'web'
logger.debug(f"display_results_for_web - currentURL : {self.web_scraper.currentURL}")
self.spinner.setVisible(False) # Hide spinner
self.searchDisplayWidget.clear_results()
self.add_dialog(self.searchDisplayWidget) # 열린 다이얼로그를 리스트에 추가
self.searchDisplayWidget.show_results(result, searchType, elapsed_time, self.web_scraper.currentURL)
print(f"result : {result}")
self.searchDisplayWidget.show_results(result)
# self.searchDisplay.display_web_results(result, elapsed_time)
# self.searchDisplay.show()
@ -1184,41 +1113,33 @@ class DeliveryFeeCalculator(QtWidgets.QWidget):
if self.searchThread is not None and self.searchThread.isRunning():
self.searchThread.quit() # 이전 스레드가 실행 중이라면 안전하게 종료
logger.debug("기존 쓰레드가 존재하므로 기존 쓰레드 종료")
logger.debug(f"키프리스 검색버튼 클릭 : 키워드 = [{keyword}]")
print("기존 쓰레드가 존재하므로 기존 쓰레드 종료")
print(f"키프리스 검색버튼 클릭 : 키워드 = [{keyword}]")
worker = APISearchWorker(self.kiprisAPI, keyword, self.set_status)
# worker = SearchWorker(self.kiprisAPI, keyword, self.set_status)
logger.debug("워커 생성")
print("워커 생성")
self.searchThread = SearchThread(worker)
logger.debug("쓰레드 생성")
print("쓰레드 생성")
worker.finished.connect(self.display_results_for_api)
self.searchThread.finished.connect(self.clear_thread_reference)
self.searchThread.start_search()
logger.debug("검색 시작")
print("검색 시작")
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.spinner.setVisible(False) # Hide spinner
self.searchDisplayWidget.clear_results()
self.add_dialog(self.searchDisplayWidget) # 열린 다이얼로그를 리스트에 추가
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)
self.widthInput.setValue(1)
self.heightInput.setValue(1)
self.weightInput.setValue(1)
def showHelp(self):
# 도움말 내용 표시
@ -1247,28 +1168,10 @@ class DeliveryFeeCalculator(QtWidgets.QWidget):
self.setComboBox()
if __name__ == '__main__':
# minimize_console()
# enable dpi scale
QtWidgets.QApplication.setHighDpiScaleFactorRoundingPolicy(
Qt.HighDpiScaleFactorRoundingPolicy.PassThrough)
QtWidgets.QApplication.setAttribute(Qt.AA_EnableHighDpiScaling)
QtWidgets.QApplication.setAttribute(Qt.AA_UseHighDpiPixmaps)
minimize_console()
app = QtWidgets.QApplication(sys.argv)
# qasync 이벤트 루프를 생성하여 PyQt5의 이벤트 루프와 결합
loop = QEventLoop(app)
asyncio.set_event_loop(loop) # asyncio의 이벤트 루프를 qasync로 설정
app.setStyle('Fusion')
logger = setup_logger('default_logger', 'delivery_calc.log', level=logging.DEBUG)
logger = setup_logger('default_logger', 'delivery_calc.log', level=logging.INFO)
ex = DeliveryFeeCalculator(logger)
ex.show()
# 이벤트 루프 시작
with loop:
loop.run_forever()
sys.exit(app.exec_())

BIN
delv.xlsx

Binary file not shown.

View File

@ -3,10 +3,12 @@
a = Analysis(
['delv.py'],
pathex=[],
pathex=['H:\\py\\delvfee'],
binaries=[],
datas=[],
hiddenimports=[],
hiddenimports=[
'sip', 'jinja2'
],
hookspath=[],
hooksconfig={},
runtime_hooks=[],

Binary file not shown.

1
search_history.json Normal file
View File

@ -0,0 +1 @@
["\uc2a4\ud0a4\uc5d0\uc774\ud2b8", "\ub86f\ub370", "\uc2a4\ud0a4\uc5d0\uc774\ud2b8", "\ub86f\ub370", "\uc2a4\ud0a4\uc5d0\uc774\ud2b8", "\ub86f\ub370", "\uc368\uc9c0\uc624"]

View File

@ -1,26 +0,0 @@
from cx_Freeze import setup, Executable
# Additional build options
build_exe_options = {
"packages": [],
"excludes": [],
"include_files": ["delv.ico", "delv.xlsx"],
"optimize": 0
}
# Target executable
target = Executable(
script="delv.py",
base="Win32GUI", # Use "Win32GUI" for a GUI application on Windows
target_name="Deliver_Calc",
icon="delv.ico"
)
# Setup configuration
setup(
name="Deliver_Calc",
version="1.4",
description="Delivery Calculation Tool",
options={"build_exe": build_exe_options},
executables=[target]
)

View File

@ -3,10 +3,7 @@ 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__()
@ -166,7 +163,7 @@ class MainApp(QWidget):
self.results_widget.show()
except Exception as e:
logger.debug(f"Error displaying results: {e}")
print(f"Error displaying results: {e}")
def close_results_widget(self):

View File

@ -1,110 +0,0 @@
import os
import asyncio
from PyQt5.QtWidgets import QDialog, QVBoxLayout, QPushButton
from playwright.async_api import async_playwright
class optionTrans(QDialog):
def __init__(self, parent=None):
super().__init__(parent)
self.browser = None
self.page = None
self.macro_running = False
self.init_ui()
def init_ui(self):
self.setWindowTitle("Macro Control")
layout = QVBoxLayout()
# 실행 버튼
self.start_button = QPushButton("실행")
self.start_button.clicked.connect(self.start_browser_task) # 실행 버튼을 비동기 작업과 연결
layout.addWidget(self.start_button)
# 중지 버튼
self.stop_button = QPushButton("중지")
self.stop_button.clicked.connect(self.stop_browser_task)
layout.addWidget(self.stop_button)
# 매크로 1 버튼
self.macro1_button = QPushButton("매크로 1 실행")
self.macro1_button.clicked.connect(self.start_macro1_task)
layout.addWidget(self.macro1_button)
# 매크로 2 버튼 (아직 구현하지 않음)
self.macro2_button = QPushButton("매크로 2 실행")
layout.addWidget(self.macro2_button)
self.setLayout(layout)
def start_browser_task(self):
# 비동기 작업을 생성하고 이벤트 루프에 실행
asyncio.create_task(self.run_browser())
def stop_browser_task(self):
asyncio.create_task(self.stop_macro())
def start_macro1_task(self):
asyncio.create_task(self.run_macro1())
def get_latest_version(self, directory):
# 디렉터리 내에서 버전 폴더를 찾아서 숫자로 정렬한 뒤 최신 버전을 반환
versions = os.listdir(directory)
versions.sort(key=lambda s: [int(part) for part in s.replace('_', '.').split('.')])
return versions[-1] # 최신 버전 반환
async def run_browser(self):
if self.browser is None:
# main.py가 위치한 디렉터리 경로
current_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # OptionTranslator.py 기준 상위 폴더로 이동
user_data_dir = os.path.join(current_dir, "user_data")
# 확장 프로그램 경로 설정 (동적으로 최신 버전의 확장 프로그램 폴더를 찾음)
extension_dir1 = os.path.join(user_data_dir, "Default", "Extensions", "jlcdjppbpplpdgfeknhioedbhfceaben")
# 확장 프로그램이 존재하는지 확인
if not os.path.exists(extension_dir1):
raise FileNotFoundError(f"확장 프로그램 디렉터리가 존재하지 않습니다: {extension_dir1}")
# 최신 버전 폴더 찾기 (숫자 기반 비교)
extension_version1 = self.get_latest_version(extension_dir1)
extension_path1 = os.path.join(extension_dir1, extension_version1)
# 최신 버전 폴더 찾기 (숫자 기반 비교)
extension_version1 = self.get_latest_version(extension_dir1) # self로 메서드 호출
extension_path1 = os.path.join(extension_dir1, extension_version1)
self.playwright = await async_playwright().start()
self.browser = await self.playwright.chromium.launch_persistent_context(
user_data_dir=user_data_dir,
headless=False,
args=[
f'--disable-extensions-except={extension_path1}',
f'--load-extension={extension_path1}'
]
)
self.page = await self.browser.new_page()
await self.page.goto('https://percenty.co.kr')
async def stop_macro(self):
if self.browser:
await self.browser.close()
self.browser = None
async def run_macro1(self):
if self.page and not self.macro_running:
self.macro_running = True
try:
element_to_right_click = await self.page.query_selector('css_selector_for_element')
await element_to_right_click.click(button="right") # 우클릭
translate_button = await self.page.query_selector('css_selector_for_translate')
await translate_button.click() # 번역 버튼 클릭
second_element = await self.page.query_selector('css_selector_for_drag')
await second_element.hover() # 요소 위에 마우스 올리기
await self.page.mouse.down()
await self.page.mouse.move(150, 0) # 오른쪽으로 150픽셀 이동
await self.page.mouse.up()
finally:
self.macro_running = False

View File

@ -1,16 +0,0 @@
from PyQt5.QtWidgets import QLineEdit
from PyQt5.QtCore import Qt
class LineEditWithHistory(QLineEdit):
def __init__(self, completer, parent=None):
super().__init__(parent)
self.completer = completer
def keyPressEvent(self, event):
if event.key() == Qt.Key_Down:
if self.completer.popup().isVisible():
event.ignore()
else:
self.completer.complete()
else:
super().keyPressEvent(event)

View File

@ -1,12 +1,9 @@
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(dict, float)
finished = pyqtSignal(list, float)
def __init__(self, kiprisObject, keyword, set_status):
super().__init__()
@ -16,9 +13,9 @@ class APISearchWorker(QObject):
def run(self):
start_time = time.time() # 검색 시작 시간
logger.debug(f"Search keyword : [{self.keyword}], self.set_status : [{self.set_status}]")
print(f"Search keyword : [{self.keyword}], self.set_status : [{self.set_status}]")
result = self.kiprisObject.run(self.keyword, self.set_status)
logger.debug(f"Search finished | result \n {result}")
print(f"Search finished | result \n [{result}]")
elapsed_time = time.time() - start_time # 경과 시간 계산
self.finished.emit(result, elapsed_time)
@ -39,7 +36,7 @@ class SearchThread(QThread):
def handle_finished(self, result, elapsed_time):
# 검색 작업이 완료되면 이 시그널이 발생합니다.
logger.debug(f"Search finished : [{elapsed_time}]초 경과")
print(f"Search finished : [{elapsed_time}]초 경과")
class AsyncWebSearchWorker(QObject):
@ -71,7 +68,7 @@ class AsyncWebSearchWorker(QObject):
elapsed_time = time.time() - self.start_time # 소요 시간 계산
self.finished.emit(result, elapsed_time) # 작업 완료 신호 전송
except Exception as e:
logger.debug(f"Error in AsyncWebSearchWorker: {e}")
print(f"Error in AsyncWebSearchWorker: {e}")
self.finished.emit(None, 0) # 에러 발생 시 None 전송
finally:
await self.scraper.close_Kipris() # 리소스 정리

View File

@ -1,17 +1,11 @@
import xml.etree.ElementTree as ET
import requests, json
import logging
# 로거 인스턴스 가져오기
logger = logging.getLogger('default_logger')
import requests
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 = {}
filename = 'categories.json'
self.category_description = self.load_category_descriptions(filename)
self.results = []
def fetch_and_decode(self, params):
# API 요청 및 응답 받기
@ -20,7 +14,7 @@ class Kipris_API:
decoded_data = response.content.decode('utf-8')
return decoded_data
except Exception as e:
logger.error(f"키프리스 요청 중 에러발생 : {e}")
print(f"키프리스 요청 중 에러발생 : {e}")
def parse_xml(self, xml_data, status):
# XML 데이터 파싱
@ -30,15 +24,10 @@ class Kipris_API:
status_published = 0
# 'body/items/item' 경로에 맞춰 'item' 태그를 순회하면서 필요한 데이터 추출
for i, item in enumerate(root.findall('.//body/items/item')):
for item in 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
@ -47,8 +36,7 @@ class Kipris_API:
# if application_status in ["등록", "공개"]:
if application_status in status: # status는 self.set_status 리스트를 참조
self.results[f"result_{i+1}"] = {
result = {
"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,
@ -63,16 +51,14 @@ 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,
"category_description": category_desc
"classification_code": item.find('classificationCode').text if item.find('classificationCode') is not None else None
}
# self.results.append(result)
self.results.append(result)
# 상태 개수와 총 아이템 개수 출력
logger.debug(f"검색된 item 총 개수: {total_items}")
self.results['total_count'] = total_items
logger.debug(f"등록 상태인 item 개수: {status_registered}")
logger.debug(f"공개 상태인 item 개수: {status_published}")
print(f"검색된 item 총 개수: {total_items}")
print(f"등록 상태인 item 개수: {status_registered}")
print(f"공개 상태인 item 개수: {status_published}")
def get_results(self):
return self.results
@ -87,25 +73,9 @@ class Kipris_API:
'drawing': '',
'bigDrawing': ''
}
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
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, "카테고리 설명을 찾을 수 없습니다.")

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 117 KiB

View File

@ -1,11 +1,9 @@
from PyQt5 import QtWidgets, QtCore
from PyQt5.QtCore import QUrl
from PyQt5.QtGui import QDesktopServices
from src.toggleSwitch import ToggleSwitch
import logging
# 로거 인스턴스 가져오기
logger = logging.getLogger('default_logger')
from src.toggleSwitch import ToggleSwitch
class SettingsDialog(QtWidgets.QDialog):
def __init__(self, parent=None, initial_settings=None):
super().__init__(parent)
@ -44,7 +42,6 @@ class SettingsDialog(QtWidgets.QDialog):
def setupUI(self):
logger.debug(f"setupUI 시작")
# 셋업 메인 레이아웃
self.mainLayout = QtWidgets.QVBoxLayout(self)
@ -113,7 +110,6 @@ class SettingsDialog(QtWidgets.QDialog):
self.editAPIWidget.setVisible(False)
self.mainLayout.addWidget(self.editAPIWidget)
# 체크박스만 추가
self.all_checkbox = QtWidgets.QCheckBox("전체 체크")
self.right_rejected_checkbox = QtWidgets.QCheckBox("거절")
@ -211,9 +207,7 @@ class SettingsDialog(QtWidgets.QDialog):
self.accept()
def loadSettings(self, settings):
logger.debug(f"loadSettings 시작")
# logger.debug(f"SettingsDialog settings : {settings}")
# print(f"SettingsDialog settings : {settings}")
self.use_kipris = settings.get('use_kipris', False) # 기본값 False로 설정
self.usage_mode = settings.get('usage_mode', 'web') # 기본값 'web'로 설정
@ -221,10 +215,10 @@ class SettingsDialog(QtWidgets.QDialog):
self.set_status = settings.get('set_status', []) # 기본값 빈 리스트로 설정
# 상태 업데이트 로그 출력
# logger.debug(f"SettingsDialog Loaded settings: use_kipris={self.use_kipris}, usage_mode={self.usage_mode}, api_key={self.api_key}")
# print(f"SettingsDialog Loaded settings: use_kipris={self.use_kipris}, usage_mode={self.usage_mode}, api_key={self.api_key}")
# logger.debug(f"SettingsDialog self.use_kipris : {self.use_kipris}")
# print(f"SettingsDialog self.use_kipris : {self.use_kipris}")
# UI 업데이트
self.isUseKiprisSwitch.setChecked(self.use_kipris)
self.apikeySwitch.setChecked(self.usage_mode == 'api')
@ -252,19 +246,17 @@ class SettingsDialog(QtWidgets.QDialog):
def toggleCNYexchange(self, checked):
self.exchangeCNYSwitch.setChecked(checked)
self.setCNY = checked
logger.debug(f"self.setCNY : {self.setCNY}")
print(f"self.setCNY : {self.setCNY}")
def toggleUSDexchange(self, checked):
self.exchangeUSDSwitch.setChecked(checked)
self.setUSD = checked
logger.debug(f"self.setUSD : {self.setUSD}")
print(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):
@ -272,14 +264,12 @@ 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()
@ -316,51 +306,36 @@ class SettingsDialog(QtWidgets.QDialog):
if status in self.set_status:
self.set_status.remove(status)
logger.debug(f"self.set_status : {self.set_status}")
# logger.debug("Current Status List:", self.set_status)
# print("Current Status List:", self.set_status)
def handle_all_checked(self, state):
if state == QtCore.Qt.Checked:
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)
for checkbox in self.checkboxes:
checkbox.setChecked(True)
elif state == QtCore.Qt.Unchecked:
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)
for checkbox in self.checkboxes[1:]: # "등록" 체크박스 제외
checkbox.setChecked(False)
self.checkboxes[0].setChecked(True) # "등록" 체크박스는 항상 체크
self.right_registered_checkbox.setChecked(True) # "등록" 체크박스는 항상 체크
def handle_checkbox_state_changed(self):
for checkbox in self.checkboxes:
# 글자를 진하게 만들기
font = checkbox.font()
font.setBold(checkbox.isChecked())
checkbox.setFont(font)
logger.debug(f"all_checked : {state}")
# 전체 체크 상태 업데이트
all_checked = all(checkbox.isChecked() for checkbox in self.checkboxes)
all_unchecked = all(not checkbox.isChecked() for checkbox in self.checkboxes[1:]) # "등록" 제외
# 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) # 시그널 재개
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):
@ -379,14 +354,9 @@ 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) # 외부 링크 자동 열기 비활성화
@ -417,6 +387,10 @@ class HelpDialog(QtWidgets.QDialog):
QDesktopServices.openUrl(url)
# ※ 행정 상태 도움말
# 거절 : 출원 후 특허 심사과정에서 실체적인 특허 등록요건을 만족하지 못할 경우에 심사관이 취하는 행정처분
# 등록 : 심사관이 심사한 결과 등록요건에 적합하여 설정등록을 받을 수 있다는 내용의 행정처분

View File

@ -3,10 +3,7 @@ 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
@ -45,45 +42,45 @@ class Kipris_WEB:
def run(self, term, status):
"""검색어로 검색하고 결과 수집"""
logger.debug(f"Playwright 검색시작 : 키워드 : [{term}]")
print(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")
logger.debug("검색페이지 로드 완료")
print("검색페이지 로드 완료")
if not loaded:
logger.debug("검색 결과가 시간 내에 로드되지 않았습니다.")
print("검색 결과가 시간 내에 로드되지 않았습니다.")
return None
# 검색 결과가 없는지 확인
nodata_info = self.page.query_selector(".nodata_info")
if nodata_info:
logger.debug("검색 결과가 없습니다.")
print("검색 결과가 없습니다.")
# 특정 메서드 호출 및 함수 종료
# self.handle_no_search_results()
return None
logger.debug("검색 결과 로딩 후 실제 요소 수집 시작")
print("검색 결과 로딩 후 실제 요소 수집 시작")
# 결과 로딩이 확인된 후, 실제 요소를 수집
self.page.wait_for_selector("form#listForm section.search_section", state="visible", timeout=10000)
logger.debug("listForm")
print("listForm")
total_count = self.page.text_content("form#listForm section.search_section div p span.total")
logger.debug(f"total_count : {total_count}")
print(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")
logger.debug(f"articles : {len(articles)}")
print(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"
logger.debug(f"trademark_name : {trademark_name}")
print(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"
logger.debug(f"applno : {applno}")
print(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"
@ -110,7 +107,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"
logger.debug(f"아이템 정보 변수 만들기")
print(f"아이템 정보 변수 만들기")
# if not admin_status == "소멸":
if admin_status in status:
@ -126,12 +123,12 @@ class Kipris_WEB:
"publication_date": publication_date,
"registration_date": registration_date,
}
logger.debug("리턴")
print("리턴")
return self.results
else:
logger.debug("No total count element found, possibly incorrect selector or page structure has changed.")
print("No total count element found, possibly incorrect selector or page structure has changed.")
except Exception as e:
logger.debug(f"오류 발생 : {e}")
print(f"오류 발생 : {e}")
return None
def download_image(url, applno):
@ -141,9 +138,9 @@ class Kipris_WEB:
filename = f"{applno}.jpeg" # 파일 이름을 ID로 설정
with open(filename, 'wb') as file:
file.write(response.content)
logger.debug(f"이미지가 성공적으로 저장되었습니다: {filename}")
print(f"이미지가 성공적으로 저장되었습니다: {filename}")
else:
logger.debug(f"이미지 다운로드 실패: HTTP {response.status_code}")
print(f"이미지 다운로드 실패: HTTP {response.status_code}")
def load_category_descriptions(self, filename):
"""JSON 파일에서 카테고리 설명을 로드합니다."""
@ -170,10 +167,10 @@ class Kipris_WEB:
image.save(buffer, 'JPEG') # 예시로 JPEG 포맷을 사용
return buffer.getvalue()
except Exception as e:
logger.debug(f"이미지 변환 실패: {e}")
print(f"이미지 변환 실패: {e}")
return None
else:
logger.debug(f"이미지 다운로드 실패: HTTP {response.status_code}")
print(f"이미지 다운로드 실패: HTTP {response.status_code}")
return None
def close_Kipris(self):

View File

@ -2,16 +2,11 @@ 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__()
@ -20,16 +15,9 @@ class ResultWidget(QWidget):
def initUI(self):
self.setWindowFlags(self.windowFlags() | Qt.WindowStaysOnTopHint)
def show_results(self, results, searchType, elapsed_time, currentURL=''):
# 결과를 표시하기 전에 이전 결과를 지웁니다.
self.clear_results()
def show_results(self, results):
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:
try:
# 결과 위젯 생성
self.results_widget = QWidget()
layout = QVBoxLayout()
@ -42,13 +30,11 @@ class ResultWidget(QWidget):
layout.addLayout(grid_layout)
grid_index = 0
grid_columns = 5
logger.debug(f"show_results - set_count : {set_count}")
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}")
# 테두리 설정
border_style = ''
@ -86,19 +72,7 @@ class ResultWidget(QWidget):
# 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"<span style='font-size: 11pt; font-weight: bold; text-decoration: underline;'>상표권명: {result['title']}</span><br>\n" \
f"<span style='font-size: 11pt; font-weight: bold; text-decoration: underline;'>등록상태: {result['application_status']}</span><br>\n" \
f"<span style='font-size: 9pt;'>카테고리: {result['classification_code']}</span><br>\n" \
f"<span style='font-size: 9pt;'>권리자: {result['applicant_name']}</span><br>\n" \
f"<span style='font-size: 9pt;'>출원일자 {result['application_date']}</span><br>\n" \
f"<span style='font-size: 9pt;'>공고일자 {result['publication_date']}</span><br>\n" \
f"<span style='font-size: 9pt;'>등록일자 {result['registration_date']}</span>\n" \
f"<span style='font-size: 9pt;'>전문 {result['full_text']}</span><br>\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"<span style='font-size: 11pt; font-weight: bold; text-decoration: underline;'>상표권명: {result['title']}</span><br>\n" \
f"<span style='font-size: 11pt; font-weight: bold; text-decoration: underline;'>등록상태: {result['application_status']}</span><br>\n" \
@ -108,9 +82,6 @@ class ResultWidget(QWidget):
f"<span style='font-size: 9pt;'> {result['registration_date']}</span>"
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)
@ -129,33 +100,19 @@ class ResultWidget(QWidget):
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:
# logger.debug(f"Error displaying results: {e}")
def clear_results(self):
# 기존 텍스트를 초기화
if hasattr(self, 'results_widget'):
self.results_widget.deleteLater()
except Exception as e:
print(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):
"""주어진 너비에 맞게 텍스트를 줄바꿈합니다."""
@ -176,31 +133,31 @@ class ResultWidget(QWidget):
async def fetch_image_data_async(self, url):
"""주어진 URL로부터 이미지 데이터를 비동기적으로 가져와 반환합니다."""
async with aiohttp.ClientSession() as session:
# logger.debug(f"download_image session Start!!")
# print(f"download_image session Start!!")
async with session.get(url) as response:
logger.debug(f"download_image url : {url}")
print(f"download_image url : {url}")
if response.status == 200:
# logger.debug(f"response : {response}")
# print(f"response : {response}")
content_type = response.headers.get('Content-Type', '') # await 제거
logger.debug(f"content_type : {content_type}")
print(f"content_type : {content_type}")
if 'image' in content_type or 'octet-stream' in content_type:
# logger.debug(f"image content type or octet-stream : {content_type}")
# print(f"image content type or octet-stream : {content_type}")
return await response.read()
else:
try:
# Content-Type이 이미지가 아니면, 데이터를 이미지로 변환
data = await response.read()
# logger.debug(f"Content-Type이 이미지가 아님 : {data}")
# print(f"Content-Type이 이미지가 아님 : {data}")
image = Image.open(BytesIO(data))
with BytesIO() as buffer:
image.save(buffer, 'JPEG')
logger.debug(f"image 를 JPEG로 저장")
print(f"image 를 JPEG로 저장")
return buffer.getvalue()
except Exception as e:
logger.debug(f"이미지 변환 실패: {e}")
print(f"이미지 변환 실패: {e}")
return None
else:
logger.debug(f"이미지 다운로드 실패: HTTP {response.status}")
print(f"이미지 다운로드 실패: HTTP {response.status}")
return None
@ -220,8 +177,8 @@ class ResultWidget(QWidget):
image.save(buffer, 'JPEG') # 예시로 JPEG 포맷을 사용
return buffer.getvalue()
except Exception as e:
logger.debug(f"이미지 변환 실패: {e}")
print(f"이미지 변환 실패: {e}")
return None
else:
logger.debug(f"이미지 다운로드 실패: HTTP {response.status_code}")
print(f"이미지 다운로드 실패: HTTP {response.status_code}")
return None

View File

@ -2,11 +2,6 @@ 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__()
@ -74,22 +69,22 @@ class TrademarkSearchDisplay(QWidget):
self.text_browser.append(html_content)
def display_web_results(self, data, elapsed_time):
logger.debug(f"Processing results... Elapsed time: {elapsed_time}s")
print(f"Processing results... Elapsed time: {elapsed_time}s")
# data 딕셔너리 내의 키 중 'result_'로 시작하는 키를 찾아 그 값을 처리
for key, item in data.items():
logger.debug(f"Checking key: {key}") # 로그 추가
print(f"Checking key: {key}") # 로그 추가
if key.startswith('result_'): # 'result_'로 시작하는 키 확인
logger.debug(f"Found valid key: {key}, Processing item...") # 로그 추가
print(f"Found valid key: {key}, Processing item...") # 로그 추가
if isinstance(item, dict): # item이 딕셔너리인지 확인
logger.debug(f"Item is a dictionary. Generating HTML for item with title: {item.get('title')}") # 로그 추가
print(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:
logger.debug(f"Image downloaded and saved to {downloaded_image_path}")
print(f"Image downloaded and saved to {downloaded_image_path}")
image_html = f'<img src="{downloaded_image_path}" style="width:100%; max-width:300px; height:auto;">'
else:
logger.debug("Failed to download image.")
print("Failed to download image.")
image_html = 'Image not available'
# HTML 콘텐츠 생성
@ -128,11 +123,11 @@ class TrademarkSearchDisplay(QWidget):
'''
self.text_browser.append(html_content)
logger.debug("HTML content appended to QTextBrowser.") # 로그 추가
print("HTML content appended to QTextBrowser.") # 로그 추가
else:
logger.debug(f"Error: Item associated with {key} is not a dictionary.") # 오류 로그
print(f"Error: Item associated with {key} is not a dictionary.") # 오류 로그
else:
logger.debug(f"Ignored key: {key}") # 무시된 키 로그
print(f"Ignored key: {key}") # 무시된 키 로그
def download_image(self, image_url, identifier):
@ -165,7 +160,7 @@ class TrademarkSearchDisplay(QWidget):
img_resized.save(image_path)
return image_path
except Exception as e:
logger.debug(f"Error resizing image: {e}")
print(f"Error resizing image: {e}")
return None

42
src/test_api.py Normal file
View File

@ -0,0 +1,42 @@
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개월 미만도 공개가능
#

View File

@ -1,10 +1,6 @@
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)

View File

@ -4,10 +4,7 @@ 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 = {}
@ -15,7 +12,6 @@ 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"
@ -46,9 +42,9 @@ class WebScraper:
try:
await self.page.goto(self.url, wait_until='networkidle')
self.is_page_loaded = True
logger.debug("Page loaded successfully.")
print("Page loaded successfully.")
except Exception as e:
logger.debug(f"Failed to load the page: {e}")
print(f"Failed to load the page: {e}")
self.is_page_loaded = False # 로드 실패 처리
@ -56,9 +52,9 @@ class WebScraper:
try:
await self.page.goto(url, wait_until='networkidle')
self.is_page_loaded = True
logger.debug("Page loaded successfully.")
print("Page loaded successfully.")
except Exception as e:
logger.debug(f"Failed to load the page: {e}")
print(f"Failed to load the page: {e}")
self.is_page_loaded = False # 로드 실패 처리
@ -69,23 +65,23 @@ class WebScraper:
# await self.page.fill("#queryText", term)
await self.page.fill("#keywordTextarea", term)
logger.debug(f"검색어 입력 : {term}")
print(f"검색어 입력 : {term}")
await self.page.click(".input_btn")
logger.debug(f"검색버튼 클릭")
print(f"검색버튼 클릭")
# JavaScript에 의해 결과가 동적으로 로드되기를 기다립니다.
loaded = await self.page.wait_for_function(
"document.querySelector('form#listForm section.search_section article') != null"
)
if not loaded:
logger.debug("검색 결과가 시간 내에 로드되지 않았습니다.")
print("검색 결과가 시간 내에 로드되지 않았습니다.")
return None
logger.debug(f"결과가 동적으로 로드되기를 기다림 : {loaded}")
print(f"결과가 동적으로 로드되기를 기다림 : {loaded}")
# 검색 결과가 없는지 확인
nodata_info = await self.page.query_selector(".nodata_info")
if nodata_info:
logger.debug("검색 결과가 없습니다.")
print("검색 결과가 없습니다.")
return None
# 결과 로딩이 확인된 후, 실제 요소를 수집
@ -93,44 +89,41 @@ 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(',', ''))
logger.debug(f"total_count : {total_count}")
self.currentURL = self.page.url
logger.debug(f"currentURL : {self.currentURL}")
print(f"total_count : {total_count}")
if total_count:
self.results['total_count'] = total_count
articles = await self.page.query_selector_all("form#listForm section.search_section article")
logger.debug(f"articles : {len(articles)}")
print(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"
logger.debug(f"trademark_name : {trademark_name}")
print(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
)
logger.debug(f"trademark_image_url_by_id : {trademark_image_url_by_id}")
print(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"
logger.debug(f"trademark_image : {trademark_image}")
print(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"
logger.debug(f"admin_status : {admin_status}")
print(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"
logger.debug(f"product_category : {product_category}")
logger.debug(f"category_desc : {category_desc}")
print(f"product_category : {product_category}")
print(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"
logger.debug(f"applicant : {applicant}")
print(f"applicant : {applicant}")
publication_date_element = await article.query_selector("div:nth-child(2) ul li:nth-child(8)")
if publication_date_element:
@ -138,7 +131,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"
logger.debug(f"publication_date : {publication_date}")
print(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:
@ -146,9 +139,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"
logger.debug(f"registration_date : {registration_date}")
if admin_status in status: # status는 self.set_status 리스트를 참조
# if not (admin_status == "소멸" or admin_status == "거절"):
print(f"registration_date : {registration_date}")
if not (admin_status == "소멸" or admin_status == "거절"):
self.results[f"result_{i+1}"] = {
"ID": applno,
"title": trademark_name,
@ -161,65 +154,65 @@ class WebScraper:
"publication_date": publication_date,
"registration_date": registration_date,
}
# logger.debug(f"results : {self.results}")
# print(f"results : {self.results}")
await self.navigate_to_page(self.url)
return self.results
else:
logger.debug("No total count element found, possibly incorrect selector or page structure has changed.")
print("No total count element found, possibly incorrect selector or page structure has changed.")
except Exception as e:
logger.debug(f"오류 발생 : {e}")
print(f"오류 발생 : {e}")
return None
async def download_image(self, url, applno):
"""이미지를 비동기적으로 다운로드하고 applno를 파일 이름으로 사용하여 저장합니다."""
async with aiohttp.ClientSession() as session:
logger.debug(f"download_image session Start!!")
print(f"download_image session Start!!")
async with session.get(url) as response:
logger.debug(f"download_image url : {url}")
print(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)
logger.debug(f"이미지가 성공적으로 저장되었습니다: {filename}")
print(f"이미지가 성공적으로 저장되었습니다: {filename}")
else:
logger.debug(f"이미지 다운로드 실패: HTTP {response.status}")
print(f"이미지 다운로드 실패: HTTP {response.status}")
async def fetch_image_data(self, url):
"""주어진 URL로부터 이미지 데이터를 비동기적으로 가져와 반환합니다."""
async with aiohttp.ClientSession() as session:
# logger.debug(f"download_image session Start!!")
# print(f"download_image session Start!!")
async with session.get(url) as response:
logger.debug(f"download_image url : {url}")
print(f"download_image url : {url}")
if response.status == 200:
# logger.debug(f"response : {response}")
# print(f"response : {response}")
content_type = response.headers.get('Content-Type', '') # await 제거
logger.debug(f"content_type : {content_type}")
print(f"content_type : {content_type}")
if 'image' in content_type or 'octet-stream' in content_type:
# logger.debug(f"image content type or octet-stream : {content_type}")
# print(f"image content type or octet-stream : {content_type}")
return await response.read()
else:
try:
# Content-Type이 이미지가 아니면, 데이터를 이미지로 변환
data = await response.read()
# logger.debug(f"Content-Type이 이미지가 아님 : {data}")
# print(f"Content-Type이 이미지가 아님 : {data}")
image = Image.open(BytesIO(data))
with BytesIO() as buffer:
image.save(buffer, 'JPEG')
logger.debug(f"image 를 JPEG로 저장")
print(f"image 를 JPEG로 저장")
return buffer.getvalue()
except Exception as e:
logger.debug(f"이미지 변환 실패: {e}")
print(f"이미지 변환 실패: {e}")
return None
else:
logger.debug(f"이미지 다운로드 실패: HTTP {response.status}")
print(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()
# logger.debug(f"JSON 파일에서 카테고리 설명을 비동기적으로 로드합니다: {content}")
# print(f"JSON 파일에서 카테고리 설명을 비동기적으로 로드합니다: {content}")
# return json.loads(content)
def load_category_descriptions(self, filename):
@ -229,7 +222,7 @@ class WebScraper:
def add_category_description(self, category_code):
"""주어진 카테고리 코드에 따라 설명을 반환합니다."""
logger.debug(f"add_category_description => category_code: {category_code}")
print(f"add_category_description => category_code: {category_code}")
return self.category_description.get(category_code, "카테고리 설명을 찾을 수 없습니다.")

View File

@ -1,10 +1,7 @@
from requests_html import HTMLSession
import json
import requests
import logging
# 로거 인스턴스 가져오기
logger = logging.getLogger('default_logger')
class WebScraper:
def __init__(self):
self.session = HTMLSession()
@ -26,7 +23,7 @@ class WebScraper:
"""지정된 URL로 이동하고 페이지를 로드합니다."""
response = self.session.get(url)
response.html.render() # 필요 시 JavaScript 실행
logger.debug("Page loaded successfully.")
print("Page loaded successfully.")
return response
def search_for_term(self, term):
@ -46,17 +43,17 @@ class WebScraper:
search_response.html.render()
return search_response
else:
logger.debug("폼의 action URL을 찾을 수 없습니다.")
print("폼의 action URL을 찾을 수 없습니다.")
else:
logger.debug("검색 폼을 찾을 수 없습니다.")
print("검색 폼을 찾을 수 없습니다.")
except Exception as e:
logger.debug(f"검색 실행 중 오류 발생: {e}")
print(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}';")
# logger.debug(f"검색어 입력: {term}")
# print(f"검색어 입력: {term}")
# input_field = response.html.find('#keywordTextarea', first=True)
# script = f"document.querySelector('#keywordTextarea').value = '{term}';"
# response.html.page.evaluate(script) # JavaScript 실행
@ -67,7 +64,7 @@ class WebScraper:
articles = response.html.find('form#listForm section.search_section article')
if not articles:
logger.debug("검색 결과가 없습니다.")
print("검색 결과가 없습니다.")
return None
# Store results in a structured format
@ -90,9 +87,9 @@ class WebScraper:
filename = f"{applno}.jpeg"
with open(filename, 'wb') as file:
file.write(response.content)
logger.debug(f"이미지가 성공적으로 저장되었습니다: {filename}")
print(f"이미지가 성공적으로 저장되었습니다: {filename}")
else:
logger.debug(f"이미지 다운로드 실패: HTTP {response.status_code}")
print(f"이미지 다운로드 실패: HTTP {response.status_code}")
def fetch_image_data(self, url):
"""주어진 URL로부터 이미지 데이터를 직접 가져와 반환합니다."""
@ -100,7 +97,7 @@ class WebScraper:
if response.status_code == 200:
return response.content
else:
logger.debug(f"이미지 다운로드 실패: HTTP {response.status_code}")
print(f"이미지 다운로드 실패: HTTP {response.status_code}")
return None
def close_browser(self):
@ -110,4 +107,4 @@ class WebScraper:
# # 사용 예시
# scraper = WebScraper()
# results = scraper.search_for_term("특허")
# logger.debug(results)
# print(results)

View File

@ -1,17 +0,0 @@
.AmazonVariationSelectModalRoot {
position: fixed;
right: 10em;
top: 1em;
z-index: 9000000000;
background: transparent;
border: #1B00AE solid medium;
box-shadow: 0 0 30px #A6A6A6;
-moz-box-shadow: 0 0 30px #A6A6A6;
-webkit-box-shadow: 0 0 30px #A6A6A6;
font-weight: bold;
border-radius: 8px;
padding: 0;
width: 20em;
height: 30em;
font-size: 16px;
}

View File

@ -1,3 +0,0 @@
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M17.0367 2.53125H15.6324C15.4356 2.53125 15.2487 2.62165 15.1282 2.77634L6.84537 13.269L2.87372 8.23661C2.81364 8.16033 2.73706 8.09865 2.64973 8.0562C2.56239 8.01375 2.46658 7.99164 2.36948 7.99152H0.965239C0.83064 7.99152 0.75631 8.14621 0.838676 8.25067L6.34113 15.2217C6.59827 15.5471 7.09247 15.5471 7.35162 15.2217L17.1632 2.78839C17.2456 2.68594 17.1713 2.53125 17.0367 2.53125Z" fill="white"/>
</svg>

Before

Width:  |  Height:  |  Size: 514 B

View File

@ -1,8 +0,0 @@
.P_CLASS_CAPTCHA_WARNING_MODAL_CONTAINER {
position: fixed;
left: 0;
right: 0;
top: 0;
z-index: 2000000000;
background: transparent;
}

View File

@ -1,3 +0,0 @@
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M7.71387 14.8658C7.71387 15.2068 7.84933 15.5338 8.09044 15.7749C8.33156 16.016 8.65859 16.1515 8.99958 16.1515C9.34057 16.1515 9.6676 16.016 9.90872 15.7749C10.1498 15.5338 10.2853 15.2068 10.2853 14.8658C10.2853 14.5248 10.1498 14.1977 9.90872 13.9566C9.6676 13.7155 9.34057 13.58 8.99958 13.58C8.65859 13.58 8.33156 13.7155 8.09044 13.9566C7.84933 14.1977 7.71387 14.5248 7.71387 14.8658ZM8.35672 11.4908H9.64244C9.73083 11.4908 9.80315 11.4184 9.80315 11.33V2.00861C9.80315 1.92022 9.73083 1.8479 9.64244 1.8479H8.35672C8.26833 1.8479 8.19601 1.92022 8.19601 2.00861V11.33C8.19601 11.4184 8.26833 11.4908 8.35672 11.4908Z" fill="white"/>
</svg>

Before

Width:  |  Height:  |  Size: 754 B

View File

@ -1,10 +0,0 @@
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_9949_58753)">
<path d="M9.19481 0.362579C6.1312 0.354544 3.43522 1.93959 1.89437 4.33423C1.82606 4.4407 1.9024 4.58133 2.02897 4.58133H3.44124C3.53767 4.58133 3.62807 4.53914 3.68834 4.46481C3.82897 4.29405 3.97964 4.12932 4.13834 3.97262C4.79325 3.31972 5.55464 2.80544 6.4024 2.44785C7.2783 2.0782 8.21044 1.88936 9.17272 1.88936C10.135 1.88936 11.0671 2.0762 11.943 2.44785C12.7908 2.80544 13.5522 3.31972 14.2071 3.97262C14.862 4.62553 15.3743 5.38691 15.7339 6.23267C16.1055 7.10856 16.2924 8.0387 16.2924 9.00097C16.2924 9.96325 16.1035 10.8934 15.7339 11.7693C15.3763 12.615 14.862 13.3764 14.2071 14.0293C13.5522 14.6822 12.7908 15.1965 11.943 15.5541C11.0664 15.9243 10.1243 16.1143 9.17272 16.1126C8.21044 16.1126 7.2783 15.9237 6.4024 15.5541C5.5563 15.1969 4.78744 14.6791 4.13834 14.0293C3.97964 13.8706 3.83097 13.7059 3.68834 13.5371C3.62807 13.4628 3.53566 13.4206 3.44124 13.4206H2.02897C1.9024 13.4206 1.82405 13.5612 1.89437 13.6677C3.43321 16.0563 6.11713 17.6394 9.17272 17.6394C13.9178 17.6394 17.7709 13.8204 17.8191 9.08937C17.8674 4.282 14.0082 0.374633 9.19481 0.362579ZM6.6499 11.251V9.72419H0.341867C0.253474 9.72419 0.181152 9.65187 0.181152 9.56347V8.43847C0.181152 8.35008 0.253474 8.27776 0.341867 8.27776H6.6499V6.75097C6.6499 6.61637 6.8066 6.54004 6.91106 6.62441L9.76173 8.87441C9.78094 8.88944 9.79648 8.90865 9.80716 8.93058C9.81784 8.95251 9.8234 8.97658 9.8234 9.00097C9.8234 9.02536 9.81784 9.04944 9.80716 9.07137C9.79648 9.09329 9.78094 9.1125 9.76173 9.12753L6.91106 11.3775C6.8066 11.4599 6.6499 11.3856 6.6499 11.251Z" fill="white"/>
</g>
<defs>
<clipPath id="clip0_9949_58753">
<rect width="18" height="18" fill="white"/>
</clipPath>
</defs>
</svg>

Before

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -1,651 +0,0 @@
[
{
"code": "0202000",
"name": "가나",
"usable": true,
"parentCode": "0202",
"wholeCodes": [
"02",
"0202",
"0202000"
]
},
{
"code": "0202001",
"name": "가봉",
"usable": true,
"parentCode": "0202",
"wholeCodes": [
"02",
"0202",
"0202001"
]
},
{
"code": "0202002",
"name": "가이아나",
"usable": true,
"parentCode": "0202",
"wholeCodes": [
"02",
"0202",
"0202002"
]
},
{
"code": "0202003",
"name": "감비아",
"usable": true,
"parentCode": "0202",
"wholeCodes": [
"02",
"0202",
"0202003"
]
},
{
"code": "0202004",
"name": "기니",
"usable": true,
"parentCode": "0202",
"wholeCodes": [
"02",
"0202",
"0202004"
]
},
{
"code": "0202005",
"name": "기니비사우",
"usable": true,
"parentCode": "0202",
"wholeCodes": [
"02",
"0202",
"0202005"
]
},
{
"code": "0202006",
"name": "나미비아",
"usable": true,
"parentCode": "0202",
"wholeCodes": [
"02",
"0202",
"0202006"
]
},
{
"code": "0202007",
"name": "나이지리아",
"usable": true,
"parentCode": "0202",
"wholeCodes": [
"02",
"0202",
"0202007"
]
},
{
"code": "0202008",
"name": "남아프리카공화국",
"usable": true,
"parentCode": "0202",
"wholeCodes": [
"02",
"0202",
"0202008"
]
},
{
"code": "0202009",
"name": "니제르",
"usable": true,
"parentCode": "0202",
"wholeCodes": [
"02",
"0202",
"0202009"
]
},
{
"code": "0202010",
"name": "라이베리아",
"usable": true,
"parentCode": "0202",
"wholeCodes": [
"02",
"0202",
"0202010"
]
},
{
"code": "0202011",
"name": "레소토",
"usable": true,
"parentCode": "0202",
"wholeCodes": [
"02",
"0202",
"0202011"
]
},
{
"code": "0202012",
"name": "르완다",
"usable": true,
"parentCode": "0202",
"wholeCodes": [
"02",
"0202",
"0202012"
]
},
{
"code": "0202013",
"name": "마다가스카르",
"usable": true,
"parentCode": "0202",
"wholeCodes": [
"02",
"0202",
"0202013"
]
},
{
"code": "0202014",
"name": "마르티니크",
"usable": true,
"parentCode": "0202",
"wholeCodes": [
"02",
"0202",
"0202014"
]
},
{
"code": "0202015",
"name": "말라위",
"usable": true,
"parentCode": "0202",
"wholeCodes": [
"02",
"0202",
"0202015"
]
},
{
"code": "0202016",
"name": "말리",
"usable": true,
"parentCode": "0202",
"wholeCodes": [
"02",
"0202",
"0202016"
]
},
{
"code": "0202017",
"name": "모로코",
"usable": true,
"parentCode": "0202",
"wholeCodes": [
"02",
"0202",
"0202017"
]
},
{
"code": "0202018",
"name": "모리셔스",
"usable": true,
"parentCode": "0202",
"wholeCodes": [
"02",
"0202",
"0202018"
]
},
{
"code": "0202019",
"name": "모리타니",
"usable": true,
"parentCode": "0202",
"wholeCodes": [
"02",
"0202",
"0202019"
]
},
{
"code": "0202020",
"name": "모잠비크",
"usable": true,
"parentCode": "0202",
"wholeCodes": [
"02",
"0202",
"0202020"
]
},
{
"code": "0202021",
"name": "베냉",
"usable": true,
"parentCode": "0202",
"wholeCodes": [
"02",
"0202",
"0202021"
]
},
{
"code": "0202022",
"name": "보츠와나",
"usable": true,
"parentCode": "0202",
"wholeCodes": [
"02",
"0202",
"0202022"
]
},
{
"code": "0202023",
"name": "부룬디",
"usable": true,
"parentCode": "0202",
"wholeCodes": [
"02",
"0202",
"0202023"
]
},
{
"code": "0202024",
"name": "부르키나파소",
"usable": true,
"parentCode": "0202",
"wholeCodes": [
"02",
"0202",
"0202024"
]
},
{
"code": "0202025",
"name": "사오토메프린시페",
"usable": true,
"parentCode": "0202",
"wholeCodes": [
"02",
"0202",
"0202025"
]
},
{
"code": "0202026",
"name": "상투메 프린시페",
"usable": true,
"parentCode": "0202",
"wholeCodes": [
"02",
"0202",
"0202026"
]
},
{
"code": "0202027",
"name": "서사하라",
"usable": true,
"parentCode": "0202",
"wholeCodes": [
"02",
"0202",
"0202027"
]
},
{
"code": "0202028",
"name": "세네갈",
"usable": true,
"parentCode": "0202",
"wholeCodes": [
"02",
"0202",
"0202028"
]
},
{
"code": "0202029",
"name": "세이셀",
"usable": true,
"parentCode": "0202",
"wholeCodes": [
"02",
"0202",
"0202029"
]
},
{
"code": "0202030",
"name": "소말리아",
"usable": true,
"parentCode": "0202",
"wholeCodes": [
"02",
"0202",
"0202030"
]
},
{
"code": "0202031",
"name": "수단",
"usable": true,
"parentCode": "0202",
"wholeCodes": [
"02",
"0202",
"0202031"
]
},
{
"code": "0202032",
"name": "스와질랜드",
"usable": true,
"parentCode": "0202",
"wholeCodes": [
"02",
"0202",
"0202032"
]
},
{
"code": "0202033",
"name": "시에라리온",
"usable": true,
"parentCode": "0202",
"wholeCodes": [
"02",
"0202",
"0202033"
]
},
{
"code": "0202034",
"name": "알제리",
"usable": true,
"parentCode": "0202",
"wholeCodes": [
"02",
"0202",
"0202034"
]
},
{
"code": "0202035",
"name": "앙골라",
"usable": true,
"parentCode": "0202",
"wholeCodes": [
"02",
"0202",
"0202035"
]
},
{
"code": "0202037",
"name": "에리트리아",
"usable": true,
"parentCode": "0202",
"wholeCodes": [
"02",
"0202",
"0202037"
]
},
{
"code": "0202036",
"name": "에티오피아",
"usable": true,
"parentCode": "0202",
"wholeCodes": [
"02",
"0202",
"0202036"
]
},
{
"code": "0202038",
"name": "우간다",
"usable": true,
"parentCode": "0202",
"wholeCodes": [
"02",
"0202",
"0202038"
]
},
{
"code": "0202039",
"name": "이집트",
"usable": true,
"parentCode": "0202",
"wholeCodes": [
"02",
"0202",
"0202039"
]
},
{
"code": "0202040",
"name": "잠비아",
"usable": true,
"parentCode": "0202",
"wholeCodes": [
"02",
"0202",
"0202040"
]
},
{
"code": "0202041",
"name": "적도기니공화국",
"usable": true,
"parentCode": "0202",
"wholeCodes": [
"02",
"0202",
"0202041"
]
},
{
"code": "0202042",
"name": "중앙아프리카공화국",
"usable": true,
"parentCode": "0202",
"wholeCodes": [
"02",
"0202",
"0202042"
]
},
{
"code": "0202043",
"name": "지부티",
"usable": true,
"parentCode": "0202",
"wholeCodes": [
"02",
"0202",
"0202043"
]
},
{
"code": "0202044",
"name": "지브롤터",
"usable": true,
"parentCode": "0202",
"wholeCodes": [
"02",
"0202",
"0202044"
]
},
{
"code": "0202045",
"name": "짐바브웨",
"usable": true,
"parentCode": "0202",
"wholeCodes": [
"02",
"0202",
"0202045"
]
},
{
"code": "0202046",
"name": "차드",
"usable": true,
"parentCode": "0202",
"wholeCodes": [
"02",
"0202",
"0202046"
]
},
{
"code": "0202047",
"name": "카메룬",
"usable": true,
"parentCode": "0202",
"wholeCodes": [
"02",
"0202",
"0202047"
]
},
{
"code": "0202048",
"name": "카보베르데",
"usable": true,
"parentCode": "0202",
"wholeCodes": [
"02",
"0202",
"0202048"
]
},
{
"code": "0202049",
"name": "케냐",
"usable": true,
"parentCode": "0202",
"wholeCodes": [
"02",
"0202",
"0202049"
]
},
{
"code": "0202050",
"name": "코모로",
"usable": true,
"parentCode": "0202",
"wholeCodes": [
"02",
"0202",
"0202050"
]
},
{
"code": "0202051",
"name": "코모로스",
"usable": true,
"parentCode": "0202",
"wholeCodes": [
"02",
"0202",
"0202051"
]
},
{
"code": "0202052",
"name": "코트디브와르",
"usable": true,
"parentCode": "0202",
"wholeCodes": [
"02",
"0202",
"0202052"
]
},
{
"code": "0202053",
"name": "콩고",
"usable": true,
"parentCode": "0202",
"wholeCodes": [
"02",
"0202",
"0202053"
]
},
{
"code": "0202054",
"name": "콩고민주공화국",
"usable": true,
"parentCode": "0202",
"wholeCodes": [
"02",
"0202",
"0202054"
]
},
{
"code": "0202055",
"name": "탄자니아",
"usable": true,
"parentCode": "0202",
"wholeCodes": [
"02",
"0202",
"0202055"
]
},
{
"code": "0202056",
"name": "터크스앤카이코스제도",
"usable": true,
"parentCode": "0202",
"wholeCodes": [
"02",
"0202",
"0202056"
]
},
{
"code": "0202057",
"name": "토고",
"usable": true,
"parentCode": "0202",
"wholeCodes": [
"02",
"0202",
"0202057"
]
},
{
"code": "0202058",
"name": "튀니지",
"usable": true,
"parentCode": "0202",
"wholeCodes": [
"02",
"0202",
"0202058"
]
}
]

View File

@ -1,541 +0,0 @@
[
{
"code": "0200000",
"name": "그루지야",
"usable": true,
"parentCode": "0200",
"wholeCodes": [
"02",
"0200",
"0200000"
]
},
{
"code": "0200001",
"name": "네팔",
"usable": true,
"parentCode": "0200",
"wholeCodes": [
"02",
"0200",
"0200001"
]
},
{
"code": "0200002",
"name": "대만",
"usable": true,
"parentCode": "0200",
"wholeCodes": [
"02",
"0200",
"0200002"
]
},
{
"code": "0200003",
"name": "동티모르",
"usable": true,
"parentCode": "0200",
"wholeCodes": [
"02",
"0200",
"0200003"
]
},
{
"code": "0200004",
"name": "라오스",
"usable": true,
"parentCode": "0200",
"wholeCodes": [
"02",
"0200",
"0200004"
]
},
{
"code": "0200005",
"name": "레바논",
"usable": true,
"parentCode": "0200",
"wholeCodes": [
"02",
"0200",
"0200005"
]
},
{
"code": "0200006",
"name": "리비아",
"usable": true,
"parentCode": "0200",
"wholeCodes": [
"02",
"0200",
"0200006"
]
},
{
"code": "0200007",
"name": "마카오",
"usable": true,
"parentCode": "0200",
"wholeCodes": [
"02",
"0200",
"0200007"
]
},
{
"code": "0200008",
"name": "말레이시아",
"usable": true,
"parentCode": "0200",
"wholeCodes": [
"02",
"0200",
"0200008"
]
},
{
"code": "0200009",
"name": "몰디브",
"usable": true,
"parentCode": "0200",
"wholeCodes": [
"02",
"0200",
"0200009"
]
},
{
"code": "0200010",
"name": "몽골",
"usable": true,
"parentCode": "0200",
"wholeCodes": [
"02",
"0200",
"0200010"
]
},
{
"code": "0200011",
"name": "미얀마",
"usable": true,
"parentCode": "0200",
"wholeCodes": [
"02",
"0200",
"0200011"
]
},
{
"code": "0200012",
"name": "바레인",
"usable": true,
"parentCode": "0200",
"wholeCodes": [
"02",
"0200",
"0200012"
]
},
{
"code": "0200013",
"name": "방글라데시",
"usable": true,
"parentCode": "0200",
"wholeCodes": [
"02",
"0200",
"0200013"
]
},
{
"code": "0200014",
"name": "베트남",
"usable": true,
"parentCode": "0200",
"wholeCodes": [
"02",
"0200",
"0200014"
]
},
{
"code": "0200015",
"name": "부탄",
"usable": true,
"parentCode": "0200",
"wholeCodes": [
"02",
"0200",
"0200015"
]
},
{
"code": "0200016",
"name": "북한",
"usable": true,
"parentCode": "0200",
"wholeCodes": [
"02",
"0200",
"0200016"
]
},
{
"code": "0200017",
"name": "브루나이",
"usable": true,
"parentCode": "0200",
"wholeCodes": [
"02",
"0200",
"0200017"
]
},
{
"code": "0200018",
"name": "사우디아라비아",
"usable": true,
"parentCode": "0200",
"wholeCodes": [
"02",
"0200",
"0200018"
]
},
{
"code": "0200019",
"name": "스리랑카",
"usable": true,
"parentCode": "0200",
"wholeCodes": [
"02",
"0200",
"0200019"
]
},
{
"code": "0200020",
"name": "시리아",
"usable": true,
"parentCode": "0200",
"wholeCodes": [
"02",
"0200",
"0200020"
]
},
{
"code": "0200021",
"name": "싱가포르",
"usable": true,
"parentCode": "0200",
"wholeCodes": [
"02",
"0200",
"0200021"
]
},
{
"code": "0200022",
"name": "아랍에미리트",
"usable": true,
"parentCode": "0200",
"wholeCodes": [
"02",
"0200",
"0200022"
]
},
{
"code": "0200023",
"name": "아르메니아",
"usable": true,
"parentCode": "0200",
"wholeCodes": [
"02",
"0200",
"0200023"
]
},
{
"code": "0200024",
"name": "아프가니스탄",
"usable": true,
"parentCode": "0200",
"wholeCodes": [
"02",
"0200",
"0200024"
]
},
{
"code": "0200025",
"name": "예멘",
"usable": true,
"parentCode": "0200",
"wholeCodes": [
"02",
"0200",
"0200025"
]
},
{
"code": "0200026",
"name": "오만",
"usable": true,
"parentCode": "0200",
"wholeCodes": [
"02",
"0200",
"0200026"
]
},
{
"code": "0200027",
"name": "요르단",
"usable": true,
"parentCode": "0200",
"wholeCodes": [
"02",
"0200",
"0200027"
]
},
{
"code": "0200028",
"name": "우즈베키스탄",
"usable": true,
"parentCode": "0200",
"wholeCodes": [
"02",
"0200",
"0200028"
]
},
{
"code": "0200030",
"name": "이라크",
"usable": true,
"parentCode": "0200",
"wholeCodes": [
"02",
"0200",
"0200030"
]
},
{
"code": "0200031",
"name": "이란",
"usable": true,
"parentCode": "0200",
"wholeCodes": [
"02",
"0200",
"0200031"
]
},
{
"code": "0200032",
"name": "이스라엘",
"usable": true,
"parentCode": "0200",
"wholeCodes": [
"02",
"0200",
"0200032"
]
},
{
"code": "0200033",
"name": "인도",
"usable": true,
"parentCode": "0200",
"wholeCodes": [
"02",
"0200",
"0200033"
]
},
{
"code": "0200034",
"name": "인도네시아",
"usable": true,
"parentCode": "0200",
"wholeCodes": [
"02",
"0200",
"0200034"
]
},
{
"code": "0200035",
"name": "인도양식민지",
"usable": true,
"parentCode": "0200",
"wholeCodes": [
"02",
"0200",
"0200035"
]
},
{
"code": "0200036",
"name": "일본",
"usable": true,
"parentCode": "0200",
"wholeCodes": [
"02",
"0200",
"0200036"
]
},
{
"code": "0200037",
"name": "중국",
"usable": true,
"parentCode": "0200",
"wholeCodes": [
"02",
"0200",
"0200037"
]
},
{
"code": "0200038",
"name": "카자흐스탄",
"usable": true,
"parentCode": "0200",
"wholeCodes": [
"02",
"0200",
"0200038"
]
},
{
"code": "0200039",
"name": "카타르",
"usable": true,
"parentCode": "0200",
"wholeCodes": [
"02",
"0200",
"0200039"
]
},
{
"code": "0200040",
"name": "캄보디아",
"usable": true,
"parentCode": "0200",
"wholeCodes": [
"02",
"0200",
"0200040"
]
},
{
"code": "0200041",
"name": "쿠웨이트",
"usable": true,
"parentCode": "0200",
"wholeCodes": [
"02",
"0200",
"0200041"
]
},
{
"code": "0200042",
"name": "키리기스스탄",
"usable": true,
"parentCode": "0200",
"wholeCodes": [
"02",
"0200",
"0200042"
]
},
{
"code": "0200043",
"name": "타지키스탄",
"usable": true,
"parentCode": "0200",
"wholeCodes": [
"02",
"0200",
"0200043"
]
},
{
"code": "0200044",
"name": "태국",
"usable": true,
"parentCode": "0200",
"wholeCodes": [
"02",
"0200",
"0200044"
]
},
{
"code": "0200045",
"name": "투르크메니스탄",
"usable": true,
"parentCode": "0200",
"wholeCodes": [
"02",
"0200",
"0200045"
]
},
{
"code": "0200046",
"name": "티베트",
"usable": true,
"parentCode": "0200",
"wholeCodes": [
"02",
"0200",
"0200046"
]
},
{
"code": "0200047",
"name": "파키스탄",
"usable": true,
"parentCode": "0200",
"wholeCodes": [
"02",
"0200",
"0200047"
]
},
{
"code": "0200048",
"name": "필리핀",
"usable": true,
"parentCode": "0200",
"wholeCodes": [
"02",
"0200",
"0200048"
]
},
{
"code": "0200049",
"name": "홍콩",
"usable": true,
"parentCode": "0200",
"wholeCodes": [
"02",
"0200",
"0200049"
]
}
]

View File

@ -1,79 +0,0 @@
[
{
"code": "0204000",
"name": "미국",
"usable": true,
"parentCode": "0204",
"wholeCodes": [
"02",
"0204",
"0204000"
]
},
{
"code": "0204001",
"name": "바베이도스",
"usable": true,
"parentCode": "0204",
"wholeCodes": [
"02",
"0204",
"0204001"
]
},
{
"code": "0204002",
"name": "세인트 빈센트 그레나딘",
"usable": true,
"parentCode": "0204",
"wholeCodes": [
"02",
"0204",
"0204002"
]
},
{
"code": "0204003",
"name": "아이티",
"usable": true,
"parentCode": "0204",
"wholeCodes": [
"02",
"0204",
"0204003"
]
},
{
"code": "0204004",
"name": "앤티가 바부다",
"usable": true,
"parentCode": "0204",
"wholeCodes": [
"02",
"0204",
"0204004"
]
},
{
"code": "0204005",
"name": "유에스버진아일랜드",
"usable": true,
"parentCode": "0204",
"wholeCodes": [
"02",
"0204",
"0204005"
]
},
{
"code": "0204006",
"name": "캐나다",
"usable": true,
"parentCode": "0204",
"wholeCodes": [
"02",
"0204",
"0204006"
]
}
]

View File

@ -1,288 +0,0 @@
[
{
"code": "0203000",
"name": "괌",
"usable": true,
"parentCode": "0203",
"wholeCodes": [
"02",
"0203",
"0203000"
]
},
{
"code": "0203001",
"name": "나우루",
"usable": true,
"parentCode": "0203",
"wholeCodes": [
"02",
"0203",
"0203001"
]
},
{
"code": "0203002",
"name": "노퍽아일랜드",
"usable": true,
"parentCode": "0203",
"wholeCodes": [
"02",
"0203",
"0203002"
]
},
{
"code": "0203003",
"name": "뉴질랜드",
"usable": true,
"parentCode": "0203",
"wholeCodes": [
"02",
"0203",
"0203003"
]
},
{
"code": "0203004",
"name": "뉴칼레도니아",
"usable": true,
"parentCode": "0203",
"wholeCodes": [
"02",
"0203",
"0203004"
]
},
{
"code": "0203005",
"name": "마리아나군도",
"usable": true,
"parentCode": "0203",
"wholeCodes": [
"02",
"0203",
"0203005"
]
},
{
"code": "0203006",
"name": "마셜군도",
"usable": true,
"parentCode": "0203",
"wholeCodes": [
"02",
"0203",
"0203006"
]
},
{
"code": "0203007",
"name": "마이크로네시아",
"usable": true,
"parentCode": "0203",
"wholeCodes": [
"02",
"0203",
"0203007"
]
},
{
"code": "0203008",
"name": "미크로네시아",
"usable": true,
"parentCode": "0203",
"wholeCodes": [
"02",
"0203",
"0203008"
]
},
{
"code": "0203009",
"name": "바누아투",
"usable": true,
"parentCode": "0203",
"wholeCodes": [
"02",
"0203",
"0203009"
]
},
{
"code": "0203010",
"name": "서사모아",
"usable": true,
"parentCode": "0203",
"wholeCodes": [
"02",
"0203",
"0203010"
]
},
{
"code": "0203011",
"name": "세인트빈센트",
"usable": true,
"parentCode": "0203",
"wholeCodes": [
"02",
"0203",
"0203011"
]
},
{
"code": "0203012",
"name": "솔로몬군도",
"usable": true,
"parentCode": "0203",
"wholeCodes": [
"02",
"0203",
"0203012"
]
},
{
"code": "0203013",
"name": "아메리칸사모아",
"usable": true,
"parentCode": "0203",
"wholeCodes": [
"02",
"0203",
"0203013"
]
},
{
"code": "0203014",
"name": "코코스섬",
"usable": true,
"parentCode": "0203",
"wholeCodes": [
"02",
"0203",
"0203014"
]
},
{
"code": "0203015",
"name": "쿡아일랜드",
"usable": true,
"parentCode": "0203",
"wholeCodes": [
"02",
"0203",
"0203015"
]
},
{
"code": "0203016",
"name": "크리스마스섬",
"usable": true,
"parentCode": "0203",
"wholeCodes": [
"02",
"0203",
"0203016"
]
},
{
"code": "0203017",
"name": "키리바시",
"usable": true,
"parentCode": "0203",
"wholeCodes": [
"02",
"0203",
"0203017"
]
},
{
"code": "0203018",
"name": "통가",
"usable": true,
"parentCode": "0203",
"wholeCodes": [
"02",
"0203",
"0203018"
]
},
{
"code": "0203019",
"name": "투발루",
"usable": true,
"parentCode": "0203",
"wholeCodes": [
"02",
"0203",
"0203019"
]
},
{
"code": "0203020",
"name": "파푸아뉴기니",
"usable": true,
"parentCode": "0203",
"wholeCodes": [
"02",
"0203",
"0203020"
]
},
{
"code": "0203021",
"name": "팔라우",
"usable": true,
"parentCode": "0203",
"wholeCodes": [
"02",
"0203",
"0203021"
]
},
{
"code": "0203022",
"name": "폴리네시아(프랑스령)",
"usable": true,
"parentCode": "0203",
"wholeCodes": [
"02",
"0203",
"0203022"
]
},
{
"code": "0203023",
"name": "피지",
"usable": true,
"parentCode": "0203",
"wholeCodes": [
"02",
"0203",
"0203023"
]
},
{
"code": "0203024",
"name": "호주",
"usable": true,
"parentCode": "0203",
"wholeCodes": [
"02",
"0203",
"0203024"
]
},
{
"code": "0203025",
"name": "후투나",
"usable": true,
"parentCode": "0203",
"wholeCodes": [
"02",
"0203",
"0203025"
]
}
]

View File

@ -1,453 +0,0 @@
[
{
"code": "0205000",
"name": "과델루페",
"usable": true,
"parentCode": "0205",
"wholeCodes": [
"02",
"0205",
"0205000"
]
},
{
"code": "0205001",
"name": "과테말라",
"usable": true,
"parentCode": "0205",
"wholeCodes": [
"02",
"0205",
"0205001"
]
},
{
"code": "0205002",
"name": "그레나다",
"usable": true,
"parentCode": "0205",
"wholeCodes": [
"02",
"0205",
"0205002"
]
},
{
"code": "0205003",
"name": "네비스",
"usable": true,
"parentCode": "0205",
"wholeCodes": [
"02",
"0205",
"0205003"
]
},
{
"code": "0205004",
"name": "니카라과",
"usable": true,
"parentCode": "0205",
"wholeCodes": [
"02",
"0205",
"0205004"
]
},
{
"code": "0205005",
"name": "도미니카",
"usable": true,
"parentCode": "0205",
"wholeCodes": [
"02",
"0205",
"0205005"
]
},
{
"code": "0205006",
"name": "도미니카공화국",
"usable": true,
"parentCode": "0205",
"wholeCodes": [
"02",
"0205",
"0205006"
]
},
{
"code": "0205007",
"name": "멕시코",
"usable": true,
"parentCode": "0205",
"wholeCodes": [
"02",
"0205",
"0205007"
]
},
{
"code": "0205008",
"name": "몬체라트",
"usable": true,
"parentCode": "0205",
"wholeCodes": [
"02",
"0205",
"0205008"
]
},
{
"code": "0205009",
"name": "바바도스",
"usable": true,
"parentCode": "0205",
"wholeCodes": [
"02",
"0205",
"0205009"
]
},
{
"code": "0205010",
"name": "바하마",
"usable": true,
"parentCode": "0205",
"wholeCodes": [
"02",
"0205",
"0205010"
]
},
{
"code": "0205011",
"name": "버뮤다",
"usable": true,
"parentCode": "0205",
"wholeCodes": [
"02",
"0205",
"0205011"
]
},
{
"code": "0205012",
"name": "베네수엘라",
"usable": true,
"parentCode": "0205",
"wholeCodes": [
"02",
"0205",
"0205012"
]
},
{
"code": "0205013",
"name": "벨리제",
"usable": true,
"parentCode": "0205",
"wholeCodes": [
"02",
"0205",
"0205013"
]
},
{
"code": "0205014",
"name": "볼리비아",
"usable": true,
"parentCode": "0205",
"wholeCodes": [
"02",
"0205",
"0205014"
]
},
{
"code": "0205015",
"name": "브라질",
"usable": true,
"parentCode": "0205",
"wholeCodes": [
"02",
"0205",
"0205015"
]
},
{
"code": "0205016",
"name": "브리티시 버진아일랜드",
"usable": true,
"parentCode": "0205",
"wholeCodes": [
"02",
"0205",
"0205016"
]
},
{
"code": "0205017",
"name": "세인트루시아",
"usable": true,
"parentCode": "0205",
"wholeCodes": [
"02",
"0205",
"0205017"
]
},
{
"code": "0205018",
"name": "수리남",
"usable": true,
"parentCode": "0205",
"wholeCodes": [
"02",
"0205",
"0205018"
]
},
{
"code": "0205019",
"name": "아루바",
"usable": true,
"parentCode": "0205",
"wholeCodes": [
"02",
"0205",
"0205019"
]
},
{
"code": "0205020",
"name": "아르헨티나",
"usable": true,
"parentCode": "0205",
"wholeCodes": [
"02",
"0205",
"0205020"
]
},
{
"code": "0205021",
"name": "아센션 이스난드",
"usable": true,
"parentCode": "0205",
"wholeCodes": [
"02",
"0205",
"0205021"
]
},
{
"code": "0205022",
"name": "안티구아",
"usable": true,
"parentCode": "0205",
"wholeCodes": [
"02",
"0205",
"0205022"
]
},
{
"code": "0205023",
"name": "앙길라",
"usable": true,
"parentCode": "0205",
"wholeCodes": [
"02",
"0205",
"0205023"
]
},
{
"code": "0205024",
"name": "에콰도르",
"usable": true,
"parentCode": "0205",
"wholeCodes": [
"02",
"0205",
"0205024"
]
},
{
"code": "0205025",
"name": "엘살바도르",
"usable": true,
"parentCode": "0205",
"wholeCodes": [
"02",
"0205",
"0205025"
]
},
{
"code": "0205026",
"name": "온두라스",
"usable": true,
"parentCode": "0205",
"wholeCodes": [
"02",
"0205",
"0205026"
]
},
{
"code": "0205027",
"name": "우루과이",
"usable": true,
"parentCode": "0205",
"wholeCodes": [
"02",
"0205",
"0205027"
]
},
{
"code": "0205028",
"name": "자메이카",
"usable": true,
"parentCode": "0205",
"wholeCodes": [
"02",
"0205",
"0205028"
]
},
{
"code": "0205029",
"name": "칠레",
"usable": true,
"parentCode": "0205",
"wholeCodes": [
"02",
"0205",
"0205029"
]
},
{
"code": "0205030",
"name": "코스타리카",
"usable": true,
"parentCode": "0205",
"wholeCodes": [
"02",
"0205",
"0205030"
]
},
{
"code": "0205031",
"name": "콜롬비아",
"usable": true,
"parentCode": "0205",
"wholeCodes": [
"02",
"0205",
"0205031"
]
},
{
"code": "0205032",
"name": "쿠바",
"usable": true,
"parentCode": "0205",
"wholeCodes": [
"02",
"0205",
"0205032"
]
},
{
"code": "0205033",
"name": "트리니다드토바고",
"usable": true,
"parentCode": "0205",
"wholeCodes": [
"02",
"0205",
"0205033"
]
},
{
"code": "0205034",
"name": "파나마",
"usable": true,
"parentCode": "0205",
"wholeCodes": [
"02",
"0205",
"0205034"
]
},
{
"code": "0205035",
"name": "파라과이",
"usable": true,
"parentCode": "0205",
"wholeCodes": [
"02",
"0205",
"0205035"
]
},
{
"code": "0205036",
"name": "페루",
"usable": true,
"parentCode": "0205",
"wholeCodes": [
"02",
"0205",
"0205036"
]
},
{
"code": "0205037",
"name": "포크랜드",
"usable": true,
"parentCode": "0205",
"wholeCodes": [
"02",
"0205",
"0205037"
]
},
{
"code": "0205038",
"name": "푸에르토리코",
"usable": true,
"parentCode": "0205",
"wholeCodes": [
"02",
"0205",
"0205038"
]
},
{
"code": "0205039",
"name": "프랑스령 기아나",
"usable": true,
"parentCode": "0205",
"wholeCodes": [
"02",
"0205",
"0205039"
]
},
{
"code": "0205040",
"name": "하이티",
"usable": true,
"parentCode": "0205",
"wholeCodes": [
"02",
"0205",
"0205040"
]
}
]

View File

@ -1,3 +0,0 @@
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M9 0C4.02991 0 0 4.02991 0 9C0 13.9701 4.02991 18 9 18C13.9701 18 18 13.9701 18 9C18 4.02991 13.9701 0 9 0ZM9 16.4732C4.87366 16.4732 1.52679 13.1263 1.52679 9C1.52679 7.21205 2.15558 5.56875 3.20424 4.28304L13.717 14.7958C12.4312 15.8444 10.7879 16.4732 9 16.4732ZM14.7958 13.717L4.28304 3.20424C5.56875 2.15558 7.21205 1.52679 9 1.52679C13.1263 1.52679 16.4732 4.87366 16.4732 9C16.4732 10.7879 15.8444 12.4312 14.7958 13.717Z" fill="white"/>
</svg>

Before

Width:  |  Height:  |  Size: 557 B

View File

@ -1,41 +0,0 @@
name:
css: '#productTitle'
type: Text
price:
css: '#price_inside_buybox'
type: Text
short_description:
css: '#featurebullets_feature_div'
type: Text
images:
css: '.imgTagWrapper img'
type: Attribute
attribute: data-a-dynamic-image
rating:
css: span.arp-rating-out-of-text
type: Text
number_of_reviews:
css: 'a.a-link-normal h2'
type: Text
variants:
css: 'form.a-section li'
multiple: true
type: Text
children:
name:
css: ""
type: Attribute
attribute: title
asin:
css: ""
type: Attribute
attribute: data-defaultasin
product_description:
css: '#productDescription'
type: Text
sales_rank:
css: 'li#SalesRank'
type: Text
link_to_all_reviews:
css: 'div.card-padding a.a-link-emphasis'
type: Link

View File

@ -1,152 +0,0 @@
{
"files": {
"main.js": "/static/js/main.js",
"main.css": "/static/css/main.de1fe23d.css",
"background.js": "/static/js/background.js",
"offscreen.js": "/static/js/offscreen.js",
"test_inject.js": "/static/js/test_inject.js",
"starbucks.js": "/static/js/starbucks.js",
"starbucks_docstart_inject.js": "/static/js/starbucks_docstart_inject.js",
"starbucks_docend_inject.js": "/static/js/starbucks_docend_inject.js",
"detail_tmall_com_start.js": "/static/js/detail_tmall_com_start.js",
"detail_tmall_com_start_inject.js": "/static/js/detail_tmall_com_start_inject.js",
"item_taobao_com.js": "/static/js/item_taobao_com.js",
"item_taobao_com_inject.js": "/static/js/item_taobao_com_inject.js",
"item_taobao_com_start.js": "/static/js/item_taobao_com_start.js",
"item_taobao_com_start_inject.js": "/static/js/item_taobao_com_start_inject.js",
"world_taobao_com_detail.js": "/static/js/world_taobao_com_detail.js",
"s_taobao_com.js": "/static/js/s_taobao_com.js",
"cart_taobao_com.js": "/static/js/cart_taobao_com.js",
"shoucang_taobao_com.js": "/static/js/shoucang_taobao_com.js",
"shop_taobao_com.js": "/static/js/shop_taobao_com.js",
"percenty_prod.js": "/static/js/percenty_prod.js",
"percenty_test.js": "/static/js/percenty_test.js",
"percenty_antd_prod.js": "/static/js/percenty_antd_prod.js",
"percenty_antd_test.js": "/static/js/percenty_antd_test.js",
"detail_tmall_com.js": "/static/js/detail_tmall_com.js",
"detail_tmall_com_inject.js": "/static/js/detail_tmall_com_inject.js",
"list_tmall_com.js": "/static/js/list_tmall_com.js",
"aliexpress_com.js": "/static/js/aliexpress_com.js",
"aliexpress_com_inject.js": "/static/js/aliexpress_com_inject.js",
"aliexpress_com_list.js": "/static/js/aliexpress_com_list.js",
"aliexpress_com_start.js": "/static/js/aliexpress_com_start.js",
"detail_1688_com.js": "/static/js/detail_1688_com.js",
"detail_1688_com_inject.js": "/static/js/detail_1688_com_inject.js",
"show_1688_com.js": "/static/js/show_1688_com.js",
"s_1688_com.js": "/static/js/s_1688_com.js",
"amazon_com.js": "/static/js/amazon_com.js",
"amazon_com_list.js": "/static/js/amazon_com_list.js",
"vvic_com.js": "/static/js/vvic_com.js",
"vvic_com_inject.js": "/static/js/vvic_com_inject.js",
"vvic_com_list.js": "/static/js/vvic_com_list.js",
"item_rakuten_com.js": "/static/js/item_rakuten_com.js",
"item_rakuten_com_inject.js": "/static/js/item_rakuten_com_inject.js",
"item_rakuten_com_iframe.js": "/static/js/item_rakuten_com_iframe.js",
"brandavenue_rakuten_com.js": "/static/js/brandavenue_rakuten_com.js",
"rakuten_com_category.js": "/static/js/rakuten_com_category.js",
"bic_rakuten_com_item.js": "/static/js/bic_rakuten_com_item.js",
"bic_rakuten_com_item_inject.js": "/static/js/bic_rakuten_com_item_inject.js",
"bic_rakuten_com_search.js": "/static/js/bic_rakuten_com_search.js",
"ranking_rakuten_com.js": "/static/js/ranking_rakuten_com.js",
"iherb_com_detail.js": "/static/js/iherb_com_detail.js",
"iherb_com_detail_inject.js": "/static/js/iherb_com_detail_inject.js",
"temu_com_detail.js": "/static/js/temu_com_detail.js",
"temu_com_detail_inject.js": "/static/js/temu_com_detail_inject.js",
"temu_com_detail_start.js": "/static/js/temu_com_detail_start.js",
"temu_com_list.js": "/static/js/temu_com_list.js",
"temu_com_list_inject.js": "/static/js/temu_com_list_inject.js",
"rakuten_fashion.js": "/static/js/rakuten_fashion.js",
"rakuten_fashion_list.js": "/static/js/rakuten_fashion_list.js",
"rakuten_fashion_inject.js": "/static/js/rakuten_fashion_inject.js",
"ople_com.js": "/static/js/ople_com.js",
"ople_com_list.js": "/static/js/ople_com_list.js",
"ople_com_inject.js": "/static/js/ople_com_inject.js",
"img_search.js": "/static/js/img_search.js",
"zozo_jp.js": "/static/js/zozo_jp.js",
"zozo_jp_list.js": "/static/js/zozo_jp_list.js",
"zozo_jp_inject.js": "/static/js/zozo_jp_inject.js",
"shein_com.js": "/static/js/shein_com.js",
"shein_com_list.js": "/static/js/shein_com_list.js",
"shein_com_inject.js": "/static/js/shein_com_inject.js",
"osee_tracking.js": "/static/js/osee_tracking.js",
"detail_tmall_com_option_inject.js": "/static/js/detail_tmall_com_option_inject.js",
"item_taobao_com_option_inject.js": "/static/js/item_taobao_com_option_inject.js",
"static/js/787.09c3bd89.chunk.js": "/static/js/787.09c3bd89.chunk.js",
"index.html": "/index.html",
"main.js.map": "/static/js/main.js.map",
"main.de1fe23d.css.map": "/static/css/main.de1fe23d.css.map",
"background.js.map": "/static/js/background.js.map",
"offscreen.js.map": "/static/js/offscreen.js.map",
"test_inject.js.map": "/static/js/test_inject.js.map",
"starbucks.js.map": "/static/js/starbucks.js.map",
"starbucks_docstart_inject.js.map": "/static/js/starbucks_docstart_inject.js.map",
"detail_tmall_com_start.js.map": "/static/js/detail_tmall_com_start.js.map",
"detail_tmall_com_start_inject.js.map": "/static/js/detail_tmall_com_start_inject.js.map",
"item_taobao_com.js.map": "/static/js/item_taobao_com.js.map",
"item_taobao_com_inject.js.map": "/static/js/item_taobao_com_inject.js.map",
"item_taobao_com_start.js.map": "/static/js/item_taobao_com_start.js.map",
"item_taobao_com_start_inject.js.map": "/static/js/item_taobao_com_start_inject.js.map",
"world_taobao_com_detail.js.map": "/static/js/world_taobao_com_detail.js.map",
"s_taobao_com.js.map": "/static/js/s_taobao_com.js.map",
"cart_taobao_com.js.map": "/static/js/cart_taobao_com.js.map",
"shoucang_taobao_com.js.map": "/static/js/shoucang_taobao_com.js.map",
"shop_taobao_com.js.map": "/static/js/shop_taobao_com.js.map",
"percenty_prod.js.map": "/static/js/percenty_prod.js.map",
"percenty_test.js.map": "/static/js/percenty_test.js.map",
"percenty_antd_prod.js.map": "/static/js/percenty_antd_prod.js.map",
"percenty_antd_test.js.map": "/static/js/percenty_antd_test.js.map",
"detail_tmall_com.js.map": "/static/js/detail_tmall_com.js.map",
"detail_tmall_com_inject.js.map": "/static/js/detail_tmall_com_inject.js.map",
"list_tmall_com.js.map": "/static/js/list_tmall_com.js.map",
"aliexpress_com.js.map": "/static/js/aliexpress_com.js.map",
"aliexpress_com_inject.js.map": "/static/js/aliexpress_com_inject.js.map",
"aliexpress_com_list.js.map": "/static/js/aliexpress_com_list.js.map",
"aliexpress_com_start.js.map": "/static/js/aliexpress_com_start.js.map",
"detail_1688_com.js.map": "/static/js/detail_1688_com.js.map",
"detail_1688_com_inject.js.map": "/static/js/detail_1688_com_inject.js.map",
"show_1688_com.js.map": "/static/js/show_1688_com.js.map",
"s_1688_com.js.map": "/static/js/s_1688_com.js.map",
"amazon_com.js.map": "/static/js/amazon_com.js.map",
"amazon_com_list.js.map": "/static/js/amazon_com_list.js.map",
"vvic_com.js.map": "/static/js/vvic_com.js.map",
"vvic_com_inject.js.map": "/static/js/vvic_com_inject.js.map",
"vvic_com_list.js.map": "/static/js/vvic_com_list.js.map",
"item_rakuten_com.js.map": "/static/js/item_rakuten_com.js.map",
"item_rakuten_com_inject.js.map": "/static/js/item_rakuten_com_inject.js.map",
"item_rakuten_com_iframe.js.map": "/static/js/item_rakuten_com_iframe.js.map",
"brandavenue_rakuten_com.js.map": "/static/js/brandavenue_rakuten_com.js.map",
"rakuten_com_category.js.map": "/static/js/rakuten_com_category.js.map",
"bic_rakuten_com_item.js.map": "/static/js/bic_rakuten_com_item.js.map",
"bic_rakuten_com_item_inject.js.map": "/static/js/bic_rakuten_com_item_inject.js.map",
"bic_rakuten_com_search.js.map": "/static/js/bic_rakuten_com_search.js.map",
"ranking_rakuten_com.js.map": "/static/js/ranking_rakuten_com.js.map",
"iherb_com_detail.js.map": "/static/js/iherb_com_detail.js.map",
"iherb_com_detail_inject.js.map": "/static/js/iherb_com_detail_inject.js.map",
"temu_com_detail.js.map": "/static/js/temu_com_detail.js.map",
"temu_com_detail_inject.js.map": "/static/js/temu_com_detail_inject.js.map",
"temu_com_detail_start.js.map": "/static/js/temu_com_detail_start.js.map",
"temu_com_list.js.map": "/static/js/temu_com_list.js.map",
"temu_com_list_inject.js.map": "/static/js/temu_com_list_inject.js.map",
"rakuten_fashion.js.map": "/static/js/rakuten_fashion.js.map",
"rakuten_fashion_list.js.map": "/static/js/rakuten_fashion_list.js.map",
"rakuten_fashion_inject.js.map": "/static/js/rakuten_fashion_inject.js.map",
"ople_com.js.map": "/static/js/ople_com.js.map",
"ople_com_list.js.map": "/static/js/ople_com_list.js.map",
"ople_com_inject.js.map": "/static/js/ople_com_inject.js.map",
"img_search.js.map": "/static/js/img_search.js.map",
"zozo_jp.js.map": "/static/js/zozo_jp.js.map",
"zozo_jp_list.js.map": "/static/js/zozo_jp_list.js.map",
"zozo_jp_inject.js.map": "/static/js/zozo_jp_inject.js.map",
"shein_com.js.map": "/static/js/shein_com.js.map",
"shein_com_list.js.map": "/static/js/shein_com_list.js.map",
"shein_com_inject.js.map": "/static/js/shein_com_inject.js.map",
"osee_tracking.js.map": "/static/js/osee_tracking.js.map",
"detail_tmall_com_option_inject.js.map": "/static/js/detail_tmall_com_option_inject.js.map",
"item_taobao_com_option_inject.js.map": "/static/js/item_taobao_com_option_inject.js.map",
"787.09c3bd89.chunk.js.map": "/static/js/787.09c3bd89.chunk.js.map"
},
"entrypoints": [
"static/js/main.js",
"static/css/main.de1fe23d.css"
]
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 250 B

View File

@ -1,3 +0,0 @@
<svg width="16" height="17" viewBox="0 0 16 17" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M9.41385 8.00009L15.7069 1.70709C15.8944 1.51959 15.9997 1.26527 15.9997 1.00009C15.9997 0.734917 15.8944 0.480601 15.7069 0.293093C15.5193 0.105585 15.265 0.000244141 14.9998 0.000244141C14.7347 0.000244141 14.4804 0.105585 14.2928 0.293093L7.99985 6.58609L1.70685 0.293093C1.614 0.200249 1.50378 0.1266 1.38247 0.0763533C1.26117 0.0261062 1.13115 0.000244141 0.999849 0.000244141C0.868547 0.000244141 0.738531 0.0261062 0.617224 0.0763533C0.495916 0.1266 0.385694 0.200249 0.292849 0.293093C0.105341 0.480601 0 0.734917 0 1.00009C0 1.26527 0.105341 1.51959 0.292849 1.70709L6.58585 8.00009L0.292849 14.2931C0.105341 14.4806 0 14.7349 0 15.0001C0 15.2653 0.105341 15.5196 0.292849 15.7071C0.480357 15.8946 0.734673 15.9999 0.999849 15.9999C1.26503 15.9999 1.51934 15.8946 1.70685 15.7071L7.99985 9.41409L14.2928 15.7071C14.3855 15.8003 14.4957 15.8742 14.617 15.9247C14.7383 15.9752 14.8684 16.0011 14.9998 16.0011C15.1313 16.0011 15.2614 15.9752 15.3827 15.9247C15.504 15.8742 15.6142 15.8003 15.7069 15.7071C15.7998 15.6143 15.8735 15.5041 15.9238 15.3828C15.9742 15.2615 16 15.1314 16 15.0001C16 14.8688 15.9742 14.7387 15.9238 14.6174C15.8735 14.4961 15.7998 14.3859 15.7069 14.2931L9.41385 8.00009Z" fill="#5C5F62"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -1 +0,0 @@
<!doctype html><html lang="en"><head><meta charset="utf-8"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><script defer="defer" src="/static/js/main.js"></script><script defer="defer" src="/static/js/img_search.js"></script><link href="/static/css/main.de1fe23d.css" rel="stylesheet"></head><body><div id="rootPopup"></div></body></html>

View File

@ -1,3 +0,0 @@
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M9 18C7.78535 18 6.60586 17.7627 5.49668 17.2934C4.42441 16.8398 3.46289 16.1895 2.63672 15.3633C1.81055 14.5371 1.16016 13.5756 0.706641 12.5033C0.237305 11.3941 0 10.2146 0 9C0 8.6502 0.283008 8.36719 0.632812 8.36719C0.982617 8.36719 1.26562 8.6502 1.26562 9C1.26562 10.0441 1.46953 11.0566 1.87383 12.0111C2.26406 12.9322 2.82129 13.7602 3.53145 14.4703C4.2416 15.1805 5.06953 15.7395 5.99062 16.1279C6.94336 16.5305 7.95586 16.7344 9 16.7344C10.0441 16.7344 11.0566 16.5305 12.0111 16.1262C12.9322 15.7359 13.7602 15.1787 14.4703 14.4686C15.1805 13.7584 15.7395 12.9305 16.1279 12.0094C16.5305 11.0566 16.7344 10.0441 16.7344 9C16.7344 7.95586 16.5305 6.94336 16.1262 5.98887C15.7373 5.06999 15.1744 4.23494 14.4686 3.52969C13.7641 2.8229 12.9288 2.25991 12.0094 1.87207C11.0566 1.46953 10.0441 1.26562 9 1.26562C8.6502 1.26562 8.36719 0.982617 8.36719 0.632812C8.36719 0.283008 8.6502 0 9 0C10.2146 0 11.3941 0.237305 12.5033 0.706641C13.5756 1.16016 14.5371 1.81055 15.3633 2.63672C16.1895 3.46289 16.8381 4.42617 17.2916 5.49668C17.7609 6.60586 17.9982 7.78535 17.9982 9C17.9982 10.2146 17.7609 11.3941 17.2916 12.5033C16.8398 13.5756 16.1895 14.5371 15.3633 15.3633C14.5371 16.1895 13.5738 16.8381 12.5033 17.2916C11.3941 17.7627 10.2146 18 9 18V18Z" fill="white"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -1,5 +0,0 @@
<svg width="18" height="15" viewBox="0 0 18 15" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M3.64238 6.91294C5.21445 6.91294 6.48887 5.63853 6.48887 4.06646C6.48887 2.49439 5.21445 1.21997 3.64238 1.21997C2.07031 1.21997 0.795898 2.49439 0.795898 4.06646C0.795898 5.63853 2.07031 6.91294 3.64238 6.91294Z" fill="white"/>
<path d="M14.3567 14.7882C15.9288 14.7882 17.2032 13.5138 17.2032 11.9417C17.2032 10.3696 15.9288 9.09521 14.3567 9.09521C12.7847 9.09521 11.5103 10.3696 11.5103 11.9417C11.5103 13.5138 12.7847 14.7882 14.3567 14.7882Z" fill="white"/>
<path d="M14.1437 1.21997H10.7558C10.0831 1.21997 9.50068 1.57271 9.17256 2.09771L8.95107 2.62271L3.85693 14.5665H7.25303C7.91748 14.5665 8.89365 13.6887 9.11514 13.0325L14.1437 1.21997Z" fill="white"/>
</svg>

Before

Width:  |  Height:  |  Size: 779 B

View File

@ -1 +0,0 @@
1.242d538dbb4a2c4301cacfdbfeee9b816e29e23316ba41a5b982eee1cb859d12

View File

@ -1,196 +0,0 @@
{
"action": {
"default_popup": "index.html",
"default_title": "퍼센티"
},
"background": {
"service_worker": "./static/js/background.js"
},
"content_scripts": [ {
"js": [ "./static/js/percenty_prod.js" ],
"matches": [ "https://www.percenty.co.kr/*" ],
"run_at": "document_end"
}, {
"js": [ "./static/js/percenty_antd_prod.js" ],
"matches": [ "https://www.new.percenty.co.kr/*" ],
"run_at": "document_end"
}, {
"js": [ "./static/js/item_taobao_com.js" ],
"matches": [ "https://item.taobao.com/*" ],
"run_at": "document_end"
}, {
"js": [ "./static/js/world_taobao_com_detail.js" ],
"matches": [ "https://world.taobao.com/item/*" ],
"run_at": "document_end"
}, {
"js": [ "./static/js/item_taobao_com_start.js" ],
"matches": [ "https://item.taobao.com/*" ],
"run_at": "document_start",
"world": "MAIN"
}, {
"js": [ "./static/js/detail_tmall_com.js" ],
"matches": [ "https://detail.tmall.com/*", "https://*.detail.tmall.com/*", "https://detail.tmall.hk/*" ],
"run_at": "document_end"
}, {
"js": [ "./static/js/detail_tmall_com_start.js" ],
"matches": [ "https://detail.tmall.com/*", "https://*.detail.tmall.com/*", "https://detail.tmall.hk/*" ],
"run_at": "document_start",
"world": "MAIN"
}, {
"js": [ "./static/js/s_taobao_com.js" ],
"matches": [ "https://s.taobao.com/*" ],
"run_at": "document_end"
}, {
"css": [ ],
"js": [ "./static/js/cart_taobao_com.js" ],
"matches": [ "https://cart.taobao.com/*" ],
"run_at": "document_end"
}, {
"css": [ ],
"js": [ "./static/js/shoucang_taobao_com.js" ],
"matches": [ "https://shoucang.taobao.com/*" ],
"run_at": "document_end"
}, {
"js": [ "./static/js/list_tmall_com.js" ],
"matches": [ "https://list.tmall.com/*", "https://list.tmall.hk/*" ],
"run_at": "document_end"
}, {
"js": [ "./static/js/aliexpress_com.js" ],
"matches": [ "https://*.aliexpress.com/item/*", "https://*.aliexpress.com/i/*" ],
"run_at": "document_end"
}, {
"js": [ "./static/js/aliexpress_com_list.js" ],
"matches": [ "https://*.aliexpress.com/*category/*", "https://*.aliexpress.com/*wholesale*", "https://*.aliexpress.com/af/*" ],
"run_at": "document_end"
}, {
"css": [ ],
"js": [ "./static/js/aliexpress_com_start.js" ],
"matches": [ "https://*.aliexpress.com/item/*", "https://*.aliexpress.com/i/*" ],
"run_at": "document_start",
"world": "MAIN"
}, {
"js": [ "./static/js/detail_1688_com.js" ],
"matches": [ "https://detail.1688.com/*" ],
"run_at": "document_end"
}, {
"js": [ "./static/js/show_1688_com.js" ],
"matches": [ "https://show.1688.com/*" ],
"run_at": "document_end"
}, {
"js": [ "./static/js/s_1688_com.js" ],
"matches": [ "https://s.1688.com/*" ],
"run_at": "document_end"
}, {
"js": [ "./static/js/osee_tracking.js" ],
"matches": [ "https://*.1688.com/*" ],
"run_at": "document_end"
}, {
"js": [ "./static/js/amazon_com.js" ],
"matches": [ "https://*.amazon.com/*/dp/*", "https://*.amazon.co.jp/*/dp/*", "https://*.amazon.ca/*/dp/*", "https://*.amazon.fr/*/dp/*", "https://*.amazon.de/*/dp/*", "https://*.amazon.in/*/dp/*", "https://*.amazon.it/*/dp/*", "https://*.amazon.com.mx/*/dp/*", "https://*.amazon.es/*/dp/*", "https://*.amazon.co.uk/*/dp/*", "https://*.amazon.com/dp/*", "https://*.amazon.co.jp/dp/*", "https://*.amazon.ca/dp/*", "https://*.amazon.fr/dp/*", "https://*.amazon.de/dp/*", "https://*.amazon.in/dp/*", "https://*.amazon.it/dp/*", "https://*.amazon.com.mx/dp/*", "https://*.amazon.es/dp/*", "https://*.amazon.co.uk/dp/*", "https://*.amazon.com/*gp/product/*", "https://*.amazon.co.jp/*gp/product/*", "https://*.amazon.ca/*gp/product/*", "https://*.amazon.fr/*gp/product/*", "https://*.amazon.de/*gp/product/*", "https://*.amazon.in/*gp/product/*", "https://*.amazon.it/*gp/product/*", "https://*.amazon.com.mx/*gp/product/*", "https://*.amazon.es/*gp/product/*", "https://*.amazon.co.uk/*gp/product/*", "https://*.amazon.com/*gp/aw/d/*", "https://*.amazon.co.jp/*gp/aw/d/*", "https://*.amazon.ca/*gp/aw/d/*", "https://*.amazon.fr/*gp/aw/d/*", "https://*.amazon.de/*gp/aw/d/*", "https://*.amazon.in/*gp/aw/d/*", "https://*.amazon.it/*gp/aw/d/*", "https://*.amazon.com.mx/*gp/aw/d/*", "https://*.amazon.es/*gp/aw/d/*", "https://*.amazon.co.uk/*gp/aw/d/*" ],
"run_at": "document_end"
}, {
"js": [ "./static/js/amazon_com_list.js" ],
"matches": [ "https://*.amazon.com/b?*", "https://*.amazon.co.jp/b?*", "https://*.amazon.ca/b?*", "https://*.amazon.fr/b?*", "https://*.amazon.de/b?*", "https://*.amazon.in/b?*", "https://*.amazon.it/b?*", "https://*.amazon.com.mx/b?*", "https://*.amazon.es/b?*", "https://*.amazon.co.uk/b?*", "https://*.amazon.com/*/b?*", "https://*.amazon.co.jp/*/b?*", "https://*.amazon.ca/*/b?*", "https://*.amazon.fr/*/b?*", "https://*.amazon.de/*/b?*", "https://*.amazon.in/*/b?*", "https://*.amazon.it/*/b?*", "https://*.amazon.com.mx/*/b?*", "https://*.amazon.es/*/b?*", "https://*.amazon.co.uk/*/b?*", "https://*.amazon.com/s?*", "https://*.amazon.co.jp/s?*", "https://*.amazon.ca/s?*", "https://*.amazon.fr/s?*", "https://*.amazon.de/s?*", "https://*.amazon.in/s?*", "https://*.amazon.it/s?*", "https://*.amazon.com.mx/s?*", "https://*.amazon.es/s?*", "https://*.amazon.co.uk/s?*", "https://*.amazon.com/*/s?*", "https://*.amazon.co.jp/*/s?*", "https://*.amazon.ca/*/s?*", "https://*.amazon.fr/*/s?*", "https://*.amazon.de/*/s?*", "https://*.amazon.in/*/s?*", "https://*.amazon.it/*/s?*", "https://*.amazon.com.mx/*/s?*", "https://*.amazon.es/*/s?*", "https://*.amazon.co.uk/*/s?*", "https://*.amazon.com/gp/browse*", "https://*.amazon.co.jp/gp/browse*", "https://*.amazon.ca/gp/browse*", "https://*.amazon.fr/gp/browse*", "https://*.amazon.de/gp/browse*", "https://*.amazon.in/gp/browse*", "https://*.amazon.it/gp/browse*", "https://*.amazon.com.mx/gp/browse*", "https://*.amazon.es/gp/browse*", "https://*.amazon.co.uk/gp/browse*" ],
"run_at": "document_end"
}, {
"js": [ "./static/js/vvic_com.js" ],
"matches": [ "https://*.vvic.com/item/*" ],
"run_at": "document_end"
}, {
"js": [ "./static/js/vvic_com_list.js" ],
"matches": [ "https://*.vvic.com/*/search/*", "https://*.vvic.com/*/list/*" ],
"run_at": "document_end"
}, {
"js": [ "./static/js/item_rakuten_com.js" ],
"matches": [ "https://item.rakuten.co.jp/*" ],
"run_at": "document_end"
}, {
"all_frames": true,
"js": [ "./static/js/item_rakuten_com_iframe.js" ],
"matches": [ "https://item.rakuten.co.jp/*", "https://*.rakuten.ne.jp/*gallery.html*" ],
"run_at": "document_end"
}, {
"js": [ "./static/js/rakuten_com_category.js" ],
"matches": [ "https://www.rakuten.co.jp/category/*", "https://search.rakuten.co.jp/search/*" ],
"run_at": "document_end"
}, {
"js": [ "./static/js/iherb_com_detail.js" ],
"matches": [ "https://kr.iherb.com/pr/*" ],
"run_at": "document_end"
}, {
"js": [ "./static/js/temu_com_detail.js" ],
"matches": [ "https://*.temu.com/*" ],
"run_at": "document_end"
}, {
"js": [ "./static/js/temu_com_list.js" ],
"matches": [ "https://*.temu.com/search_result*", "https://*.temu.com/kr/*", "https://*.temu.com/category.html*" ],
"run_at": "document_idle"
}, {
"js": [ "./static/js/temu_com_detail_start.js" ],
"matches": [ "https://*.temu.com/*" ],
"run_at": "document_start",
"world": "MAIN"
}, {
"js": [ "./static/js/ople_com.js" ],
"matches": [ "https://*.ople.com/*/shop/item.php?it_id=*" ],
"run_at": "document_end"
}, {
"js": [ "./static/js/ople_com_list.js" ],
"matches": [ "https://*.ople.com/*/shop/*" ],
"run_at": "document_end"
}, {
"js": [ "./static/js/starbucks.js" ],
"matches": [ "*://*/*" ],
"run_at": "document_end"
}, {
"js": [ "./static/js/rakuten_fashion_list.js" ],
"matches": [ "https://*.brandavenue.rakuten.co.jp/*" ],
"run_at": "document_end"
}, {
"js": [ "./static/js/rakuten_fashion.js" ],
"matches": [ "https://*.brandavenue.rakuten.co.jp/item/*" ],
"run_at": "document_end"
}, {
"js": [ "./static/js/img_search.js" ],
"matches": [ "*://*/*" ],
"run_at": "document_end"
}, {
"js": [ "./static/js/zozo_jp_list.js" ],
"matches": [ "https://*.zozo.jp/*" ],
"run_at": "document_end"
}, {
"js": [ "./static/js/zozo_jp.js" ],
"matches": [ "https://*.zozo.jp/shop/*" ],
"run_at": "document_end"
}, {
"js": [ "./static/js/shein_com_list.js" ],
"matches": [ "https://asia.shein.com/*", "https://asia.shein.com/category/*", "https://kr.shein.com/*", "https://kr.shein.com/category/*" ],
"run_at": "document_idle"
}, {
"js": [ "./static/js/shein_com.js" ],
"matches": [ "https://asia.shein.com/*-p-*.html*", "https://kr.shein.com/*-p-*.html*" ],
"run_at": "document_end"
} ],
"description": "퍼센티 구매대행 상품 수집 및 편의기능을 위한 확장프로그램",
"differential_fingerprint": "1.242d538dbb4a2c4301cacfdbfeee9b816e29e23316ba41a5b982eee1cb859d12",
"externally_connectable": {
"matches": [ "https://*.percenty.co.kr/*" ]
},
"host_permissions": [ "*://*/*" ],
"icons": {
"128": "percenty_logo.png",
"16": "percenty_logo.png",
"48": "percenty_logo.png"
},
"incognito": "not_allowed",
"key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAjldxlPmTZGVdwgaFoLR4f+gNpouI9Gyb3WPKaREQZoS3RAZigftdm+3eH1LjILNurhKpiODN8HOnK+js9883jcOalBOOkr1c+k0LBZ9hwzF7hhAKHIp5ZU8aTQHokKTYBSXyx/7viLmq5HApkay/etN7+aDWFOD6u9HNCStv2J1VE8iZI04SgTv5zCPxqYw/dzyKDKNpH1TTWZDTqvOSE4i8riLCy+VvxQ1MUNT0q4J/9+8dwt59ZjdVWBMWF3N23xrjv9Z6wIHtsaHOzN1yVLe53tHd/48jXmEVdd95tECsyu3f7QZ3rKJTviV8F3NtPbIUqmoTMTVZX2Q0FcXoKQIDAQAB",
"manifest_version": 3,
"name": "퍼센티",
"permissions": [ "activeTab", "storage", "cookies", "declarativeNetRequest", "contextMenus", "offscreen" ],
"update_url": "https://clients2.google.com/service/update2/crx",
"version": "1.1.123",
"web_accessible_resources": [ {
"matches": [ "*://*/*" ],
"resources": [ "*/item_taobao_com_inject.js", "*/item_taobao_com_option_inject.js", "*/detail_tmall_com_inject.js", "*/detail_tmall_com_option_inject.js", "*/aliexpress_com_inject.js", "*/detail_1688_com_inject.js", "*/vvic_com_inject.js", "*/item_rakuten_com_inject.js", "*/iherb_com_detail_inject.js", "*/starbucks_docstart_inject.js", "*/starbucks_docend_inject.js", "*/detail_tmall_com_start_inject.js", "*/item_taobao_com_start_inject.js", "*/temu_com_detail_inject.js", "*/temu_com_list_inject.js", "*/rakuten_fashion_inject.js", "*/ople_com_inject.js", "*/zozo_jp_inject.js", "*/taobao_img_search.js", "*/shein_com_inject.js", "*/test_inject.js", "*.png*", "*.svg*", "*.json*", "*.jpeg", "*.jpg" ]
} ]
}

View File

@ -1,2 +0,0 @@
<!doctype html>
<script type="module" src="./static/js/offscreen.js"></script>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

View File

@ -1,3 +0,0 @@
# https://www.robotstxt.org/robotstxt.html
User-agent: *
Disallow:

View File

@ -1,2 +0,0 @@
body{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;background-color:#fff;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif;height:auto;margin:0;width:-webkit-fit-content;width:-moz-fit-content;width:fit-content}code{font-family:source-code-pro,Menlo,Monaco,Consolas,Courier New,monospace}
/*# sourceMappingURL=main.de1fe23d.css.map*/

View File

@ -1 +0,0 @@
{"version":3,"file":"static/css/main.de1fe23d.css","mappings":"AAAA,KAOI,kCAAmC,CACnC,iCAAkC,CAJlC,qBAAuB,CACvB,mIACc,CAHd,WAAY,CAFZ,QAAS,CACT,yBAAkB,CAAlB,sBAAkB,CAAlB,iBAOJ,CAEA,KACI,uEACJ","sources":["index.css"],"sourcesContent":["body {\n margin: 0;\n width: fit-content;\n height: auto;\n background-color: white;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',\n sans-serif;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n}\n\ncode {\n font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', monospace;\n}\n"],"names":[],"sourceRoot":""}

View File

@ -1,2 +0,0 @@
"use strict";(self.webpackChunkpercenty_chrome_extension=self.webpackChunkpercenty_chrome_extension||[]).push([[787],{787:(e,t,n)=>{n.r(t),n.d(t,{getCLS:()=>y,getFCP:()=>h,getFID:()=>C,getLCP:()=>P,getTTFB:()=>D});var i,r,a,o,c=function(e,t){return{name:e,value:void 0===t?-1:t,delta:0,entries:[],id:"v2-".concat(Date.now(),"-").concat(Math.floor(8999999999999*Math.random())+1e12)}},u=function(e,t){try{if(PerformanceObserver.supportedEntryTypes.includes(e)){if("first-input"===e&&!("PerformanceEventTiming"in self))return;var n=new PerformanceObserver((function(e){return e.getEntries().map(t)}));return n.observe({type:e,buffered:!0}),n}}catch(e){}},s=function(e,t){var n=function n(i){"pagehide"!==i.type&&"hidden"!==document.visibilityState||(e(i),t&&(removeEventListener("visibilitychange",n,!0),removeEventListener("pagehide",n,!0)))};addEventListener("visibilitychange",n,!0),addEventListener("pagehide",n,!0)},f=function(e){addEventListener("pageshow",(function(t){t.persisted&&e(t)}),!0)},m=function(e,t,n){var i;return function(r){t.value>=0&&(r||n)&&(t.delta=t.value-(i||0),(t.delta||void 0===i)&&(i=t.value,e(t)))}},v=-1,p=function(){return"hidden"===document.visibilityState?0:1/0},d=function(){s((function(e){var t=e.timeStamp;v=t}),!0)},l=function(){return v<0&&(v=p(),d(),f((function(){setTimeout((function(){v=p(),d()}),0)}))),{get firstHiddenTime(){return v}}},h=function(e,t){var n,i=l(),r=c("FCP"),a=function(e){"first-contentful-paint"===e.name&&(s&&s.disconnect(),e.startTime<i.firstHiddenTime&&(r.value=e.startTime,r.entries.push(e),n(!0)))},o=window.performance&&performance.getEntriesByName&&performance.getEntriesByName("first-contentful-paint")[0],s=o?null:u("paint",a);(o||s)&&(n=m(e,r,t),o&&a(o),f((function(i){r=c("FCP"),n=m(e,r,t),requestAnimationFrame((function(){requestAnimationFrame((function(){r.value=performance.now()-i.timeStamp,n(!0)}))}))})))},g=!1,T=-1,y=function(e,t){g||(h((function(e){T=e.value})),g=!0);var n,i=function(t){T>-1&&e(t)},r=c("CLS",0),a=0,o=[],v=function(e){if(!e.hadRecentInput){var t=o[0],i=o[o.length-1];a&&e.startTime-i.startTime<1e3&&e.startTime-t.startTime<5e3?(a+=e.value,o.push(e)):(a=e.value,o=[e]),a>r.value&&(r.value=a,r.entries=o,n())}},p=u("layout-shift",v);p&&(n=m(i,r,t),s((function(){p.takeRecords().map(v),n(!0)})),f((function(){a=0,T=-1,r=c("CLS",0),n=m(i,r,t)})))},E={passive:!0,capture:!0},w=new Date,L=function(e,t){i||(i=t,r=e,a=new Date,F(removeEventListener),S())},S=function(){if(r>=0&&r<a-w){var e={entryType:"first-input",name:i.type,target:i.target,cancelable:i.cancelable,startTime:i.timeStamp,processingStart:i.timeStamp+r};o.forEach((function(t){t(e)})),o=[]}},b=function(e){if(e.cancelable){var t=(e.timeStamp>1e12?new Date:performance.now())-e.timeStamp;"pointerdown"==e.type?function(e,t){var n=function(){L(e,t),r()},i=function(){r()},r=function(){removeEventListener("pointerup",n,E),removeEventListener("pointercancel",i,E)};addEventListener("pointerup",n,E),addEventListener("pointercancel",i,E)}(t,e):L(t,e)}},F=function(e){["mousedown","keydown","touchstart","pointerdown"].forEach((function(t){return e(t,b,E)}))},C=function(e,t){var n,a=l(),v=c("FID"),p=function(e){e.startTime<a.firstHiddenTime&&(v.value=e.processingStart-e.startTime,v.entries.push(e),n(!0))},d=u("first-input",p);n=m(e,v,t),d&&s((function(){d.takeRecords().map(p),d.disconnect()}),!0),d&&f((function(){var a;v=c("FID"),n=m(e,v,t),o=[],r=-1,i=null,F(addEventListener),a=p,o.push(a),S()}))},k={},P=function(e,t){var n,i=l(),r=c("LCP"),a=function(e){var t=e.startTime;t<i.firstHiddenTime&&(r.value=t,r.entries.push(e),n())},o=u("largest-contentful-paint",a);if(o){n=m(e,r,t);var v=function(){k[r.id]||(o.takeRecords().map(a),o.disconnect(),k[r.id]=!0,n(!0))};["keydown","click"].forEach((function(e){addEventListener(e,v,{once:!0,capture:!0})})),s(v,!0),f((function(i){r=c("LCP"),n=m(e,r,t),requestAnimationFrame((function(){requestAnimationFrame((function(){r.value=performance.now()-i.timeStamp,k[r.id]=!0,n(!0)}))}))}))}},D=function(e){var t,n=c("TTFB");t=function(){try{var t=performance.getEntriesByType("navigation")[0]||function(){var e=performance.timing,t={entryType:"navigation",startTime:0};for(var n in e)"navigationStart"!==n&&"toJSON"!==n&&(t[n]=Math.max(e[n]-e.navigationStart,0));return t}();if(n.value=n.delta=t.responseStart,n.value<0||n.value>performance.now())return;n.entries=[t],e(n)}catch(e){}},"complete"===document.readyState?setTimeout(t,0):addEventListener("load",(function(){return setTimeout(t,0)}))}}}]);
//# sourceMappingURL=787.09c3bd89.chunk.js.map

View File

@ -1,68 +0,0 @@
/*
object-assign
(c) Sindre Sorhus
@license MIT
*/
/*!
* The buffer module from node.js, for the browser.
*
* @author Feross Aboukhadijeh <https://feross.org>
* @license MIT
*/
/*! ieee754. BSD-3-Clause License. Feross Aboukhadijeh <https://feross.org/opensource> */
/**
* @license
* Lodash <https://lodash.com/>
* Copyright OpenJS Foundation and other contributors <https://openjsf.org/>
* Released under MIT license <https://lodash.com/license>
* Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
* Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
*/
/** @license React v0.20.2
* scheduler.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/** @license React v16.13.1
* react-is.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/** @license React v17.0.2
* react-dom.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/** @license React v17.0.2
* react-jsx-runtime.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/** @license React v17.0.2
* react.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

View File

@ -1,8 +0,0 @@
/**
* @license
* Lodash <https://lodash.com/>
* Copyright OpenJS Foundation and other contributors <https://openjsf.org/>
* Released under MIT license <https://lodash.com/license>
* Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
* Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
*/

View File

@ -1,59 +0,0 @@
/*
object-assign
(c) Sindre Sorhus
@license MIT
*/
/**
* @license
* Lodash <https://lodash.com/>
* Copyright OpenJS Foundation and other contributors <https://openjsf.org/>
* Released under MIT license <https://lodash.com/license>
* Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
* Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
*/
/** @license React v0.20.2
* scheduler.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/** @license React v16.13.1
* react-is.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/** @license React v17.0.2
* react-dom.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/** @license React v17.0.2
* react-jsx-runtime.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/** @license React v17.0.2
* react.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

View File

@ -1,17 +0,0 @@
/*!
* The buffer module from node.js, for the browser.
*
* @author Feross Aboukhadijeh <https://feross.org>
* @license MIT
*/
/*! ieee754. BSD-3-Clause License. Feross Aboukhadijeh <https://feross.org/opensource> */
/**
* @license
* Lodash <https://lodash.com/>
* Copyright OpenJS Foundation and other contributors <https://openjsf.org/>
* Released under MIT license <https://lodash.com/license>
* Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
* Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
*/

View File

@ -1,68 +0,0 @@
/*
object-assign
(c) Sindre Sorhus
@license MIT
*/
/*!
* The buffer module from node.js, for the browser.
*
* @author Feross Aboukhadijeh <https://feross.org>
* @license MIT
*/
/*! ieee754. BSD-3-Clause License. Feross Aboukhadijeh <https://feross.org/opensource> */
/**
* @license
* Lodash <https://lodash.com/>
* Copyright OpenJS Foundation and other contributors <https://openjsf.org/>
* Released under MIT license <https://lodash.com/license>
* Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
* Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
*/
/** @license React v0.20.2
* scheduler.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/** @license React v16.13.1
* react-is.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/** @license React v17.0.2
* react-dom.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/** @license React v17.0.2
* react-jsx-runtime.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/** @license React v17.0.2
* react.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

View File

@ -1,59 +0,0 @@
/*
object-assign
(c) Sindre Sorhus
@license MIT
*/
/**
* @license
* Lodash <https://lodash.com/>
* Copyright OpenJS Foundation and other contributors <https://openjsf.org/>
* Released under MIT license <https://lodash.com/license>
* Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
* Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
*/
/** @license React v0.20.2
* scheduler.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/** @license React v16.13.1
* react-is.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/** @license React v17.0.2
* react-dom.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/** @license React v17.0.2
* react-jsx-runtime.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/** @license React v17.0.2
* react.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

View File

@ -1,19 +0,0 @@
/*!
* The buffer module from node.js, for the browser.
*
* @author Feross Aboukhadijeh <https://feross.org>
* @license MIT
*/
/*! ieee754. BSD-3-Clause License. Feross Aboukhadijeh <https://feross.org/opensource> */
/*! safe-buffer. MIT License. Feross Aboukhadijeh <https://feross.org/opensource> */
/**
* @license
* Lodash <https://lodash.com/>
* Copyright OpenJS Foundation and other contributors <https://openjsf.org/>
* Released under MIT license <https://lodash.com/license>
* Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
* Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
*/

View File

@ -1,68 +0,0 @@
/*
object-assign
(c) Sindre Sorhus
@license MIT
*/
/*!
* The buffer module from node.js, for the browser.
*
* @author Feross Aboukhadijeh <https://feross.org>
* @license MIT
*/
/*! ieee754. BSD-3-Clause License. Feross Aboukhadijeh <https://feross.org/opensource> */
/**
* @license
* Lodash <https://lodash.com/>
* Copyright OpenJS Foundation and other contributors <https://openjsf.org/>
* Released under MIT license <https://lodash.com/license>
* Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
* Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
*/
/** @license React v0.20.2
* scheduler.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/** @license React v16.13.1
* react-is.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/** @license React v17.0.2
* react-dom.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/** @license React v17.0.2
* react-jsx-runtime.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/** @license React v17.0.2
* react.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

View File

@ -1,2 +0,0 @@
(()=>{"use strict";let _=function(_){return _.TO_OFFSCREEN_DEFAULT_INJECT_DATA="TO_OFFSCREEN_DEFAULT_INJECT_DATA",_.TO_OFFSCREEN_TAOBAO_SCRAP="TO_OFFSCREEN_TAOBAO_SCRAP",_.TO_OFFSCREEN_TMALL_SCRAP="TO_OFFSCREEN_TMALL_SCRAP",_.TO_OFFSCREEN_GET_IDLE_TIME="TO_OFFSCREEN_GET_IDLE_TIME",_.TO_BACKGROUND_ENSURE_OFFSCREEN="TO_BACKGROUND_ENSURE_OFFSCREEN",_.TO_CONTENT_SCRAP_AUTO_BY_URL="TO_CONTENT_SCRAP_AUTO_BY_URL",_.TO_BACKGROUND_SET_1688_QUERY="TO_BACKGROUND_SET_1688_QUERY",_.GET_PERCENTY_TOKEN="GET_PERCENTY_TOKEN",_.INJECT_RESULT="INJECT_RESULT",_.OPEN_TAB_AND_SCRAP="OPEN_TAB_AND_SCRAP",_.OPEN_TAB_AND_SCRAP_FINISH="OPEN_TAB_AND_SCRAP_FINISH",_.SCRAP_AUTO="SCRAP_AUTO",_.SCRAP_AUTO_FINISH="SCRAP_AUTO_FINISH",_.SCRAP_AUTO_FINISH_TO_LIST_PAGE="SCRAP_AUTO_FINISH_TO_LIST_PAGE",_.OPEN_PERCENTY_TAB="OPEN_PERCENTY_TAB",_.GET_CURRENT_TAB_ID_FROM_CONTENTS_SCRIPT="GET_CURRENT_TAB_ID_FROM_CONTENTS_SCRIPT",_.CLOSE_TAB="CLOSE_TAB",_.SCRAP_SUCCESS_TO_PERCENTY_WEB="SCRAP_SUCCESS_TO_PERCENTY_WEB",_.SCRAP_SUCCESS_TO_PERCENTY_WEB_TAB="SCRAP_SUCCESS_TO_PERCENTY_WEB_TAB",_.EXTENSION_INSTALLED_TO_PERCENTY_WEB_TAB="EXTENSION_INSTALLED_TO_PERCENTY_WEB_TAB",_.FETCH_RAW="FETCH_RAW",_.GET_NAVER_SHOPPING_LENS="GET_NAVER_SHOPPING_LENS",_.IMG_SEARCH="IMG_SEARCH",_.IMG_SEARCH_TAB="IMG_SEARCH_TAB",_.IMG_SEARCH_RESULT="IMG_SEARCH_RESULT",_.IMAGE_SEARCH_POSITION="IMAGE_SEARCH_POSITION",_.IMAGE_SEARCH_BTN_POSITION="IMAGE_SEARCH_BTN_POSITION",_.IMAGE_SEARCH_RESULT="IMAGE_SEARCH_RESULT",_.IMAGE_SEARCH_MODAL_OPEN="IMAGE_SEARCH_MODAL_OPEN",_.UPDATE_DECLARATIVE_NET_REQUEST_RULES="UPDATE_DECLARATIVE_NET_REQUEST_RULES",_.GET_SHEIN_THUMBNAIL_IMGS="GET_SHEIN_THUMBNAIL_IMGS",_.GET_IMG_BLOB_URL="GET_IMG_BLOB_URL",_.TO_DELETE_COOKIES="TO_DELETE_COOKIES",_.TO_CONTENT_SET_SCRAP_PARAMS="TO_CONTENT_SET_SCRAP_PARAMS",_.HEALTH_CHECK="HEALTH_CHECK",_.OPEN_SMART_STORE_LOGIN_EXTERNAL="OPEN_SMART_STORE_LOGIN_EXTERNAL",_.UPLOAD_SMART_STORE_EXTERNAL="UPLOAD_SMART_STORE_EXTERNAL",_.EDIT_SMART_STORE_EXTERNAL="EDIT_SMART_STORE_EXTERNAL",_.GET_CURRENT_LOGGED_IN_SMART_STORE_CHANNEL_EXTERNAL="GET_CURRENT_LOGGED_IN_SMART_STORE_CHANNEL_EXTERNAL",_.GET_CHROME_EXTENSION_VERSION_EXTERNAL="GET_CHROME_EXTENSION_VERSION_EXTERNAL",_.DELETE_SMART_STORE_PRODUCT_EXTERNAL="DELETE_SMART_STORE_PRODUCT_EXTERNAL",_.UPDATE_SMART_STORE_PRODUCT_STATE_EXTERNAL="UPDATE_SMART_STORE_PRODUCT_STATE_EXTERNAL",_.GET_SMART_STORE_PRODUCT_EXTERNAL="GET_SMART_STORE_PRODUCT_EXTERNAL",_.FETCH_RAW_EXTERNAL="FETCH_RAW_EXTERNAL",_.UPDATE_DECLARATIVE_NET_REQUEST_RULES_EXTERNAL="UPDATE_DECLARATIVE_NET_REQUEST_RULES_EXTERNAL",_.GET_DECLARATIVE_NET_REQUEST_RULES_EXTERNAL="GET_DECLARATIVE_NET_REQUEST_RULES_EXTERNAL",_.SCRAP_START_EXTERNAL="SCRAP_START_EXTERNAL",_.REQUEST_AI_SOURCING="REQUEST_AI_SOURCING",_.REQUEST_NAVER_SHOPPING_POPULAR_TERMS="REQUEST_NAVER_SHOPPING_POPULAR_TERMS",_.REQUEST_TAOBAO_IMG_SEARCH_EXTERNAL="REQUEST_TAOBAO_IMG_SEARCH_EXTERNAL",_.REFRESH_OFFSCREEN_DOCUMENT_IF_NEED="REFRESH_OFFSCREEN_DOCUMENT_IF_NEED",_.OPEN_TAB_WITH_SCRAP_PARAMS_EXTERNAL="OPEN_TAB_WITH_SCRAP_PARAMS_EXTERNAL",_.SCRAP_SUCCESS_FROM_EXT="SCRAP_SUCCESS_FROM_EXT",_.CHROME_EXTENSION_INSTALLED_FROM_EXT="CHROME_EXTENSION_INSTALLED_FROM_EXT",_.NAVER_SHOPPING_LENS_FROM_EXT="NAVER_SHOPPING_LENS_FROM_EXT",_.CLEAR_CHROME_EXTENSION_STORAGE="CLEAR_CHROME_EXTENSION_STORAGE",_.OPEN_FROM_MARKET_TAB="OPEN_FROM_MARKET_TAB",_.HIGHLIGHT_OPTION="HIGHLIGHT_OPTION",_}({});window.postMessage({type:_.INJECT_RESULT,data:{grp15_ias_prm:window.grp15_ias_prm}})})();
//# sourceMappingURL=bic_rakuten_com_item_inject.js.map

View File

@ -1,59 +0,0 @@
/*
object-assign
(c) Sindre Sorhus
@license MIT
*/
/**
* @license
* Lodash <https://lodash.com/>
* Copyright OpenJS Foundation and other contributors <https://openjsf.org/>
* Released under MIT license <https://lodash.com/license>
* Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
* Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
*/
/** @license React v0.20.2
* scheduler.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/** @license React v16.13.1
* react-is.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/** @license React v17.0.2
* react-dom.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/** @license React v17.0.2
* react-jsx-runtime.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/** @license React v17.0.2
* react.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

View File

@ -1,59 +0,0 @@
/*
object-assign
(c) Sindre Sorhus
@license MIT
*/
/**
* @license
* Lodash <https://lodash.com/>
* Copyright OpenJS Foundation and other contributors <https://openjsf.org/>
* Released under MIT license <https://lodash.com/license>
* Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
* Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
*/
/** @license React v0.20.2
* scheduler.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/** @license React v16.13.1
* react-is.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/** @license React v17.0.2
* react-dom.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/** @license React v17.0.2
* react-jsx-runtime.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/** @license React v17.0.2
* react.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

View File

@ -1,68 +0,0 @@
/*
object-assign
(c) Sindre Sorhus
@license MIT
*/
/*!
* The buffer module from node.js, for the browser.
*
* @author Feross Aboukhadijeh <https://feross.org>
* @license MIT
*/
/*! ieee754. BSD-3-Clause License. Feross Aboukhadijeh <https://feross.org/opensource> */
/**
* @license
* Lodash <https://lodash.com/>
* Copyright OpenJS Foundation and other contributors <https://openjsf.org/>
* Released under MIT license <https://lodash.com/license>
* Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
* Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
*/
/** @license React v0.20.2
* scheduler.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/** @license React v16.13.1
* react-is.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/** @license React v17.0.2
* react-dom.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/** @license React v17.0.2
* react-jsx-runtime.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/** @license React v17.0.2
* react.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

Some files were not shown because too many files have changed in this diff Show More