Skip to content

[codex] Harden place extractor fixtures and preview enrichment#48

Merged
michaelmwu merged 1 commit into
mainfrom
michaelmwu/improve-maps-scraping
Jul 5, 2026
Merged

[codex] Harden place extractor fixtures and preview enrichment#48
michaelmwu merged 1 commit into
mainfrom
michaelmwu/improve-maps-scraping

Conversation

@michaelmwu

@michaelmwu michaelmwu commented Jul 5, 2026

Copy link
Copy Markdown
Member

Summary

  • Add browser-backed fixture tests for the Google Maps place JS extractor across overview, reviews, about, limited-view, and search-result panel shapes.
  • Move the large inline _PLACE_JS_EXTRACTOR JavaScript into src/gmaps_scraper/data/place_extractor.js and load it via importlib.resources while preserving the Python symbol.
  • Add conservative preview-payload extraction for rating and review_count, with fixtures for positive and ambiguous payloads.

Why

The JS extractor was mostly protected by source-string assertions, which can pass even when selector behavior drifts. The new fixture harness evaluates the extractor in a real local browser page and asserts the structured snapshot. Preview payloads can also contain rating and review-count signals on limited/thin pages, so the scraper now backfills those fields when DOM data is missing.

Notes

  • DOM values still take precedence over preview values.
  • Preview rating/count extraction rejects ambiguous arrays, price-shaped evidence, explicit year evidence in the same node, non-adjacent values, and conflicting candidates rather than guessing.
  • The Task 4 handoff brief was amended locally in .context/, but .context/ is gitignored workspace memory and is not part of this PR.

Validation

  • ./scripts/lint.sh
  • ./scripts/typecheck.sh
  • ./scripts/test.sh (267 tests)
  • Built a wheel and verified gmaps_scraper/data/place_extractor.js is included.
  • Smoke scraped three cached place URLs from /Users/michaelwu/dev/favorite-places/site/data/cache/places.sqlite with --skip-reviews --skip-about --llm-policy never; all returned quality_flags: [], confidence: 1.0, and populated ratings/review counts.

Summary by CodeRabbit

  • New Features

    • Improved place details extraction for Google Maps pages, including ratings, review counts, addresses, photos, website/phone, categories, and pricing details.
    • Added support for recognizing limited-view and search-result pages more reliably.
    • Preview cards can now surface rating and review count information when available.
  • Bug Fixes

    • Better handling of ambiguous or incomplete preview data.
    • More accurate detection of review-related content, photo sources, and address fallbacks.

@coderabbitai

coderabbitai Bot commented Jul 5, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

This PR extracts the browser-side place DOM extraction logic into a standalone place_extractor.js resource loaded via importlib.resources, adds preview-payload rating/review-count enrichment heuristics in place_scraper.py, and adds corresponding HTML/text fixtures and expanded Playwright-based tests.

Changes

Place Extractor and Enrichment

