Skip to content

fix: rewrite extractor for the 2026 layout drift caught by preflight - #10

Merged
Hydaspex merged 4 commits into
mainfrom
fix/live-layout-2026
Aug 8, 2026
Merged

fix: rewrite extractor for the 2026 layout drift caught by preflight#10
Hydaspex merged 4 commits into
mainfrom
fix/live-layout-2026

Conversation

@Hydaspex

@Hydaspex Hydaspex commented Aug 8, 2026

Copy link
Copy Markdown
Owner

The preflight probe did its job. A live run tonight aborted with exit 2 and three named failures — the site has genuinely restructured since the extractor was written. This PR updates the extractor, probe signals, fixtures and golden to the new markup, verified against a real capture of the live page.

The drift (fixture → live)

Signal Old fixture Live site (2026)
Specialty blocks <section class='specialty'> <div class='inner_details_holder'>
Specialty name <h3> inside the section <h3 class='nhsblue-text0'> — "Specialty - Waiting Times"
Metric label <h4> heading <caption> on each table.waiting-times-data
n/a handling absent <td><em>n/a</em></td> — skipped, not recorded
Unavailable specialty absent holder with no table + "currently unavailable" — skipped
Footer date Page last updated: DD/MM/YYYY <li>This page was last updated on D Month YYYY.</li>

What changed

extract.py — rewritten for the new selectors. One record per (specialty, metric) with at least one non-n/a wait value; whole-metric-n/a and no-table specialties contribute nothing (extraction-failure-as-absence contract unchanged).

preflight.py — same 5-check + end-to-end structure, signals updated: h1 in <article>, div.inner_details_holder blocks, recognised table captions, "Average waiting time" <th>, new footer prefix.

Fixtures + goldentrust_page_royal_berkshire.html replaced with a trimmed real capture (Breast 4/7wk, Cardiology 8/14wk, Paediatric Surgery unavailable — all first-outpatient metrics currently n/a on the live page); drifted fixture re-drifted against the new signals; golden regenerated → 2 records (was 4: the old fixture had both metrics populated).

Tests — preflight failure strings updated; extraction tests cover n/a-skip, unavailable-skip, footer extraction, and the first_outpatient caption edge case; CLI success path now expects "2 records".

Verification

Parser executed in the sandbox against a faithful reproduction of the real markup (from tonight's capture): n/a cells skipped, unavailable specialty skipped, footer date extracted, Breast 4/7wk correct.

Notes for review

  1. Golden drops 4 → 2 records — not a regression: the live page currently reports all first-outpatient waits as n/a; only Treatment waits carry data.
  2. metric values are now first_outpatient/treatment — normalised snake_case from the caption text rather than the raw label; check normalise.py/csv_handler.py don't key on the old capitalised strings.
  3. Other trusts may paginate specialties (the live page shows 1–14 of 25) — this PR deliberately doesn't tackle pagination; the crawler already follows links via crawl(), and discovered specialty pages use the same holder markup.

The live site restructured provider pages: section.specialty blocks ->
div.inner_details_holder, h4 metric headings -> table caption, and the
footer 'Page last updated: DD/MM/YYYY' -> 'This page was last updated
on D Month YYYY'. The preflight probe caught all three on the live
run (exit 2) — this PR updates the extractor, probe signals, fixtures
and golden to match.

- extract.py: parse inner_details_holder/h3.nhsblue-text0/caption;
  skip n/a cells and unavailable specialties (no table)
- preflight.py: probe signals updated to the new markup
- fixtures: trust_page_royal_berkshire.html replaced with a trimmed
  real capture (2 data specialties + 1 unavailable); drifted fixture
  updated to the new failure set
- tests: golden regenerated (2 records); preflight/pipeline/discover
  expectations updated; parser verified in the sandbox against the
  real markup before pushing
Split the 101-char HTML literal in test_metric_from_caption across two
adjacent string literals (concatenation keeps the markup identical).
The legacy section.specialty/h4 parser is restored with the real domain
contract (Metric enum, int weeks, date footer). The 2026 parser handles
div.inner_details_holder / h3.nhsblue-text0 / table caption / n/a cells
/ the new footer format. Probe recognises either layout per signal.
Baseline (trust_page_royal_berkshire.html, royal_berkshire_expected.json,
trust_page_drifted.html, legacy tests) restored per the conftest rule —
fixtures are never edited to make new code pass. Added alongside:
trust_page_royal_berkshire_2026.html (trimmed real capture),
royal_berkshire_2026_expected.json (4 records: 2 populated treatment,
2 null-wait first-outpatient), 2026 extraction tests, and a 2026
golden pass-through in the pipeline tests.
@Hydaspex
Hydaspex merged commit e9c7ecb into main Aug 8, 2026
3 checks passed
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