142 lines
5.2 KiB
Python
142 lines
5.2 KiB
Python
import requests
|
|
import logging
|
|
class NaverSearchAPI:
|
|
def __init__(self, client_id: str, client_secret: str, logger=None):
|
|
"""
|
|
네이버 검색 API 클라이언트 초기화
|
|
:param client_id: 네이버 API 클라이언트 ID
|
|
:param client_secret: 네이버 API 클라이언트 Secret
|
|
:param logger: 로그 기록용 객체 (선택)
|
|
"""
|
|
self.client_id = client_id
|
|
self.client_secret = client_secret
|
|
self.logger = logger
|
|
|
|
def get_search_words(self, input_text, count=4):
|
|
"""
|
|
입력된 문자열을 띄어쓰기로 분리 후 앞 네 개의 단어만 반환하는 메서드.
|
|
|
|
:param input_text: 문자열 입력
|
|
:param count: 반환 단어 갯수
|
|
:return: 앞 네 개의 단어로 구성된 문자열
|
|
"""
|
|
if not isinstance(input_text, str):
|
|
raise ValueError("입력값은 문자열이어야 합니다.")
|
|
|
|
# 띄어쓰기로 분리
|
|
words = input_text.split()
|
|
|
|
# 앞 네 개의 단어만 추출
|
|
split_words = words[:count]
|
|
|
|
# 다시 문자열로 결합하여 반환
|
|
return " ".join(split_words)
|
|
|
|
def search(self, query: str, display: int = 10, start: int = 1, sort: str = "sim") -> dict:
|
|
"""
|
|
네이버 검색 API로 검색어를 검색
|
|
:param query: 검색어
|
|
:param display: 검색 결과 출력 개수 (기본값: 10)
|
|
:param start: 검색 시작 위치 (기본값: 1)
|
|
:param sort: 정렬 옵션 ("sim": 유사도, "date": 날짜)
|
|
:return: 검색 결과 JSON 데이터
|
|
"""
|
|
search_words = self.get_search_words(query, 4)
|
|
url = "https://openapi.naver.com/v1/search/shop.json"
|
|
headers = {
|
|
"X-Naver-Client-Id": self.client_id,
|
|
"X-Naver-Client-Secret": self.client_secret
|
|
}
|
|
params = {
|
|
"query": search_words,
|
|
"display": display,
|
|
"start": start,
|
|
"sort": sort
|
|
}
|
|
|
|
try:
|
|
response = requests.get(url, headers=headers, params=params)
|
|
response.raise_for_status() # HTTP 에러 발생 시 예외 처리
|
|
search_results = response.json()
|
|
|
|
result = self.parse_search_results(search_results)
|
|
|
|
if self.logger:
|
|
self.logger.log(f"네이버 검색 성공: {query}, 결과 개수: {len(result)}", level=logging.DEBUG)
|
|
return result
|
|
|
|
except requests.exceptions.RequestException as e:
|
|
if self.logger:
|
|
self.logger.log(f"네이버 검색 실패: {e}", level=logging.DEBUG, exc_info=True)
|
|
|
|
return {"error": str(e)}
|
|
|
|
def parse_search_results_list(self, search_results: dict) -> list:
|
|
"""검색 결과를 원하는 형식으로 변환"""
|
|
detailed_products = []
|
|
|
|
# 검색 결과에서 items 리스트 추출
|
|
items = search_results.get('items', [])
|
|
|
|
for item in items:
|
|
# 각 항목에서 필요한 데이터 추출
|
|
title = item.get('title', '').replace('<b>', '').replace('</b>', '') # HTML 태그 제거
|
|
lprice = item.get('lprice', '') # 최저가
|
|
# manu_tag = item.get('brand', '') # 브랜드
|
|
# related_tags = item.get('relatedTags', []) # 연관 검색어
|
|
# 카테고리 데이터
|
|
category = [
|
|
item.get('category1', ''),
|
|
item.get('category2', ''),
|
|
item.get('category3', ''),
|
|
item.get('category4', '')
|
|
]
|
|
|
|
# 데이터 추가
|
|
detailed_products.append({
|
|
"title": title,
|
|
"price": lprice,
|
|
"manu_tag": '',
|
|
"category": category,
|
|
'related_tags': ''
|
|
})
|
|
|
|
return detailed_products
|
|
|
|
def parse_search_results(self, search_results: dict) -> dict:
|
|
"""검색 결과를 원하는 형식으로 변환"""
|
|
detailed_products = {}
|
|
|
|
# 검색 결과에서 items 리스트 추출
|
|
items = search_results.get('items', [])
|
|
|
|
for index, item in enumerate(items):
|
|
# 각 항목에서 필요한 데이터 추출
|
|
title = item.get('title', '').replace('<b>', '').replace('</b>', '') # HTML 태그 제거
|
|
lprice = item.get('lprice', '') # 최저가
|
|
category = [
|
|
item.get('category1', ''),
|
|
item.get('category2', ''),
|
|
item.get('category3', ''),
|
|
item.get('category4', '')
|
|
]
|
|
|
|
# 인덱스를 키로 사용하여 딕셔너리로 저장
|
|
detailed_products[index] = {
|
|
"title": title,
|
|
"price": lprice,
|
|
"category": category
|
|
}
|
|
|
|
return detailed_products
|
|
|
|
|
|
# n_search = NaverSearchAPI(client_id='Uq5c9J_WdQYF8e2wOQT4', client_secret='y0CnrADAae')
|
|
|
|
# query = "섬유 시편 원단 수동 절단기 컷팅기 샘플러 나이프"
|
|
# search_results = n_search.search(query, display=20, start=1, sort="sim")
|
|
# print("검색 search_results:", search_results)
|
|
# print("items")
|
|
# for item in search_results.get("items", []):
|
|
# print(f"{item}")
|