crawler_api.py - 클릭방식으로 변환
This commit is contained in:
@@ -9,6 +9,7 @@ from fastapi.responses import StreamingResponse, FileResponse
|
||||
from fastapi.staticfiles import StaticFiles
|
||||
from playwright.async_api import async_playwright
|
||||
from dotenv import load_dotenv
|
||||
from analyze import analyze_file_content
|
||||
|
||||
load_dotenv()
|
||||
|
||||
@@ -25,10 +26,37 @@ app.add_middleware(
|
||||
allow_headers=["*"],
|
||||
)
|
||||
|
||||
@app.get("/")
|
||||
@app.get("/dashboard")
|
||||
async def get_dashboard():
|
||||
return FileResponse("dashboard.html")
|
||||
|
||||
@app.get("/mailTest")
|
||||
async def get_mail_test():
|
||||
return FileResponse("mailTest.html")
|
||||
|
||||
@app.get("/attachments")
|
||||
async def get_attachments():
|
||||
sample_path = "sample"
|
||||
if not os.path.exists(sample_path):
|
||||
os.makedirs(sample_path)
|
||||
files = []
|
||||
for f in os.listdir(sample_path):
|
||||
f_path = os.path.join(sample_path, f)
|
||||
if os.path.isfile(f_path):
|
||||
files.append({
|
||||
"name": f,
|
||||
"size": f"{os.path.getsize(f_path) / 1024:.1f} KB"
|
||||
})
|
||||
return files
|
||||
|
||||
@app.get("/analyze-file")
|
||||
async def analyze_file(filename: str):
|
||||
return analyze_file_content(filename)
|
||||
|
||||
@app.get("/")
|
||||
async def root():
|
||||
return FileResponse("index.html")
|
||||
|
||||
@app.get("/sync")
|
||||
async def sync_data():
|
||||
async def event_generator():
|
||||
@@ -97,18 +125,18 @@ async def sync_data():
|
||||
|
||||
modal_sel = "article.archive-modal"
|
||||
if await page.locator(modal_sel).is_visible():
|
||||
yield f"data: {json.dumps({'type': 'log', 'message': ' - [로그] 모달 발견. 데이터 추출 중...'})}\n\n"
|
||||
# 사용자 제공 정밀 셀렉터 기반 추출
|
||||
date_sel = "body > article.archive-modal > div > div > div.modal-body > div.log-wrap > div.log-item-wrap.log-body.scrollbar.scroll-container > div.date > div.text"
|
||||
user_sel = "body > article.archive-modal > div > div > div.modal-body > div.log-wrap > div.log-item-wrap.log-body.scrollbar.scroll-container > div.user > div.text"
|
||||
act_sel = "body > article.archive-modal > div > div > div.modal-body > div.log-wrap > div.log-item-wrap.log-body.scrollbar.scroll-container > div.activity > div.text"
|
||||
yield f"data: {json.dumps({'type': 'log', 'message': ' - [로그] 모달 발견. 데이터 로딩 대기...'})}\n\n"
|
||||
# .log-body 내부의 데이터만 타겟팅하도록 수정
|
||||
date_sel = "article.archive-modal .log-body .date .text"
|
||||
user_sel = "article.archive-modal .log-body .user .text"
|
||||
act_sel = "article.archive-modal .log-body .activity .text"
|
||||
|
||||
# 데이터가 나타날 때까지 반복 대기
|
||||
# 데이터가 나타날 때까지 최대 15초 대기
|
||||
success_log = False
|
||||
for _ in range(10):
|
||||
for _ in range(15):
|
||||
if await page.locator(date_sel).count() > 0:
|
||||
raw_date = (await page.locator(date_sel).first.inner_text()).strip()
|
||||
if raw_date and "활동시간" not in raw_date:
|
||||
if raw_date:
|
||||
success_log = True
|
||||
break
|
||||
await asyncio.sleep(1)
|
||||
@@ -148,32 +176,33 @@ async def sync_data():
|
||||
await asyncio.sleep(0.5)
|
||||
|
||||
if popup_page:
|
||||
yield f"data: {json.dumps({'type': 'log', 'message': ' - [구성] 창 발견. 데이터 로딩 대기 (최대 80초)...'})}\n\n"
|
||||
target_selector = "#composition-list h6"
|
||||
yield f"data: {json.dumps({'type': 'log', 'message': ' - [구성] 창 발견. 데이터 로딩 대기 (최대 30초)...'})}\n\n"
|
||||
# 사용자 제공 정밀 선택자 적용 (nth-child(3)가 실제 데이터)
|
||||
target_selector = "#composition-list h6:nth-child(3)"
|
||||
success_comp = False
|
||||
|
||||
# 최대 80초간 끝까지 대기
|
||||
for _ in range(80):
|
||||
# 최대 30초간 데이터가 나타날 때까지 대기
|
||||
for _ in range(30):
|
||||
h6_count = await popup_page.locator(target_selector).count()
|
||||
if h6_count > 5: # 일정 개수 이상의 목록이 나타나면 로딩 시작으로 간주
|
||||
if h6_count > 0:
|
||||
success_comp = True
|
||||
break
|
||||
await asyncio.sleep(1)
|
||||
|
||||
if success_comp:
|
||||
yield f"data: {json.dumps({'type': 'log', 'message': ' - [구성] 데이터 감지됨. 15초간 최종 렌더링 대기...'})}\n\n"
|
||||
await asyncio.sleep(15) # 완전한 로딩을 위한 강제 대기
|
||||
yield f"data: {json.dumps({'type': 'log', 'message': ' - [구성] 데이터 감지됨. 최종 렌더링 대기...'})}\n\n"
|
||||
await asyncio.sleep(10) # 렌더링 안정화를 위한 대기
|
||||
|
||||
# 유연한 데이터 수집
|
||||
# 모든 h6:nth-child(3) 요소를 순회하며 숫자 합산
|
||||
locators_h6 = popup_page.locator(target_selector)
|
||||
h6_count = await locators_h6.count()
|
||||
current_total = 0
|
||||
for j in range(h6_count):
|
||||
text = (await locators_h6.nth(j).inner_text()).strip()
|
||||
# 텍스트 내에서 숫자만 추출 (여러 줄일 경우 마지막 줄 기준)
|
||||
nums = re.findall(r'\d+', text.split('\n')[-1])
|
||||
if nums:
|
||||
val = int(nums[0])
|
||||
if val < 5000: current_total += val
|
||||
current_total += int(nums[0])
|
||||
|
||||
file_count = current_total
|
||||
yield f"data: {json.dumps({'type': 'log', 'message': f' - [구성] 성공 ({file_count}개)'})}\n\n"
|
||||
|
||||
Reference in New Issue
Block a user