From acf30fcc20b746ebd1f058ff332efac49f7191b6 Mon Sep 17 00:00:00 2001 From: qananasikq Date: Fri, 10 Apr 2026 15:10:50 +0300 Subject: [PATCH] add antibot guard and retry --- iaai_scraper/core/exceptions.py | 10 ++++++++++ iaai_scraper/core/retry.py | 3 +++ iaai_scraper/parsing/parser.py | 5 +++-- 3 files changed, 16 insertions(+), 2 deletions(-) create mode 100644 iaai_scraper/core/exceptions.py diff --git a/iaai_scraper/core/exceptions.py b/iaai_scraper/core/exceptions.py new file mode 100644 index 0000000..dd4c3dc --- /dev/null +++ b/iaai_scraper/core/exceptions.py @@ -0,0 +1,10 @@ +class ScraperError(Exception): + """Base scraper exception.""" + + +class AntiBotDetectedError(ScraperError): + """Raised when the target website appears to block automation.""" + + +class SiteStructureChangedError(ScraperError): + """Raised when the page shape changed and required data is missing.""" diff --git a/iaai_scraper/core/retry.py b/iaai_scraper/core/retry.py index 4fd87d6..2fce32c 100644 --- a/iaai_scraper/core/retry.py +++ b/iaai_scraper/core/retry.py @@ -7,6 +7,8 @@ from typing import Any from playwright.sync_api import Error, TimeoutError as PlaywrightTimeoutError +from .exceptions import AntiBotDetectedError + logger = logging.getLogger("iaai_scraper.retry") # Типы исключений, при которых retry имеет смысл. @@ -16,6 +18,7 @@ RETRYABLE_EXCEPTIONS = ( ConnectionError, OSError, TimeoutError, + AntiBotDetectedError, ) diff --git a/iaai_scraper/parsing/parser.py b/iaai_scraper/parsing/parser.py index d9765ba..359c451 100644 --- a/iaai_scraper/parsing/parser.py +++ b/iaai_scraper/parsing/parser.py @@ -236,12 +236,13 @@ class VehicleParser: def _build_access_notes(self, summary: dict[str, Any], responses: list[dict[str, Any]]) -> dict[str, Any]: endpoints = [item.get("url", "") for item in responses] + dom_hints = self._dom_hints(" ".join(str(value) for value in summary.values() if value is not None)) return { "vin_visible": bool(summary.get("vin")), "images_visible": bool(summary.get("image_urls")), "network_json_count": len(responses), - "possible_captcha": False, - "possible_antibot": False, + "possible_captcha": bool(dom_hints.get("has_captcha_text")), + "possible_antibot": bool(dom_hints.get("has_antibot_text")), "observed_endpoints": endpoints[:20], }