Skip to content

Releases

0.3.5

Choose a tag to compare

@Lucifer-02 Lucifer-02 released this 23 Sep 14:07

[0.3.5] - 2026-09-23

Changed

  • Loại Bỏ 100% Magic Numbers Trong src/map_miner/scraper.py:
    • Chuyển toàn bộ các số điều khiển vận hành (timeouts, delays, intervals, viewports, thresholds) thành default parameter values trong signature hàm.
    • Loại bỏ hoàn toàn số inline trần trong thân các hàm: _create_browser_context, _pass_consent, _find_feed_selector, _scroll_feed, _get_place_urls, _scrape_query_spa, _process_link, và scrape_google_maps.
    • Bổ sung bộ unit test và kiểm tra AST tự động đảm bảo không còn magic numbers trần và các tham số mới có thể override linh hoạt.

Fixed

  • Triệt Tiêu Hoàn Toàn TimeoutNegativeWarning & Chuẩn Hóa An Toàn Timeouts:
    • Bọc an toàn remaining_time = max(0.0, query_timeout - elapsed) tại tất cả các điểm kiểm tra timeout trong _get_place_urls và _scrape_query_spa, ngăn chặn hoàn toàn giá trị âm khi thời gian chạy vượt quá deadline.
    • Chuẩn hóa công thức tính cur_timeout_ms trong SPA mode: bảo đảm luôn đạt giá trị nguyên dương $\ge 1$ (max(1, min(preview_timeout_ms, max(1000, int(max(0.0, remaining_time - 0.5) * 1000))))), loại bỏ rủi ro truyền số âm hoặc 0 vào search_page.expect_response.
    • Chuẩn hóa toàn bộ tham số timeout truyền vào Playwright APIs (wait_for_selector, goto, get_attribute, scroll_into_view_if_needed, expect_response, click), đảm bảo luôn là số nguyên dương $\ge 1$ qua max(1, int(timeout)).
    • Chuẩn hóa safe_timeout = max(1.0, float(timeout)) trong _handle_captcha_if_present để bảo vệ coroutine giải reCAPTCHA luôn có thời gian chờ hợp lệ $\ge 1.0$ giây.
    • Tự động cấu hình NODE_OPTIONS="--no-warnings" trước khi khởi tạo async_playwright trong scrape_google_maps, triệt tiêu triệt để các cảnh báo nội bộ từ Node.js Playwright driver.

0.3.3

Choose a tag to compare

@Lucifer-02 Lucifer-02 released this 20 Sep 07:22

[0.3.3] - 2026-09-20

Added

  • Cơ Chế Cứu Vãn Dữ Liệu Hai Tầng (Two-tier Zero Data Loss Rescue):
    • Bổ sung tham số results_collector: list[dict[str, Any]] | None trong scrape_query_spa và links_collector: set[str] | None trong get_place_urls.
    • Khởi tạo collector và truyền vào hàm cào trong run_spa_query và run_get_urls. Khi chạm Hard Watchdog Timeout (310s) hoặc gặp exception, scraper trả về toàn bộ dữ liệu đã tích lũy trong collector thay vì trả về rỗng ([] / set()), cứu vãn 100% số địa điểm đã cào được (trung bình 19.6 địa điểm/lần timeout).
  • Dừng Sớm Khi Liên Tiếp Ra Ngoài Bán Kính (MAX_CONSECUTIVE_OUT_OF_RANGE_SCROLLS = 3):
    • Thêm hằng số MAX_CONSECUTIVE_OUT_OF_RANGE_SCROLLS = 3. Nếu 3 lượt cuộn liên tiếp toàn bộ địa điểm mới đều vượt quá range_limit, scraper kích hoạt dừng cuộn sớm ngay lập tức, tiết kiệm tài nguyên khi cào các query mật độ thấp (như courthouse).
  • Hậu Kiểm Bán Kính Sau Bóc Tách (Post-Extraction Radius Filtering):
    • Đối với các thẻ địa điểm không chứa tọa độ trên URL, sau khi bóc tách place_data từ preview blob, hệ thống kiểm tra khoảng cách từ latitude/longitude trích xuất được. Nếu vượt quá range_limit, địa điểm bị loại bỏ (early drop) và không ghi nhận vào kết quả.
  • Bộ Tiện Ích Giải Phóng An Toàn (Graceful Shutdown & Safe Closure):
    • Bổ sung các hàm safe_close_page, safe_close_context, và safe_close_browser hóa giải triệt để bẫy asyncio.shield() khi task bị huỷ (cancellation).
    • Quản lý vòng đời task trong global_route_handler qua _active_route_tasks, unroute sạch sẽ trước khi đóng context, triệt tiêu hoàn toàn 479 lỗi Task was destroyed but it is pending!.
  • Tái Cấu Trúc Constants thành Dataclass ScraperConfig:
    • Định nghĩa dataclass ScraperConfig tập trung hóa toàn bộ các thông số timeouts, guardrails, bộ nhớ đệm, retries và concurrency delays.
    • Tích hợp tham số config: ScraperConfig | None = None vào scrape_google_maps, scrape_query_spa, get_place_urls với cơ chế phân giải độ ưu tiên (precedence) linh hoạt.
    • Duy trì 100% tương thích ngược với các hằng số DEFAULT_* và MAX_* module-level từ DEFAULT_CONFIG = ScraperConfig().
    • Export ScraperConfig và DEFAULT_CONFIG tại map_miner và map_miner.scraper.
  • Bóc Tách Xử Lý Dữ Liệu Thuần Túy Ra Khỏi I/O (src/map_miner/extractor.py):
    • Chuyển toàn bộ các logic xử lý dữ liệu thuần túy (pure data processing) từ scraper.py sang extractor.py: DEFAULT_FLATTEN_COLUMNS, REQUIRED_COLUMNS, make_place_url, extract_coordinates_from_url, is_preview_response_for_link, _get_flatten_column_type, format_places_dataframe.
    • Bổ sung 2 hàm tiện ích tính khoảng cách và kiểm tra phạm vi: calculate_distance và is_within_range hỗ trợ cả Point lẫn tuple[float, float].
    • Re-export toàn bộ hằng số và hàm tại src/map_miner/scraper.py và src/map_miner/__init__.py, bảo đảm 100% tương thích ngược (Backward Compatibility).
    • Thay thế toàn bộ các phép tính geodesic(...).meters trong scraper.py bằng calculate_distance(...).

