Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,17 @@ on:
branches: [main]

jobs:
browser:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.12"
- run: pip install -e ".[dev,browser]"
- run: python -m playwright install --with-deps chromium
- run: python -m pytest tests/test_browser_playwright.py -q

typecheck:
runs-on: ubuntu-latest
steps:
Expand Down
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
# Changelog

## 2026-10-24 — 무작위 조작 대기와 HTML 결과 대기 단축

- 기본 클릭·선택 대기를 0.25~1.25초에서 0.05~0.15초로 줄이고 매 조작의 랜덤성을 유지한다.
- 시군구 선택이 이미 보낸 정상 조회 POST의 지역·탭·검색 모드·필터를 검증해 결과를
재사용하고 중복 버튼 조회를 줄인다. 지역 AJAX 목록과 실제 옵션의 일치를 확인한다.
- image/font/media만 제외하고 HTML 문서 완료·선택 지역·활성 탭 검증을 유지해
load handler의 동적 추가 행도 보존한다. HTTP 캐시 비활성화 비용은 실측으로 확인한다.
- 30분은 실제 전국 실행으로 검증할 목표이며 미검증 속도 향상률을 보장하지 않는다.

## 2026-10-24 — 지역 체크포인트와 저장 재개

- 선택적인 영속 체크포인트로 지역 목록·완료 결과·요청 예산을 보존하고 미완료 지역부터 재개한다.
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,11 +85,11 @@ playwright install chromium
```

웹 화면 수집기는 공식 API의 대체물이 아닌 실험 기능입니다. 기본적으로
시군구 단위로 조회해 요청 수를 줄이고, 화면 조작 사이에는 짧은 무작위 지연,
시군구 단위로 조회해 요청 수를 줄이고, 화면 조작 사이에는 0.05~0.15초 무작위 지연,
전체 수집 사이에는 기본 8시간 간격을 적용하며 최근 24시간 실행 횟수를 최대
3회로 제한합니다. 자동화 탐지
우회, 브라우저 지문 조작, CAPTCHA 우회는 수행하지 않으며 사이트가 접근을
거부하면 오류로 중단합니다. 한 실행의 검색 요청 상한과 지역 AJAX 완료 상태도
거부하면 오류로 중단합니다. 한 실행의 지역 조회 시도 상한과 지역 AJAX 완료 상태도
검사해 접근 거부나 부분 결과를 정상적인 빈 결과로 저장하지 않습니다. 운영 전
[오피넷 이용약관·저작권·공개 API 안내](https://www.opinet.co.kr/user/custapi/openApiInfo.do)와
허용된 수집·보관·재배포 범위를 확인해야 합니다. 자세한 사용법은
Expand Down
34 changes: 33 additions & 1 deletion docs/browser-collection.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,35 @@
# 지역별 웹 화면 수집기

## 2026-10-24 수집 시간 단축

기본 화면 조작 간격은 매번 독립적으로 뽑는 **0.05~0.15초 무작위 대기**다.
기존 0.25~1.25초보다 평균 대기는 0.75초에서 0.10초로 줄지만 랜덤성은 유지한다.
지역 선택 AJAX 완료·선택값 일치·검색 응답 검증은 생략하지 않는다.
지역 선택은 헤더 수신뿐 아니라 응답 본문 완료까지 제한 시간 안에 기다린 뒤
하위 목록과 선택값을 확인한다. 빈 결과도 선택 지역·활성 탭이 맞아야 확정한다.

가격 파싱에 쓰지 않는 `image`·`font`·`media` 요청만 제외하고 문서·스크립트·스타일·
XHR·fetch는 유지한다. HTML은 문서 완료 뒤 읽어 `load` handler가 추가하는 결과도
포함한다. 이미지의 `alt` 등 DOM 속성은 보존한다. 요청 라우팅에 따른 HTTP 캐시 비활성화
비용도 있으므로 운영 속도는 실제 실행으로 확인한다.

실제 공개 화면에서 시군구 선택이 이미 결과 문서 POST를 보낸다. 시군구 모드에서 해당
선택이 낸 main-frame 문서 응답의 지역·빈 읍면동·검색 모드·탭·빈 상호/주소 필터가 모두
일치할 때 이를 재사용해 조회 버튼의 중복 POST를 줄인다. 동일 지역 선택이나 필터 등
조건이 맞지 않으면 기존 조회 버튼으로 진행한다. 코드에서 form을 직접 제출하지 않는다.
활성 탭은 부모 `li.sel`과 `BTN_DIV`·`LPG_YN`도 함께 확인한다.

시도 선택은 공개 `sigunguGisAjax`의 `result` 배열과 `SIGUNGU_NM`을 읽고 화면 옵션의
값·이름·순서를 정확히 대조한다. 정상 빈 목록도 본문과 대조하므로 고정 대기 길이에
의존해 이전 목록을 읽지 않는다. 시군구 선택의 문서 이동은 새 문서 완료를 확인한다.
기존 전국 문서 조회량 약1150회에서 탐색·중복 버튼 조회를 줄인 약460회는 요청량 모델이며,
실제 시간 단축률은 아니다. 자동 조회의 시간은 `selection` 누적 시간에 포함된다.

전국 약230개 시군구·460회 검색의 30분 목표는 시작·탐색 약120초, 랜덤 대기 약100초를
제외한 지역 선택·응답·파싱 평균이 약3.4초 이하여야 한다. 이는 시간 예산이며 운영 실측
보장이 아니다. `selection`·`response`·`results` 누적 로그로 실제 병목을 확인한다.
실제 전국 수집을 30분 안에 완료하기 전에는 목표 달성으로 보고하지 않는다.

## 2026-10-24 재개와 수집 비용

`OpinetBrowserCollector(checkpoint_path="/persistent/opinet.sqlite3")`는 지역별 정상 결과를
Expand Down Expand Up @@ -108,7 +138,7 @@ timeout 원인의 해결을 뜻하지는 않으며, 실제 수집 복구는 별

## 반복 수집과 부하 분산

기본 `OpinetBrowserThrottle`은 화면 조작 사이에 0.25~1.25초의 무작위 대기를
기본 `OpinetBrowserThrottle`은 화면 조작 사이에 0.05~0.15초의 무작위 대기를
넣고, 전체 수집 사이에는 8시간의 대기를 선택한다. 최근 24시간 실행 횟수는
최대 3회로 제한한다. 이 지연은
사람인 것처럼 보이기 위한 기능이 아니라 요청과 화면 갱신을 한 시점에 몰리지
Expand Down Expand Up @@ -145,6 +175,8 @@ asyncio.run(main())
8시간을 기다린다. 최근 24시간에 3회 실행한 경우에는 다음 실행 가능 시각까지
추가로 기다린다. `stop_event.set()` 또는 `asyncio` 작업 취소로 중단할 수 있다.
한 실행은 `max_search_requests`를 넘는 지역 조회를 시작하지 않는다.
이 예산의 단위는 탭별 지역 조회 시도다. 재시도는 별도1회를 차감하며, 선택 AJAX나
필터 때문에 재사용하지 못한 자동 선택 POST까지 포함한 전체 HTTP 요청 수 상한은 아니다.
저장 실패나 일시적 네트워크 오류 후에도 다음 주기를 예약하려면 `on_error`에
호출 애플리케이션의 알림 함수를 전달한다. 기본값은 오류를 호출자에게 전파해
실패를 숨기지 않는다. `max_runs_per_24h`는 하나의 `run_forever()` 작업에
Expand Down
5 changes: 5 additions & 0 deletions docs/implementation-status.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# python-opinet-api Implementation Status

2026-10-24 추가: 기본 무작위 조작 대기를 0.05~0.15초로 단축하고 시군구 선택의
정상 자동 조회 응답을 검증해 중복 버튼 조회를 줄인다. 시도 응답 목록과 실제 옵션을
대조하며 가격 파싱에 쓰지 않는 시각 자원을 제외한다. 문서 완료·지역·탭 검증을 유지해
동적 추가 행을 빠뜨리지 않는다. 운영 전국30분 목표는 실제 실행으로 별도 확인한다.

2026-10-24: 지역별 영속 체크포인트·완료 결과 재전달·단일 작성자 잠금·시군구 탐색 최적화를
추가했다. [복구 계약](browser-collection.md)을 따른다. 실제 운영 속도 개선률은 미측정이며
단계별 누적 시간 로그로 지역 선택·응답·결과 준비 비용을 구분한다.
Expand Down
Loading
Loading