from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import json
import time
import sys
# 한글 출력 인코딩 설정
if sys.stdout.encoding.lower() != 'utf-8':
sys.stdout.reconfigure(encoding='utf-8')
chrome_options = Options()
chrome_options.add_argument("user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36")
chrome_options.add_experimental_option("excludeSwitches", ["enable-automation"])
chrome_options.add_experimental_option('useAutomationExtension', False)
service = Service(r"C:\\Users\\light\\Documents\\chromedriver-win64\\chromedriver.exe")
driver = webdriver.Chrome(service=service, options=chrome_options)
driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {
"source": """
Object.defineProperty(navigator, 'webdriver', {
get: () => undefined
})
"""
})
wait = WebDriverWait(driver, 15)
url = "<https://www.lguplus.com/mobile/plan/mplan/plan-all>"
driver.get(url)
time.sleep(3)
# "더보기" 버튼 반복 클릭 (최대 30번 안전장치)
for _ in range(30):
try:
btn = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "button.btn-more")))
if not btn.is_enabled() or "disabled" in btn.get_attribute("class"):
break
driver.execute_script("arguments[0].click();", btn)
time.sleep(2)
except Exception as e:
print("더보기 버튼 없음 또는 클릭 불가:", e)
break
# 요금제 카드 수집: ul.plan-list > li
plans = []
try:
cards = driver.find_elements(By.CSS_SELECTOR, "ul.plan-list > li")
print(f"{len(cards)}개 요금제 카드 발견")
except Exception as e:
print(" 요금제 카드 로딩 실패:", e)
driver.quit()
exit()
for idx, card in enumerate(cards, 1):
try:
# 요금제명
name = card.find_element(By.CSS_SELECTOR, "button.btn-plan").text.strip()
# 인기 뱃지
try:
badge = card.find_element(By.CSS_SELECTOR, "span.ico-flag").text.strip()
except:
badge = None
# 데이터, 테더링 등 주요 정보
infos = [em.text.strip() for em in card.find_elements(By.CSS_SELECTOR, "p.plan-info em")]
# 가격 정보
try:
price = card.find_element(By.CSS_SELECTOR, "span.price").text.strip()
except:
price = None
try:
sale_price = card.find_element(By.CSS_SELECTOR, "span.sale-price").text.strip()
except:
sale_price = None
# 브랜드 정보
brands = []
for img in card.find_elements(By.CSS_SELECTOR, "div.brand-wrap img[alt]"):
alt = img.get_attribute("alt")
if alt:
brands.append(alt.strip())
# 혜택 정보
benefits = {}
try:
benefit_divs = card.find_elements(By.CSS_SELECTOR, "dl.benefit-area > div")
for div in benefit_divs:
try:
dt = div.find_element(By.CSS_SELECTOR, "dt").text.strip()
dd = div.find_element(By.CSS_SELECTOR, "dd").text.strip()
benefits[dt] = dd
except:
continue
except:
pass
# 속도 정보 (선택적)
try:
plan_speed = card.find_element(By.CSS_SELECTOR, "span.plan-speed").text.strip()
except:
plan_speed = None
plan = {
"name": name,
"badge": badge,
"infos": infos,
"plan_speed": plan_speed,
"price": price,
"sale_price": sale_price,
"brands": brands,
"benefits": benefits
}
plans.append(plan)
print(f" {idx}번째 요금제 저장: {name}")
except Exception as e:
print(f" {idx}번째 요금제 파싱 실패:", e)
with open("plans_structured.json", "w", encoding="utf-8") as f:
json.dump(plans, f, ensure_ascii=False, indent=2)
print(f"\\n 총 {len(plans)}개 요금제 저장 완료 (plans_structured.json)")
time.sleep(2)
driver.quit()