Changed

  • Tối Ưu Hóa Dừng Cuộn Trống:
    • Giảm MAX_CONSECUTIVE_EMPTY_SCROLLS từ 6 xuống 4 lượt cuộn.
  • Kiểm Tra Deadline Chủ Động & Dynamic Preview Timeout:
    • Trong scrape_query_spa, tính toán remaining_time và kiểm tra deadline (remaining_time <= 2.0s) ngay trong vòng lặp duyệt thẻ địa điểm và trước khi cuộn feed.
    • Tự động điều chỉnh động thời gian chờ preview XHR cur_timeout_ms không vượt quá thời gian còn lại của query.

0.3.2

Choose a tag to compare

@Lucifer-02 Lucifer-02 released this 20 Sep 04:30

[0.3.2] - 2026-09-19

Fixed

  • Vòng Lặp Cuộn Vô Hạn Khi Cạn POI Hợp Lệ (Runaway Scrolling):
    • Sửa lỗi logic đếm consecutive_empty_scrolls trong scrape_query_spa: bộ đếm giờ đây dựa trên not found_new_in_batch thay vì bị ràng buộc bởi has_unprocessed.
    • Scraper chủ động ngắt cuộn feed sau MAX_CONSECUTIVE_EMPTY_SCROLLS (6 lần) liên tiếp không có thêm POI hợp lệ trong bán kính, chấm dứt hoàn toàn tình trạng bị treo 300 giây (5 phút) ở các query phổ biến (cafe, restaurant, store, v.v.) tại khu vực thưa dân.
  • Playwright Strict Mode Violation Trong scroll_feed:
    • Thêm .first vào page.locator(feed_selector).first.hover() trong scroll_feed trước khi gọi wheel scroll, triệt tiêu 103 lỗi strict mode khi selector fallback 'div[role="main"] div[tabindex="-1"]' khớp nhiều phần tử DOM.
  • Lỗi Driver & Pending Tasks Khi Ngắt Bằng Ctrl+C / CancelledError:
    • Bọc an toàn await asyncio.shield(resource.close()) với except BaseException tại tất cả các điểm giải phóng tài nguyên (context.close(), browser.close(), page.close()).
    • Quản lý hủy tác vụ con đồng bộ trong scrape_google_maps, loại bỏ hoàn toàn các lỗi runtime Browser.close: Connection closed while reading from the driver và Task was destroyed but it is pending!.
  • Lỗi Báo Log ERROR Sai Lệch Khi Trang 0 Kết Quả:
    • Bổ sung hàm is_no_results_page kiểm tra các dấu hiệu trang rỗng ("Google Maps can't find", "No results found", "Không tìm thấy kết quả", div.Q27duf).
    • Ghi log INFO thông báo không tìm thấy kết quả và trả về danh sách rỗng thay vì bắn logger.error("Could not find results feed selector on search page.").

