Add auto-advance: click Next, scroll to top, capture next page
After each capture the controller asks the vision model to locate a 'Next' control (returned as normalized screen coordinates), clicks it via OS input, scrolls to top, and continues the loop. Configurable via SCREEN_LEADS_AUTO_NEXT / _NEXT_LOAD_PAUSE / _MAX_AUTO_NEXT, with a per-run safety cap. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -44,6 +44,7 @@ class CaptureController:
|
||||
self.last_event = ""
|
||||
self.captured_urls: set[str] = set()
|
||||
self.leads_captured = 0
|
||||
self._advances = 0
|
||||
self._run_id: Optional[int] = None
|
||||
|
||||
# --- introspection -------------------------------------------------------
|
||||
@@ -55,6 +56,8 @@ class CaptureController:
|
||||
"leads_captured": self.leads_captured,
|
||||
"captured_urls": len(self.captured_urls),
|
||||
"on_invalid_page": config.ON_INVALID_PAGE,
|
||||
"auto_next": config.AUTO_NEXT,
|
||||
"advances": self._advances,
|
||||
}
|
||||
|
||||
def _set(self, state: State, event: str = "") -> None:
|
||||
@@ -71,6 +74,7 @@ class CaptureController:
|
||||
self._pause.clear()
|
||||
self.reason = ""
|
||||
self.leads_captured = 0
|
||||
self._advances = 0
|
||||
self.captured_urls.clear()
|
||||
self._run_id = database.start_run()
|
||||
self._set(State.RUNNING, "started")
|
||||
@@ -149,6 +153,9 @@ class CaptureController:
|
||||
if url:
|
||||
self.captured_urls.add(url)
|
||||
self.last_event = f"saved: {lead.full_name or url}"
|
||||
# Auto-advance: click a Next control, scroll to top, capture again.
|
||||
if config.AUTO_NEXT and not self._stop.is_set() and self._advance_next():
|
||||
continue
|
||||
|
||||
time.sleep(config.WATCH_INTERVAL)
|
||||
|
||||
@@ -181,6 +188,27 @@ class CaptureController:
|
||||
database.upsert_lead(lead)
|
||||
return lead
|
||||
|
||||
def _advance_next(self) -> bool:
|
||||
"""Look for a 'Next' control on screen; if found, click it and scroll to
|
||||
top so the loop captures the next page. Returns True if it advanced."""
|
||||
if self._advances >= config.MAX_AUTO_NEXT:
|
||||
self.last_event = f"auto-next cap ({config.MAX_AUTO_NEXT}) reached"
|
||||
return False
|
||||
try:
|
||||
shot = screenshot.capture(prefix="next")
|
||||
info = extractor.find_next_button(shot)
|
||||
if not info.get("found"):
|
||||
return False
|
||||
self.last_event = f"clicking '{info.get('label') or 'Next'}' → next page"
|
||||
scroller.click_at_fraction(float(info.get("x", 0)), float(info.get("y", 0)))
|
||||
time.sleep(config.NEXT_LOAD_PAUSE)
|
||||
scroller.scroll_to_top()
|
||||
self._advances += 1
|
||||
return True
|
||||
except Exception as e:
|
||||
self.last_event = f"next-button step skipped: {e}"
|
||||
return False
|
||||
|
||||
|
||||
# module-level singleton shared by the API
|
||||
controller = CaptureController()
|
||||
|
||||
Reference in New Issue
Block a user