Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 72a12ac29f | |||
| e396c08f6b | |||
| e58fa0bd57 | |||
| 3b73517cfa | |||
| f760723067 | |||
| bbb17ef362 | |||
| c3488e7bc9 | |||
| 698e0736fc | |||
| 66bf05e11d | |||
| 77d209d6fc | |||
| 27fcea070a |
@ -16,7 +16,7 @@ NAVER_PW=Login_Password
|
||||
|
||||
# 메시지 전송 플랫폼 선택
|
||||
# mattermost, synology_chat, telegram 중 선택(콤마로 구분) 또는 빈 값(발송 안함)
|
||||
MESSAGE_PLATFORM=mattermost,telegram
|
||||
MESSAGE_PLATFORMS=mattermost,telegram
|
||||
|
||||
# Mattermost 설정
|
||||
# MATTERMOST_URL은 마지막에 '/' 없이 입력
|
||||
@ -27,7 +27,7 @@ MATTERMOST_CHANNEL_ID=CHANNEL_ID
|
||||
MATTERMOST_BOT_TOKEN=BOT_TOKEN
|
||||
|
||||
# Synology Chat Webhook URL (사용 시 설정)
|
||||
SYNology_CHAT_WEBHOOK_URL=https://synology.chat/webhook/your_webhook_url
|
||||
Synology_CHAT_WEBHOOK_URL=https://synology.chat/webhook/your_webhook_url
|
||||
|
||||
# Telegram 설정 (사용 시 설정)
|
||||
TELEGRAM_BOT_TOKEN=your_bot_token
|
||||
|
||||
14
README.md
14
README.md
@ -1,7 +1,7 @@
|
||||
# 네이버 리뷰 크롤러
|
||||
- 네이버 비즈니스, 네이버 map 기준 리뷰를 크롤링해 메시지를 보내줌
|
||||
# 폴더 구조
|
||||
``` bash
|
||||
```bash
|
||||
/
|
||||
├── .env_sample # 환경변수 샘플 파일 (.env_sample)
|
||||
├── .gitignore # Git 무시 파일 목록
|
||||
@ -19,3 +19,15 @@
|
||||
|
||||
|
||||
```
|
||||
|
||||
# 빌드(Windows 11 기준)
|
||||
```bash
|
||||
pyinstaller --onefile `
|
||||
--add-data ".env;.env" `
|
||||
--add-data "conf;conf" `
|
||||
--add-data "lib;lib" `
|
||||
--add-data "data;data" `
|
||||
run.py
|
||||
```
|
||||
- 환경 변수를 포함하여 빌드하므로 `.env` 파일을 사전에 생성해 두어야 함
|
||||
- 동작 확인을 위해 `--noconsloe` 옵션 제거
|
||||
|
||||
@ -1,4 +1,25 @@
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
from dotenv import load_dotenv
|
||||
|
||||
# 프로젝트 루트 기준으로 .env 위치 지정
|
||||
BASE_DIR = getattr(sys, '_MEIPASS', os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
|
||||
ENV_PATH = os.path.join(BASE_DIR, '.env')
|
||||
load_dotenv(dotenv_path=ENV_PATH)
|
||||
|
||||
# ✅ 타임존 설정
|
||||
TZ = os.getenv("TZ", "Asia/Seoul")
|
||||
os.environ["TZ"] = TZ
|
||||
try:
|
||||
time.tzset()
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
try:
|
||||
time.tzset()
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
def parse_bool(value):
|
||||
if isinstance(value, bool):
|
||||
@ -17,14 +38,14 @@ MAX_REVIEWS = int(os.getenv("MAX_REVIEWS", "100"))
|
||||
NAVER_ID = os.getenv("NAVER_ID", "")
|
||||
NAVER_PW = os.getenv("NAVER_PW", "")
|
||||
|
||||
MESSAGE_PLATFORMS = parse_list(os.getenv("MESSAGE_PLATFORM", ""))
|
||||
MESSAGE_PLATFORMS = parse_list(os.getenv("MESSAGE_PLATFORMS", ""))
|
||||
|
||||
MATTERMOST_URL = os.getenv("MATTERMOST_URL", "")
|
||||
MATTERMOST_WEBHOOK_URL = os.getenv("MATTERMOST_WEBHOOK_URL", "")
|
||||
MATTERMOST_CHANNEL_ID = os.getenv("MATTERMOST_CHANNEL_ID", "")
|
||||
MATTERMOST_BOT_TOKEN = os.getenv("MATTERMOST_BOT_TOKEN", "")
|
||||
|
||||
SYNology_CHAT_WEBHOOK_URL = os.getenv("SYNology_CHAT_WEBHOOK_URL", "")
|
||||
Synology_CHAT_WEBHOOK_URL = os.getenv("Synology_CHAT_WEBHOOK_URL", "")
|
||||
|
||||
TELEGRAM_BOT_TOKEN = os.getenv("TELEGRAM_BOT_TOKEN", "")
|
||||
TELEGRAM_CHAT_ID = os.getenv("TELEGRAM_CHAT_ID", "")
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
# biz_crawler.py
|
||||
import os, sys
|
||||
import time
|
||||
from datetime import datetime
|
||||
@ -13,7 +14,7 @@ from conf.config import (
|
||||
MESSAGE_PLATFORMS, MATTERMOST_URL, MATTERMOST_BOT_TOKEN, MATTERMOST_CHANNEL_ID
|
||||
)
|
||||
from lib.send_message import MessageSender
|
||||
from lib.lib import (
|
||||
from lib.common import (
|
||||
create_mobile_driver,
|
||||
save_cookies,
|
||||
load_cookies,
|
||||
@ -22,6 +23,10 @@ from lib.lib import (
|
||||
clean_html_text
|
||||
)
|
||||
|
||||
def debug(msg):
|
||||
if DEBUG:
|
||||
print(f"[DEBUG] {msg}")
|
||||
|
||||
class NaverReviewCollector:
|
||||
def __init__(self, headless=HEADLESS):
|
||||
self.headless = headless
|
||||
@ -41,7 +46,7 @@ class NaverReviewCollector:
|
||||
try:
|
||||
modal = wait.until(EC.presence_of_element_located((By.ID, "modal-root")))
|
||||
modal.find_element(By.XPATH, './/button').click()
|
||||
except:
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
try:
|
||||
@ -49,7 +54,6 @@ class NaverReviewCollector:
|
||||
self.driver.find_element(By.ID, 'pw').send_keys(NAVER_PW)
|
||||
self.driver.find_element(By.XPATH, '//button[@type="submit"]').click()
|
||||
except Exception:
|
||||
self.driver.quit()
|
||||
return False
|
||||
|
||||
time.sleep(3)
|
||||
@ -70,9 +74,32 @@ class NaverReviewCollector:
|
||||
EC.presence_of_element_located((By.XPATH, '//*[starts-with(@class, "Header_btn_select_")]'))
|
||||
)
|
||||
return el.text.strip()
|
||||
except:
|
||||
except Exception:
|
||||
return "알수없음"
|
||||
|
||||
def extract_written_date(self, spans, li):
|
||||
labels = [s.text.strip() for s in spans]
|
||||
try:
|
||||
if "작성일" in labels:
|
||||
idx = labels.index("작성일")
|
||||
return spans[idx + 1].find_element(By.TAG_NAME, "time").text.strip()
|
||||
elif "예약자" in labels:
|
||||
return li.find_element(By.XPATH, ".//div[3]/div[1]/span[2]/time").text.strip()
|
||||
except Exception:
|
||||
return None
|
||||
|
||||
def extract_review_text(self, li):
|
||||
for i in range(4, 7):
|
||||
try:
|
||||
el = li.find_element(By.XPATH, f"./div[{i}]/a")
|
||||
if el:
|
||||
text = el.text.strip()
|
||||
return clean_html_text(el.get_attribute("innerHTML")) if text else "내용 없음"
|
||||
except Exception:
|
||||
continue
|
||||
return "내용 없음"
|
||||
|
||||
|
||||
def extract_reviews(self):
|
||||
reviews = []
|
||||
try:
|
||||
@ -81,48 +108,34 @@ class NaverReviewCollector:
|
||||
)
|
||||
lis = self.driver.find_elements(By.XPATH, "//ul[starts-with(@class, 'Review_columns_list')]/li")
|
||||
for li in lis:
|
||||
if "Review_banner__" in li.get_attribute("class"):
|
||||
continue
|
||||
|
||||
try:
|
||||
if "Review_banner__" in li.get_attribute("class"):
|
||||
continue
|
||||
|
||||
author = li.find_element(By.XPATH, ".//div[1]/a[2]/div/span/span").text.strip()
|
||||
visit_text = li.find_element(By.XPATH, ".//div[2]/div[1]/span[2]/time").text.strip()
|
||||
visit_date = datetime.strptime(visit_text.split("(")[0].replace(". ", "-").replace(".", ""), "%Y-%m-%d").strftime("%Y-%m-%d")
|
||||
visit_date = datetime.strptime(
|
||||
visit_text.split("(")[0].replace(". ", "-").replace(".", ""), "%Y-%m-%d"
|
||||
).strftime("%Y-%m-%d")
|
||||
|
||||
spans = li.find_elements(By.XPATH, ".//div[2]/div[2]/span")
|
||||
labels = [s.text.strip() for s in spans]
|
||||
written_text = None
|
||||
|
||||
if "작성일" in labels:
|
||||
idx = labels.index("작성일")
|
||||
written_text = spans[idx + 1].find_element(By.TAG_NAME, "time").text.strip()
|
||||
elif "예약자" in labels:
|
||||
try:
|
||||
written_text = li.find_element(By.XPATH, ".//div[3]/div[1]/span[2]/time").text.strip()
|
||||
except:
|
||||
continue
|
||||
|
||||
written_text = self.extract_written_date(spans, li)
|
||||
if not written_text:
|
||||
continue
|
||||
|
||||
written_date = datetime.strptime(written_text.split("(")[0].replace(". ", "-").replace(".", ""), "%Y-%m-%d").date()
|
||||
try:
|
||||
written_date = datetime.strptime(
|
||||
written_text.split("(")[0].replace(". ", "-").replace(".", ""), "%Y-%m-%d"
|
||||
).date()
|
||||
except ValueError:
|
||||
continue
|
||||
|
||||
if not (self.start_date <= written_date <= self.end_date):
|
||||
continue
|
||||
|
||||
content_el = None
|
||||
for i in range(4, 7):
|
||||
try:
|
||||
el = li.find_element(By.XPATH, f"./div[{i}]/a")
|
||||
if el and el.text.strip():
|
||||
content_el = el
|
||||
break
|
||||
except:
|
||||
continue
|
||||
if content_el is None:
|
||||
continue
|
||||
|
||||
html = content_el.get_attribute("innerHTML")
|
||||
text = clean_html_text(html)
|
||||
text = self.extract_review_text(li)
|
||||
#if not text:
|
||||
# continue
|
||||
|
||||
reviews.append({
|
||||
"작성자": author,
|
||||
@ -130,10 +143,9 @@ class NaverReviewCollector:
|
||||
"작성일": written_date,
|
||||
"내용": text
|
||||
})
|
||||
|
||||
except:
|
||||
except Exception:
|
||||
continue
|
||||
except:
|
||||
except Exception:
|
||||
pass
|
||||
return reviews
|
||||
|
||||
@ -163,9 +175,10 @@ class NaverReviewCollector:
|
||||
lines.append("---")
|
||||
|
||||
message = "\n".join(lines)
|
||||
|
||||
if not MESSAGE_PLATFORMS:
|
||||
print("[WARN] 메시지 전송 플랫폼이 지정되지 않음. 미전송")
|
||||
print(f"[DEBUG] {message}")
|
||||
debug(message)
|
||||
return
|
||||
|
||||
sender = MessageSender(
|
||||
@ -175,38 +188,40 @@ class NaverReviewCollector:
|
||||
)
|
||||
|
||||
if DEBUG:
|
||||
print(f"[DEBUG] message platform : {MESSAGE_PLATFORMS}")
|
||||
print("[DEBUG] 디버그 모드 메시지 미전송")
|
||||
print(f"[DEBUG] {message}")
|
||||
debug(f"메시지 플랫폼: {MESSAGE_PLATFORMS}")
|
||||
debug("디버그 모드: 메시지 전송 생략")
|
||||
debug(message)
|
||||
else:
|
||||
sender.send(message, platforms=MESSAGE_PLATFORMS, use_webhook=False)
|
||||
|
||||
def run(self):
|
||||
self.create_driver()
|
||||
self.driver.get("https://naver.com")
|
||||
time.sleep(1)
|
||||
while True:
|
||||
self.create_driver()
|
||||
self.driver.get("https://naver.com")
|
||||
time.sleep(1)
|
||||
|
||||
if os.path.exists(COOKIE_FILE):
|
||||
try:
|
||||
load_cookies(self.driver, COOKIE_FILE)
|
||||
self.driver.get("https://naver.com")
|
||||
time.sleep(1)
|
||||
except:
|
||||
os.remove(COOKIE_FILE)
|
||||
if os.path.exists(COOKIE_FILE):
|
||||
try:
|
||||
load_cookies(self.driver, COOKIE_FILE)
|
||||
self.driver.get("https://naver.com")
|
||||
time.sleep(1)
|
||||
except Exception:
|
||||
os.remove(COOKIE_FILE)
|
||||
self.driver.quit()
|
||||
self.headless = False
|
||||
continue
|
||||
else:
|
||||
if self.headless:
|
||||
self.driver.quit()
|
||||
self.headless = False
|
||||
continue
|
||||
if not self.perform_login():
|
||||
self.driver.quit()
|
||||
return
|
||||
self.driver.quit()
|
||||
NaverReviewCollector(headless=False).run()
|
||||
return
|
||||
else:
|
||||
if self.headless:
|
||||
self.driver.quit()
|
||||
NaverReviewCollector(headless=False).run()
|
||||
return
|
||||
if not self.perform_login():
|
||||
self.driver.quit()
|
||||
return
|
||||
self.driver.quit()
|
||||
NaverReviewCollector(headless=self.headless).run()
|
||||
return
|
||||
continue
|
||||
|
||||
break # 쿠키 로딩 또는 로그인 성공 시 루프 종료
|
||||
|
||||
for biz_id in BIZ_ID:
|
||||
place_name = self.access_review_page(biz_id)
|
||||
@ -215,8 +230,8 @@ class NaverReviewCollector:
|
||||
print("[WARN] 세션 만료 또는 쿠키 무효. 로그인 재진행")
|
||||
os.remove(COOKIE_FILE)
|
||||
self.driver.quit()
|
||||
NaverReviewCollector(headless=False).run()
|
||||
return
|
||||
self.headless = False
|
||||
return self.run()
|
||||
|
||||
try:
|
||||
reviews = self.extract_reviews()
|
||||
@ -228,13 +243,14 @@ class NaverReviewCollector:
|
||||
self.reviews_by_place[place_name] = []
|
||||
|
||||
self.driver.quit()
|
||||
|
||||
|
||||
if not self.reviews_by_place:
|
||||
sender = MessageSender(
|
||||
mattermost_url=MATTERMOST_URL,
|
||||
mattermost_bot_token=MATTERMOST_BOT_TOKEN,
|
||||
mattermost_token=MATTERMOST_BOT_TOKEN,
|
||||
mattermost_channel_id=MATTERMOST_CHANNEL_ID,
|
||||
)
|
||||
|
||||
send_failure_message(sender, MESSAGE_PLATFORMS)
|
||||
else:
|
||||
self.send_to_message()
|
||||
|
||||
@ -1,12 +1,11 @@
|
||||
# lib/lib.py
|
||||
|
||||
import os
|
||||
import sys
|
||||
import os, sys
|
||||
import time
|
||||
import pickle
|
||||
import re
|
||||
from datetime import datetime, timedelta
|
||||
import undetected_chromedriver as uc
|
||||
from datetime import datetime, timedelta
|
||||
from selenium.webdriver.common.by import By
|
||||
|
||||
# 공통 설정 경로 추가 (필요 시)
|
||||
@ -1,3 +1,4 @@
|
||||
# naver_review_crawler.py
|
||||
import os, sys
|
||||
from datetime import datetime
|
||||
from selenium.webdriver.common.by import By
|
||||
@ -7,11 +8,11 @@ from selenium.webdriver.support import expected_conditions as EC
|
||||
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
|
||||
|
||||
from conf.config import (
|
||||
PLACE_IDS, START_DATE, END_DATE, DEBUG,
|
||||
PLACE_IDS, START_DATE, END_DATE, DEBUG,
|
||||
MESSAGE_PLATFORMS, MATTERMOST_URL, MATTERMOST_BOT_TOKEN, MATTERMOST_CHANNEL_ID
|
||||
)
|
||||
)
|
||||
from lib.send_message import MessageSender
|
||||
from lib.lib import (
|
||||
from lib.common import (
|
||||
create_mobile_driver,
|
||||
get_start_end_dates,
|
||||
parse_korean_date,
|
||||
@ -21,7 +22,13 @@ from lib.lib import (
|
||||
send_failure_message
|
||||
)
|
||||
|
||||
class NaverReviewMapCollector:
|
||||
|
||||
def debug(msg):
|
||||
if DEBUG:
|
||||
print(f"[DEBUG] {msg}")
|
||||
|
||||
|
||||
class NaverMapReviewCollector:
|
||||
def __init__(self):
|
||||
self.driver = None
|
||||
self.total_reviews = 0
|
||||
@ -30,40 +37,46 @@ class NaverReviewMapCollector:
|
||||
|
||||
def extract_reviews(self):
|
||||
reviews = []
|
||||
WebDriverWait(self.driver, 10).until(
|
||||
EC.presence_of_element_located((By.ID, "_review_list"))
|
||||
)
|
||||
ul = self.driver.find_element(By.ID, "_review_list")
|
||||
items = ul.find_elements(By.XPATH, './/li[contains(@class, "place_apply_pui")]')
|
||||
for item in items:
|
||||
try:
|
||||
writer = "익명"
|
||||
try:
|
||||
writer = item.find_element(By.XPATH, "./div[1]/a[2]/div/span/span").text.strip()
|
||||
except:
|
||||
pass
|
||||
try:
|
||||
WebDriverWait(self.driver, 10).until(
|
||||
EC.presence_of_element_located((By.ID, "_review_list"))
|
||||
)
|
||||
ul = self.driver.find_element(By.ID, "_review_list")
|
||||
items = ul.find_elements(By.XPATH, './/li[contains(@class, "place_apply_pui")]')
|
||||
|
||||
date_obj = None
|
||||
for item in items:
|
||||
try:
|
||||
date_text = item.find_element(By.XPATH, "./div[7]/div[2]/div/span[1]/span[2]").text.strip()
|
||||
date_obj = parse_korean_date(date_text)
|
||||
except:
|
||||
continue
|
||||
writer = "익명"
|
||||
try:
|
||||
writer = item.find_element(By.XPATH, "./div[1]/a[2]/div/span/span").text.strip()
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
text = ""
|
||||
try:
|
||||
text = item.find_element(By.XPATH, "./div[5]/a").get_attribute("innerHTML")
|
||||
except:
|
||||
continue
|
||||
try:
|
||||
date_text = item.find_element(By.XPATH, "./div[7]/div[2]/div/span[1]/span[2]").text.strip()
|
||||
date_obj = parse_korean_date(date_text)
|
||||
except Exception:
|
||||
continue
|
||||
|
||||
if not (self.start_date <= date_obj <= self.end_date):
|
||||
continue
|
||||
|
||||
try:
|
||||
text_html = item.find_element(By.XPATH, "./div[5]/a").get_attribute("innerHTML")
|
||||
content = clean_html_text(text_html)
|
||||
except Exception:
|
||||
continue
|
||||
|
||||
if date_obj and (self.start_date <= date_obj <= self.end_date):
|
||||
reviews.append({
|
||||
"작성자": writer,
|
||||
"작성일": date_obj,
|
||||
"내용": clean_html_text(text)
|
||||
"내용": content
|
||||
})
|
||||
except Exception as e:
|
||||
print(f"[WARN] 리뷰 추출 실패: {e}")
|
||||
|
||||
except Exception as e:
|
||||
debug(f"[WARN] 리뷰 항목 처리 중 오류: {e}")
|
||||
except Exception as e:
|
||||
debug(f"[ERROR] 리뷰 리스트 접근 실패: {e}")
|
||||
return reviews
|
||||
|
||||
def send_to_message(self):
|
||||
@ -91,9 +104,10 @@ class NaverReviewMapCollector:
|
||||
lines.append("---")
|
||||
|
||||
message = "\n".join(lines)
|
||||
|
||||
if not MESSAGE_PLATFORMS:
|
||||
print("[WARN] 메시지 전송 플랫폼 없음")
|
||||
print(f"[DEBUG] {message}")
|
||||
print("[WARN] 메시지 전송 플랫폼이 지정되지 않음")
|
||||
debug(message)
|
||||
return
|
||||
|
||||
sender = MessageSender(
|
||||
@ -103,8 +117,8 @@ class NaverReviewMapCollector:
|
||||
)
|
||||
|
||||
if DEBUG:
|
||||
print("[DEBUG] 디버그 모드로 메시지 미전송")
|
||||
print(message)
|
||||
debug("디버그 모드로 메시지 전송 생략")
|
||||
debug(message)
|
||||
else:
|
||||
sender.send(message, platforms=MESSAGE_PLATFORMS, use_webhook=False)
|
||||
|
||||
@ -114,10 +128,15 @@ class NaverReviewMapCollector:
|
||||
for place_id in PLACE_IDS:
|
||||
url = f"https://m.place.naver.com/place/{place_id}/review/visitor?reviewSort=recent"
|
||||
print(f"[INFO] 접근: {url}")
|
||||
self.driver.get(url)
|
||||
shop_name = extract_shop_name(self.driver)
|
||||
try:
|
||||
self.driver.get(url)
|
||||
shop_name = extract_shop_name(self.driver)
|
||||
except Exception as e:
|
||||
print(f"[ERROR] {place_id} 매장 접근 오류: {e}")
|
||||
continue
|
||||
|
||||
all_reviews = []
|
||||
seen = set()
|
||||
seen = set() # (작성자, 작성일, 내용) 기준으로 중복 제거
|
||||
|
||||
while True:
|
||||
new_reviews = self.extract_reviews()
|
||||
@ -135,6 +154,7 @@ class NaverReviewMapCollector:
|
||||
break
|
||||
|
||||
all_reviews.extend(filtered)
|
||||
|
||||
if not click_more(self.driver):
|
||||
break
|
||||
|
||||
@ -154,6 +174,7 @@ class NaverReviewMapCollector:
|
||||
else:
|
||||
self.send_to_message()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
collector = NaverReviewMapCollector()
|
||||
collector = NaverMapReviewCollector()
|
||||
collector.run()
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
# send_message.py
|
||||
import requests
|
||||
|
||||
class MessageSender:
|
||||
|
||||
2
naver_review_bot.bat
Normal file
2
naver_review_bot.bat
Normal file
@ -0,0 +1,2 @@
|
||||
@echo off
|
||||
python C:\DEV\python\fg-auto\naver_review\run.py
|
||||
4
requirements.txt
Normal file
4
requirements.txt
Normal file
@ -0,0 +1,4 @@
|
||||
selenium
|
||||
requests
|
||||
undetected_chromedriver
|
||||
dotenv
|
||||
43
run.py
43
run.py
@ -1,28 +1,27 @@
|
||||
import os
|
||||
import sys
|
||||
from dotenv import load_dotenv
|
||||
|
||||
|
||||
# 환경 변수 로드
|
||||
load_dotenv()
|
||||
|
||||
# run.py
|
||||
import os, sys
|
||||
# 프로젝트 루트 기준 경로 추가
|
||||
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), 'lib')))
|
||||
|
||||
# 실행 모드 확인
|
||||
mode = os.getenv("MODE", "").strip().lower()
|
||||
from conf import config
|
||||
|
||||
if mode == "biz":
|
||||
from lib.biz_crawler import NaverReviewCollector
|
||||
print("[INFO] 비즈니스 리뷰 수집기 실행")
|
||||
collector = NaverReviewCollector()
|
||||
collector.run()
|
||||
def main():
|
||||
mode = os.getenv("MODE", "").strip().lower()
|
||||
|
||||
elif mode == "map":
|
||||
from lib.naver_review_crawler import NaverMapReviewCollector
|
||||
print("[INFO] 지도 리뷰 수집기 실행")
|
||||
collector = NaverMapReviewCollector()
|
||||
collector.run()
|
||||
if mode == "biz":
|
||||
from lib.biz_crawler import NaverReviewCollector
|
||||
print("[INFO] 비즈니스 리뷰 수집기 실행")
|
||||
collector = NaverReviewCollector()
|
||||
collector.run()
|
||||
|
||||
else:
|
||||
print("[ERROR] .env 파일에서 MODE 값을 설정해주세요. (biz 또는 map)")
|
||||
elif mode == "map":
|
||||
from lib.naver_review_crawler import NaverMapReviewCollector
|
||||
print("[INFO] 지도 리뷰 수집기 실행")
|
||||
collector = NaverMapReviewCollector()
|
||||
collector.run()
|
||||
|
||||
else:
|
||||
print(f"[ERROR] .env 파일에서 MODE 값을 설정해주세요. (biz 또는 map) 현재값: '{mode}'")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user