Changed

  • Tối Ưu Hóa SPA Preview Timeout:
    • Giảm DEFAULT_SPA_PREVIEW_TIMEOUT từ 15,000ms (15s) xuống 10,000ms (10s), tiết kiệm thời gian chờ lãng phí khi gặp thẻ không kích hoạt được request preview XHR trong khi vẫn đảm bảo độ trễ an toàn cho các proxy mạng chậm.
  • Hạ Mức Độ Log Early Drop:
    • Chuyển toàn bộ các vị trí ghi log Early drop: Place ... is ...m away từ INFO xuống DEBUG, triệt tiêu tình trạng ngập lụt log (hơn 117,000 dòng log gây phình file 41.7MB trong log cũ).
  • Cập Nhật Tài Liệu & Docstring Thuật Toán Xếp Hạng Google Maps:
    • Bổ sung tài liệu chính thức từ Google Business Profile Help #7091 vào docstring của range_limit tại scrape_google_maps, scrape_query_spa, get_place_urls và tài liệu kiến trúc CONTEXT.md.
    • Làm rõ 3 yếu tố xếp hạng: Relevance, Distance, Prominence và rationale của việc áp dụng cơ chế Early Drop từng phần tử kết hợp bộ đếm cuộn rỗng an toàn.
  • Tinh Gọn Bộ Kiểm Thử (tests/test_scraper.py):
    • Cắt giảm 508 dòng code boilerplate (-18.6%), từ 2,731 dòng xuống 2,222 dòng.
    • Chuẩn hóa các mock helpers dùng chung (MockPlaywrightContext, make_fake_browser, make_mock_page, make_mock_context).
    • Tham số hóa 7 nhóm test trùng lặp qua @pytest.mark.parametrize, duy trì 100% độ bao phủ kiểm thử (119/119 tests pass).

Added

  • Export hàm is_no_results_page tại tầng gốc package.
  • Các hằng số NO_RESULTS_SELECTORS và NO_RESULTS_TEXT_PATTERNS.

0.3.1

Choose a tag to compare

@Lucifer-02 Lucifer-02 released this 14 Sep 14:28

[0.3.1] - 2026-09-14

Added

  • Tối Ưu Hóa Băng Thông Proxy & Cache Ứng Dụng (Application-Level Route Cache & Bypass Expansion):
    • Application-Level Route Cache: Triển khai bộ nhớ đệm tầng ứng dụng DEFAULT_STATIC_CACHE_DIR (.cache/static_assets) trong global_route_handler cho các static scripts và stylesheets (/maps/_/js/, /maps/_/ss/, /maps/res/, và gstatic.com static assets). Phục vụ phản hồi tức thì với header x-cache: HIT-ROUTE-CACHE khi cache hit, loại bỏ hoàn toàn request tải lại qua proxy.
    • Mở Rộng Proxy Bypass: Mở rộng DEFAULT_PROXY_BYPASS bổ sung các Google static CDN domains (fonts.gstatic.com, apis.google.com, ssl.gstatic.com), định tuyến trực tiếp static assets không tiêu tốn lưu lượng proxy dân cư.
    • Mở Rộng Bộ Lọc URL Rác: Bổ sung "feedback-pa.clients6.google.com", "ogads-pa.clients6.google.com", "/maps/preview/entity" vào BLOCKED_URL_PATTERNS, triệt tiêu hoàn toàn các request telemetry, quảng cáo và entity dư thừa.
  • Upper Bound Guardrails:
    • Thiết lập hằng số DEFAULT_RANGE_LIMIT = 10000.0 (10 km ceiling radius) làm giới hạn bán kính tìm kiếm mặc định, bảo vệ hệ thống không cào lan man ra ngoài phạm vi địa lý dự kiến.
    • Đồng bộ hằng số DEFAULT_QUERY_TIMEOUT = 300.0 (5 phút) áp dụng trực tiếp xuyên suốt scrape_google_maps, scrape_query_spa, và get_place_urls.

