- internal_code DB 저장 → 프론트에서 선택한 제품 그대로 주문 - 기존 장바구니 백업/복구로 사용자 장바구니 보존 - 수인약품 submit_order() 수정 (체크박스 제외 방식) - 테스트 파일 정리 및 문서 추가
137 lines
4.9 KiB
Python
137 lines
4.9 KiB
Python
# -*- coding: utf-8 -*-
|
||
"""
|
||
지오영 "전체삭제" 버튼 분석 - Playwright로 실제 버튼 클릭 시 API 확인
|
||
"""
|
||
import asyncio
|
||
import os
|
||
from dotenv import load_dotenv
|
||
load_dotenv(r'c:\Users\청춘약국\source\pharmacy-wholesale-api\.env')
|
||
|
||
async def analyze_delete_all():
|
||
from playwright.async_api import async_playwright
|
||
|
||
username = os.getenv('GEOYOUNG_USER_ID')
|
||
password = os.getenv('GEOYOUNG_PASSWORD')
|
||
|
||
if not username or not password:
|
||
print("❌ GEOYOUNG_USER_ID, GEOYOUNG_PASSWORD 환경변수 필요")
|
||
return
|
||
|
||
print("=" * 60)
|
||
print("지오영 '전체삭제' 버튼 분석")
|
||
print("=" * 60)
|
||
|
||
async with async_playwright() as p:
|
||
browser = await p.chromium.launch(headless=False) # 보이게
|
||
page = await browser.new_page()
|
||
|
||
# 네트워크 요청 감시
|
||
requests_log = []
|
||
|
||
def log_request(request):
|
||
if 'Cart' in request.url or 'cart' in request.url or 'del' in request.url.lower():
|
||
requests_log.append({
|
||
'method': request.method,
|
||
'url': request.url,
|
||
'post_data': request.post_data
|
||
})
|
||
print(f"🔗 {request.method} {request.url}")
|
||
if request.post_data:
|
||
print(f" POST data: {request.post_data}")
|
||
|
||
page.on('request', log_request)
|
||
|
||
# 1. 로그인
|
||
print("\n1️⃣ 로그인 중...")
|
||
await page.goto("https://gwn.geoweb.kr/Member/Login")
|
||
await page.fill('input[type="text"]', username)
|
||
await page.fill('input[type="password"]', password)
|
||
await page.click('button[type="submit"], input[type="submit"], .btn-login')
|
||
await page.wait_for_load_state('networkidle', timeout=15000)
|
||
print("✅ 로그인 완료")
|
||
|
||
# 2. 주문 페이지로 이동 (장바구니 표시됨)
|
||
print("\n2️⃣ 주문 페이지로 이동...")
|
||
await page.goto("https://gwn.geoweb.kr/Home/Order")
|
||
await page.wait_for_load_state('networkidle', timeout=15000)
|
||
|
||
# 3. 장바구니 확인
|
||
print("\n3️⃣ 장바구니 확인...")
|
||
await asyncio.sleep(2)
|
||
|
||
# 스크린샷
|
||
await page.screenshot(path='geo_cart_before.png')
|
||
print("📸 스크린샷 저장: geo_cart_before.png")
|
||
|
||
# 4. "전체삭제" 버튼 찾기
|
||
print("\n4️⃣ '전체삭제' 버튼 찾기...")
|
||
|
||
# 가능한 선택자들
|
||
selectors = [
|
||
'button:has-text("전체삭제")',
|
||
'a:has-text("전체삭제")',
|
||
'.btn-del-all',
|
||
'#btnDelAll',
|
||
'[onclick*="delAll"]',
|
||
'button:has-text("전체 삭제")',
|
||
'button:has-text("삭제")',
|
||
]
|
||
|
||
delete_btn = None
|
||
for sel in selectors:
|
||
try:
|
||
btn = page.locator(sel).first
|
||
if await btn.count() > 0:
|
||
print(f" ✅ 버튼 발견: {sel}")
|
||
# 버튼의 HTML 확인
|
||
btn_html = await btn.evaluate('el => el.outerHTML')
|
||
print(f" HTML: {btn_html[:200]}...")
|
||
delete_btn = btn
|
||
break
|
||
except:
|
||
pass
|
||
|
||
if not delete_btn:
|
||
print(" ❌ 전체삭제 버튼을 찾지 못함")
|
||
# 페이지 HTML에서 삭제 관련 요소 검색
|
||
html = await page.content()
|
||
if '전체삭제' in html or 'delAll' in html:
|
||
print(" ⚠️ 페이지에 관련 텍스트는 있음. 수동 확인 필요")
|
||
await browser.close()
|
||
return
|
||
|
||
# 5. 버튼 클릭 (네트워크 요청 감시)
|
||
print("\n5️⃣ '전체삭제' 버튼 클릭...")
|
||
requests_log.clear()
|
||
|
||
try:
|
||
await delete_btn.click()
|
||
await asyncio.sleep(2)
|
||
|
||
# confirm 다이얼로그 처리
|
||
page.on('dialog', lambda dialog: asyncio.create_task(dialog.accept()))
|
||
|
||
await page.wait_for_load_state('networkidle', timeout=5000)
|
||
except Exception as e:
|
||
print(f" ⚠️ 클릭 중 오류: {e}")
|
||
|
||
# 6. 캡처된 요청 출력
|
||
print("\n6️⃣ 캡처된 API 요청:")
|
||
for req in requests_log:
|
||
print(f" 📤 {req['method']} {req['url']}")
|
||
if req['post_data']:
|
||
print(f" Body: {req['post_data']}")
|
||
|
||
# 스크린샷
|
||
await page.screenshot(path='geo_cart_after.png')
|
||
print("\n📸 스크린샷 저장: geo_cart_after.png")
|
||
|
||
print("\n잠시 대기 (확인용)...")
|
||
await asyncio.sleep(5)
|
||
|
||
await browser.close()
|
||
print("\n✅ 완료")
|
||
|
||
if __name__ == "__main__":
|
||
asyncio.run(analyze_delete_all())
|