This commit is contained in:
2026-08-31 20:57:14 +02:00
parent 94fb6a8568
commit a32cc84a90
6 changed files with 159 additions and 26 deletions
+10 -1
View File
@@ -1,5 +1,6 @@
import os
import re
from collections.abc import Callable
from urllib.parse import urlsplit, urlunsplit
from playwright.sync_api import TimeoutError as PlaywrightTimeoutError
@@ -98,8 +99,12 @@ def _open_reviews(page):
pass
def get_rating_distribution(url: str) -> dict:
def get_rating_distribution(
url: str,
progress: Callable[[int, str], None] | None = None,
) -> dict:
"""Pobiera pięć zbiorczych liczników. Treści opinii nie są odczytywane ani zapisywane."""
report = progress or (lambda _percent, _message: None)
try:
with sync_playwright() as playwright:
headless = os.environ.get("CHROMIUM_HEADLESS", "1").lower() not in {"0", "false", "no"}
@@ -131,13 +136,16 @@ def get_rating_distribution(url: str) -> dict:
browser = playwright.chromium.launch(**launch)
context = browser.new_context(locale="pl-PL", viewport={"width": 1100, "height": 800})
try:
report(50, "Otwarto Chromium")
page = context.pages[0] if context.pages else context.new_page()
context.add_init_script(
"Object.defineProperty(navigator, 'webdriver', {get: () => undefined})"
)
page.goto(url, wait_until="domcontentloaded", timeout=30_000)
_accept_cookies(page)
report(75, "Załadowano Google Maps")
_open_reviews(page)
report(90, "Otwarto panel opinii")
page.wait_for_timeout(700)
labels = page.locator("[aria-label]").evaluate_all(
"els => els.map(el => el.getAttribute('aria-label')).filter(Boolean)"
@@ -148,6 +156,7 @@ def get_rating_distribution(url: str) -> dict:
if "ograniczonego widoku" in body_text or "limited view" in body_text:
raise ScrapeError("Google włączyło ograniczony widok i ukryło opinie. Spróbuj później lub z innego łącza.")
raise ScrapeError("Nie udało się odczytać dokładnych pięciu liczników. Sprawdź link do miejsca.")
report(99, "Pojawiły się liczniki")
ratings = {str(stars): counts[stars] for stars in range(5, 0, -1)}
total = sum(ratings.values())
average = round(sum(int(stars) * count for stars, count in ratings.items()) / total, 2) if total else 0