Changed

  • Chuẩn Hóa Tham Số & Hạn Chế Kiểu None:
    • Bắt buộc tham số geo_coordinates: Point trong create_browser_context nhằm thiết lập geolocation nhất quán, loại bỏ kiểu Point | None = None.
    • Chuyển đổi các tham số sang giá trị mặc định cụ thể (Upper Bound defaults) thay vì None:
      • range_limit: float = DEFAULT_RANGE_LIMIT (thay vì float | None = None).
      • query_timeout: float = DEFAULT_QUERY_TIMEOUT (thay vì float | None = None).
      • stagger_delay: tuple[float, float] | float = (1.5, 3.5) và cache_dir: Path | str | None = DEFAULT_CACHE_DIR.
      • Trong proxy.py: password: str = "" (thay vì str | None = None) cho renew_tor_circuit_control và async_renew_tor_circuit_control; bypass: str = DEFAULT_PROXY_BYPASS (thay vì str | None) cho get_tor_rotating_proxy.
    • Đơn giản hóa các khối kiểm tra điều kiện, loại bỏ việc rà soát if range_limit is not None: hay if bypass is not None:.
  • Hoàn Thiện Bộ Kiểm Thử:
    • Khôi phục bộ kiểm thử dynamic versioning tests/test_version.py (3 unit tests).
    • Bổ sung 6 unit tests chuyên biệt cho proxy bypass mở rộng và application-level route cache.
    • Tối ưu hóa mock trong test_staggered_query_dispatch_spa để loại bỏ hoàn toàn RuntimeWarning: coroutine was never awaited.
    • Toàn bộ test suite đạt 100% tests pass (106 tests).
  • Đóng Gói Phân Phối (Distribution Packaging):
    • Đồng bộ phiên bản 0.3.1 làm Single Source of Truth tại src/map_miner/__init__.py.
    • Hoàn tất đóng gói package phân phối chuẩn qua Hatchling: Wheel (dist/map_miner-0.3.1-py3-none-any.whl) và Sdist (dist/map_miner-0.3.1.tar.gz).

0.3.0

Choose a tag to compare

@Lucifer-02 Lucifer-02 released this 13 Sep 17:17

[0.3.0] - 2026-09-14

Added

  • Anti-Bot & Stealth Fingerprinting:

    • Chrome 131 User-Agent with a complete set of Client Hints (sec-ch-ua, sec-ch-ua-platform, sec-ch-ua-mobile).
    • Emulated WebGL vendor/renderer (NVIDIA GeForce RTX 3060), eliminating headless SwiftShader/llvmpipe fingerprints.
    • Emulated real-browser environment properties: plugins (Chrome PDF Viewer), languages (en-US,en), hardwareConcurrency=8, and deviceMemory=8.
  • Staggered Query Dispatch:

    • Added the stagger_delay parameter to scrape_google_maps() to introduce a randomized initial delay between queries, reducing congestion and bot detection when multiple tabs send requests simultaneously from the same IP.
  • Tor Circuit Renewal Synchronization:

    • Added a dedicated proxy.py module with cooldown and lock mechanisms (DEFAULT_TOR_RENEW_COOLDOWN = 15.0s, _tor_renew_lock) to prevent SIGNAL NEWNYM conflicts between concurrent threads.
  • Offline Speech-to-Text (STT) Support:

    • Integrated vosk as an offline fallback when Google STT encounters network issues or rate limits.
    • Added a dual-stage audio fallback: 300Hz–3400Hz band-pass filtering followed by automatic fallback to standard mono 16kHz WAV.
  • Configurable SPA Preview Timeout:

    • Added the preview_timeout parameter and DEFAULT_SPA_PREVIEW_TIMEOUT = 15000 (15 seconds), eliminating Timeout 5000ms exceeded while waiting for event "response" errors when using high-latency proxies.

Changed

  • Increased CAPTCHA Solving Timeout: Increased the reCAPTCHA solving timeout from 35.0s to 85.0s (DEFAULT_CAPTCHA_TIMEOUT = 85.0s) to better handle multi-round audio challenges.
  • Code Quality & Linting Standards: Enforced strict quality checks with zero technical debt: uv run ruff check ., uv run ruff format ., ty check, and 90/90 unit tests passing.

Fixed

  • Fixed missing locations in the SPA feed caused by the overly short 5000ms timeout.
  • Fixed cross-tab connection interruptions when one tab triggers a Tor circuit renewal.
  • Fixed Polars schema inference issues by using infer_schema_length=None.

0.2.1

Choose a tag to compare

@Lucifer-02 Lucifer-02 released this 12 Sep 05:10

Release Notes

✨ New Features

  • Real Proxy Rotation & Context Isolation: Added ProxyRotator and create_browser_context (src/map_miner/scraper.py) for per-task network isolation and zero context leaks.
  • Persistent Disk Cache: Added --disk-cache-dir with a 1 GB cap, reducing wire data transfer by ~94.5%.
  • Proxy Bypass: Added DEFAULT_PROXY_BYPASS for static assets to cut proxy bandwidth usage by ~40%.
  • Extended Telemetry Blocking: Aborted client_204, cspreport, and /maps/photometa beacon requests.
  • Test Suite: Expanded test coverage from 27 to 41 unit tests.

🔄 Changes

  • Assigned proxies at BrowserContext level instead of process level.
  • Updated proxy type annotations and added .cache/ to .gitignore.

🐛 Bug Fixes

  • Resolved HTTP/2 multiplexing issues that prevented rotating proxy gateways from rotating IPs.
  • Fixed cross-query cookie and cache fingerprinting across concurrent searches.

0.1.1

Choose a tag to compare

@Lucifer-02 Lucifer-02 released this 12 Sep 05:05

Stabilizations.