- internal_code DB 저장 → 프론트에서 선택한 제품 그대로 주문 - 기존 장바구니 백업/복구로 사용자 장바구니 보존 - 수인약품 submit_order() 수정 (체크박스 제외 방식) - 테스트 파일 정리 및 문서 추가
146 lines
5.2 KiB
Python
146 lines
5.2 KiB
Python
# -*- coding: utf-8 -*-
|
||
"""
|
||
지오영 장바구니 HTML 분석 및 삭제 버튼 API 캡처
|
||
"""
|
||
import asyncio
|
||
import os
|
||
import re
|
||
from dotenv import load_dotenv
|
||
load_dotenv(r'c:\Users\청춘약국\source\pharmacy-wholesale-api\.env')
|
||
|
||
async def analyze_cart_html():
|
||
from playwright.async_api import async_playwright
|
||
|
||
username = os.getenv('GEOYOUNG_USER_ID')
|
||
password = os.getenv('GEOYOUNG_PASSWORD')
|
||
|
||
print("=" * 60)
|
||
print("지오영 장바구니 HTML 분석")
|
||
print("=" * 60)
|
||
|
||
async with async_playwright() as p:
|
||
browser = await p.chromium.launch(headless=True)
|
||
context = await browser.new_context()
|
||
page = await context.new_page()
|
||
|
||
# 1. 로그인
|
||
print("\n1️⃣ 로그인 중...")
|
||
await page.goto("https://gwn.geoweb.kr/Member/Login")
|
||
await page.wait_for_load_state('networkidle')
|
||
|
||
# 로그인 폼 찾기
|
||
await page.fill('input[type="text"], input[name*="id"], #userId', username)
|
||
await page.fill('input[type="password"], input[name*="pw"], #userPwd', password)
|
||
|
||
# 로그인 버튼 클릭
|
||
login_btns = ['button[type="submit"]', 'input[type="submit"]', '.btn-login', 'button:has-text("로그인")']
|
||
for btn_sel in login_btns:
|
||
try:
|
||
btn = page.locator(btn_sel).first
|
||
if await btn.count() > 0:
|
||
await btn.click()
|
||
break
|
||
except:
|
||
pass
|
||
|
||
await asyncio.sleep(3)
|
||
await page.wait_for_load_state('networkidle')
|
||
|
||
# 로그인 확인
|
||
if 'Login' in page.url:
|
||
print("❌ 로그인 실패")
|
||
await browser.close()
|
||
return
|
||
|
||
print(f"✅ 로그인 성공 (URL: {page.url})")
|
||
|
||
# 2. 장바구니 HTML 가져오기 (AJAX)
|
||
print("\n2️⃣ 장바구니 HTML 가져오기...")
|
||
|
||
# PartialProductCart API 직접 호출
|
||
cart_response = await page.evaluate('''
|
||
async () => {
|
||
const response = await fetch('/Home/PartialProductCart', {
|
||
method: 'POST',
|
||
headers: {'X-Requested-With': 'XMLHttpRequest'}
|
||
});
|
||
return await response.text();
|
||
}
|
||
''')
|
||
|
||
print(f"\n📦 장바구니 HTML 길이: {len(cart_response)} bytes")
|
||
|
||
# 삭제 관련 키워드 찾기
|
||
patterns = [
|
||
r'onclick="[^"]*del[^"]*"',
|
||
r'onclick="[^"]*Del[^"]*"',
|
||
r'onclick="[^"]*삭제[^"]*"',
|
||
r'class="[^"]*del[^"]*"',
|
||
r'id="[^"]*del[^"]*"',
|
||
r'function\s+\w*[dD]el\w*\s*\(',
|
||
r'전체\s*삭제',
|
||
r'delAll',
|
||
r'deleteAll',
|
||
]
|
||
|
||
print("\n🔍 삭제 관련 패턴 검색:")
|
||
for pattern in patterns:
|
||
matches = re.findall(pattern, cart_response, re.IGNORECASE)
|
||
if matches:
|
||
for m in matches[:3]: # 최대 3개만
|
||
print(f" ✅ {pattern}: {m[:100]}...")
|
||
|
||
# 버튼 요소 찾기
|
||
print("\n🔘 버튼 요소:")
|
||
button_pattern = r'<button[^>]*>.*?</button>|<a[^>]*class="[^"]*btn[^"]*"[^>]*>.*?</a>'
|
||
buttons = re.findall(button_pattern, cart_response, re.DOTALL | re.IGNORECASE)
|
||
for btn in buttons[:10]:
|
||
clean_btn = re.sub(r'\s+', ' ', btn)[:150]
|
||
print(f" • {clean_btn}")
|
||
|
||
# JavaScript 함수 찾기
|
||
print("\n📜 JavaScript 함수 (del/remove 관련):")
|
||
js_pattern = r'function\s+(\w*[dD]el\w*|\w*[rR]emove\w*)\s*\([^)]*\)\s*\{[^}]*\}'
|
||
js_funcs = re.findall(js_pattern, cart_response)
|
||
for func in js_funcs[:5]:
|
||
print(f" • {func}")
|
||
|
||
# 전체 스크립트 태그에서 DataCart 관련 찾기
|
||
print("\n🔧 DataCart API 호출 패턴:")
|
||
datacart_pattern = r'DataCart[^"\']*'
|
||
datacart_matches = re.findall(datacart_pattern, cart_response)
|
||
for m in set(datacart_matches):
|
||
print(f" • {m}")
|
||
|
||
# 페이지 전체 HTML에서도 검색
|
||
print("\n3️⃣ 메인 페이지에서 추가 검색...")
|
||
await page.goto("https://gwn.geoweb.kr/Home/Order")
|
||
await page.wait_for_load_state('networkidle')
|
||
await asyncio.sleep(2)
|
||
|
||
full_html = await page.content()
|
||
|
||
# DataCart 관련 전체 검색
|
||
print("\n🔧 전체 페이지 DataCart API:")
|
||
datacart_all = re.findall(r'/Home/DataCart/\w+', full_html)
|
||
for api in set(datacart_all):
|
||
print(f" • {api}")
|
||
|
||
# 삭제 함수 찾기
|
||
print("\n📜 삭제 관련 함수:")
|
||
del_funcs = re.findall(r'function\s+(\w*[dD]el\w*)\s*\(', full_html)
|
||
for func in set(del_funcs):
|
||
print(f" • {func}()")
|
||
|
||
# 삭제 onclick 찾기
|
||
print("\n🖱️ 삭제 onclick:")
|
||
del_onclick = re.findall(r'onclick="([^"]*[dD]el[^"]*)"', full_html)
|
||
for onclick in set(del_onclick)[:5]:
|
||
print(f" • {onclick[:100]}")
|
||
|
||
await browser.close()
|
||
print("\n✅ 분석 완료")
|
||
|
||
if __name__ == "__main__":
|
||
asyncio.run(analyze_cart_html())
|