Layer / File(s) Summary
Panel selection and core field extraction
src/gmaps_scraper/data/place_extractor.js
Scores candidate DOM panel roots by heading/address/rating/tab signals, selects best panel with fallback, and extracts name/address/description/status fields.
Review count, photo, and DOM candidate extraction
src/gmaps_scraper/data/place_extractor.js
Normalizes localized review counts, extracts main photo/background-image URLs, and builds deduplicated DOM candidate nodes with shallow paths.
Pricing, review topics, and reservation link extraction
src/gmaps_scraper/data/place_extractor.js
Parses currency/price ranges, admission/room price sections, structural offer kind/prices, room overlay price, reservation links, and assembles the final returned object.
Python resource loading and preview rating enrichment
src/gmaps_scraper/place_scraper.py
Loads _PLACE_JS_EXTRACTOR from the packaged JS resource and adds _extract_preview_rating_summary heuristics feeding rating/review_count into preview enrichment.
HTML and payload fixtures
tests/fixtures/place_pages/*, tests/fixtures/preview_payloads/*
Adds static HTML fixtures for overview, reviews, about, limited-view, and search-result pages, plus rating-summary and ambiguous preview payload text fixtures.
Extractor and enrichment test suite
tests/test_place_scraper.py
Adds Playwright-driven PlaceJsExtractorFixtureTests, reworks photo/address-selector assertions, and adds rating/review-count enrichment attribution tests.

Estimated code review effort: 4 (Complex) | ~60 minutes

Possibly related PRs

  • 508-dev/gmaps-scraper#25: Both refine the shared _PLACE_JS_EXTRACTOR pipeline and extend rating/review-count enrichment logic originally introduced there.
  • 508-dev/gmaps-scraper#28: Both modify place-page DOM pricing logic, including admission/room price parsing and structural offer kind/prices.
  • 508-dev/gmaps-scraper#37: Both adjust the description-extraction heuristics within the place DOM extraction pipeline.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the PR’s main changes: hardening place extraction fixtures and preview enrichment.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch michaelmwu/improve-maps-scraping

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 29b58efe7d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/gmaps_scraper/place_scraper.py Outdated
@michaelmwu michaelmwu force-pushed the michaelmwu/improve-maps-scraping branch from 29b58ef to 289a1e9 Compare July 5, 2026 18:47

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
tests/test_place_scraper.py (1)

230-234: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consider replacing string-matching JS assertions with the new fixture-execution harness.

These tests assert on literal substrings of _PLACE_JS_EXTRACTOR (e.g. 'const isAddressIcon = (icon) => {', 'const rowValue = (row) => {'). They'll break on harmless variable renames and won't catch a logic regression that keeps the same substrings. Since PlaceJsExtractorFixtureTests now provides real browser execution against fixtures, a fixture-based assertion (e.g. an address-icon-only HTML fixture) would more directly encode the intended behavior.

As per coding guidelines, "Tests should encode intent, not just exercise code paths; a test is weak if it would keep passing after the relevant scraper behavior or business rule is broken."

Also applies to: 849-855

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/test_place_scraper.py` around lines 230 - 234, The current test in
test_place_scraper relies on literal substring checks against
_PLACE_JS_EXTRACTOR, which is brittle and doesn’t validate scraper behavior.
Replace these string-matching assertions in
test_place_js_extractor_avoids_broad_photo_selectors (and the related
row/address substring checks) with a fixture-driven browser execution test using
PlaceJsExtractorFixtureTests so the test encodes the intended behavior instead
of implementation text. Use a focused HTML fixture that exercises the
photo-selector/address-icon behavior and assert the extracted result, not the JS
source contents.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@tests/test_place_scraper.py`:
- Around line 230-234: The current test in test_place_scraper relies on literal
substring checks against _PLACE_JS_EXTRACTOR, which is brittle and doesn’t
validate scraper behavior. Replace these string-matching assertions in
test_place_js_extractor_avoids_broad_photo_selectors (and the related
row/address substring checks) with a fixture-driven browser execution test using
PlaceJsExtractorFixtureTests so the test encodes the intended behavior instead
of implementation text. Use a focused HTML fixture that exercises the
photo-selector/address-icon behavior and assert the extracted result, not the JS
source contents.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: e98604a8-c3d5-4630-ab4d-f0bdd1666229

📥 Commits

Reviewing files that changed from the base of the PR and between 71beb48 and 289a1e9.

📒 Files selected for processing (10)
  • src/gmaps_scraper/data/place_extractor.js
  • src/gmaps_scraper/place_scraper.py
  • tests/fixtures/place_pages/about.html
  • tests/fixtures/place_pages/limited_view.html
  • tests/fixtures/place_pages/overview.html
  • tests/fixtures/place_pages/reviews.html
  • tests/fixtures/place_pages/search_result.html
  • tests/fixtures/preview_payloads/ambiguous_rating_review_count.txt
  • tests/fixtures/preview_payloads/rating_review_count.txt
  • tests/test_place_scraper.py

@michaelmwu michaelmwu merged commit 86bc7c8 into main Jul 5, 2026
8 checks passed
@michaelmwu michaelmwu deleted the michaelmwu/improve-maps-scraping branch July 5, 2026 19:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant