Skip to content

Refactor BedfordshireCouncil data parsing logic - #2186

Closed
ChadH360 wants to merge 2 commits into
robbrad:masterfrom
ChadH360:master
Closed

Refactor BedfordshireCouncil data parsing logic#2186
ChadH360 wants to merge 2 commits into
robbrad:masterfrom
ChadH360:master

Conversation

@ChadH360

@ChadH360 ChadH360 commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Bedfordshire website redesign required a new scraper. The current website (as of 22nd July) seems to be a bit of a mess with how the data is reported and has some duplicates. This scraper takes that into account, but may just be a temporary fix! I've maintained original names prior to this update

Fixes #2185

Summary by CodeRabbit

  • Bug Fixes
    • Updated Bedfordshire bin collection retrieval to match the council’s current service layout.
    • Improved extraction and formatting of collection dates and bin types, including multiple collection types in a single entry.
    • Prevented duplicate bin collection items from appearing.
    • Added stronger handling for unsuccessful service responses and missing/invalid collection details.

Bedfordshire website redesign required a new scraper.
The current website (as of 22nd July) seems to be a bit of a mess with how the data is reported and has some duplicates.
This scraper takes that into account, but may just be a temporary fix!
I've maintained original names prior to this update
@coderabbitai

coderabbitai Bot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Bedfordshire collection parsing now retrieves data from a council view URL using the UPRN, handles the updated HTML structure, maps collection types by keywords, and removes duplicate date/type entries.

Changes

Bedfordshire parser

Layer / File(s) Summary
Updated collection retrieval and parsing
uk_bin_collection/.../BedfordshireCouncil.py
parse_data replaces the form POST and legacy HTML traversal with a GET request, status validation, updated CSS selectors, date conversion, keyword-based bin mapping, and deduplication.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant ParseData
  participant CouncilView
  participant CollectionEntries
  ParseData->>CouncilView: GET view URL with uprn
  CouncilView-->>ParseData: Return collection HTML
  ParseData->>CollectionEntries: Map dates and bin types
  ParseData->>CollectionEntries: Append deduplicated entries
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is concise and accurately describes the main change to BedfordshireCouncil parsing logic.
Linked Issues check ✅ Passed The new parser addresses the Central Bedfordshire website change and fixes the missing collections element failure.
Out of Scope Changes check ✅ Passed The changes stay focused on adapting BedfordshireCouncil parsing to the council website redesign and duplicate handling.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@codecov

codecov Bot commented Jul 22, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 86.89%. Comparing base (36d9205) to head (af2a504).

Additional details and impacted files
@@           Coverage Diff           @@
##           master    #2186   +/-   ##
=======================================
  Coverage   86.89%   86.89%           
=======================================
  Files           9        9           
  Lines        1160     1160           
=======================================
  Hits         1008     1008           
  Misses        152      152           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 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.

Inline comments:
In `@uk_bin_collection/uk_bin_collection/councils/BedfordshireCouncil.py`:
- Around line 14-18: Update BedfordshireCouncil.parse_data to remove the
unconditional check_postcode(user_postcode) call, since the fetch flow only
requires uprn; retain check_uprn(user_uprn) and leave postcode retrieval
unchanged unless it is explicitly needed elsewhere.
- Around line 20-26: Update the council request in the relevant data-fetch
method to use a finite timeout and enable SSL certificate verification by
removing verify=False. Remove requests.packages.urllib3.disable_warnings(), and
if warning suppression is still required, use the direct
urllib3.disable_warnings(...) approach established by
AbstractGetBinDataClass.get_data. Preserve the hardcoded host and existing
non-200 error handling.
- Around line 32-58: Update the parsing loop around the date_element and
type_element checks to raise an explicit error when the expected <time datetime>
element or waste-collection type span is missing or malformed, instead of
continuing. After normalizing raw_type, validate that it contains at least one
recognized bin label; raise explicitly for unrecognized labels before appending
extracted_bins, while preserving the existing mappings for valid labels.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: ec0a659a-feef-46e6-a16d-7950cf5c0206

📥 Commits

Reviewing files that changed from the base of the PR and between 36d9205 and 8bb4a68.

📒 Files selected for processing (1)
  • uk_bin_collection/uk_bin_collection/councils/BedfordshireCouncil.py

Comment thread uk_bin_collection/uk_bin_collection/councils/BedfordshireCouncil.py Outdated
Comment thread uk_bin_collection/uk_bin_collection/councils/BedfordshireCouncil.py
Comment thread uk_bin_collection/uk_bin_collection/councils/BedfordshireCouncil.py
Fix parsing for Central Bedfordshire website update.
Fixes robbrad#2185

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
uk_bin_collection/uk_bin_collection/councils/BedfordshireCouncil.py (1)

32-32: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Do not silently accept missing collection rows.

When Line 32 finds no matching elements, the method returns an apparently valid empty schedule. Detect an explicit “no collections” response; otherwise raise a clear parsing error so selector changes are noticed.

🤖 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 `@uk_bin_collection/uk_bin_collection/councils/BedfordshireCouncil.py` at line
32, Update the method containing the collection_days lookup to distinguish an
explicit “no collections” response from an unexpected empty result. If the page
clearly indicates no collections, preserve the empty schedule behavior;
otherwise raise a clear parsing error when soup.find_all returns no matching
waste-collection__day elements.

Source: Learnings

🧹 Nitpick comments (1)
uk_bin_collection/uk_bin_collection/councils/BedfordshireCouncil.py (1)

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

Replace the wildcard import with explicit names.

Line 5 triggers Ruff F403 and hides this module’s dependencies. Import check_uprn and date_format explicitly.

Proposed diff
-from uk_bin_collection.uk_bin_collection.common import *
+from uk_bin_collection.uk_bin_collection.common import check_uprn, date_format
🤖 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 `@uk_bin_collection/uk_bin_collection/councils/BedfordshireCouncil.py` at line
5, Replace the wildcard import in BedfordshireCouncil with an explicit import of
check_uprn and date_format from the common module, preserving the module’s
existing behavior while resolving the hidden-dependency warning.

Source: Linters/SAST tools

🤖 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.

Inline comments:
In `@uk_bin_collection/uk_bin_collection/councils/BedfordshireCouncil.py`:
- Around line 15-23: The parse_data method currently performs redundant network
I/O and ignores its page argument. Move the UPRN-based request into the class’s
retrieval hook used by AbstractGetBinDataClass.get_and_parse_data, ensuring
skip_get_url remains respected, and update parse_data to parse the
already-fetched page response without issuing another request.

---

Outside diff comments:
In `@uk_bin_collection/uk_bin_collection/councils/BedfordshireCouncil.py`:
- Line 32: Update the method containing the collection_days lookup to
distinguish an explicit “no collections” response from an unexpected empty
result. If the page clearly indicates no collections, preserve the empty
schedule behavior; otherwise raise a clear parsing error when soup.find_all
returns no matching waste-collection__day elements.

---

Nitpick comments:
In `@uk_bin_collection/uk_bin_collection/councils/BedfordshireCouncil.py`:
- Line 5: Replace the wildcard import in BedfordshireCouncil with an explicit
import of check_uprn and date_format from the common module, preserving the
module’s existing behavior while resolving the hidden-dependency warning.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: ee858e68-4d61-4b8b-a1be-15e3411e62f0

📥 Commits

Reviewing files that changed from the base of the PR and between 8bb4a68 and af2a504.

📒 Files selected for processing (1)
  • uk_bin_collection/uk_bin_collection/councils/BedfordshireCouncil.py

Comment on lines 15 to +23
def parse_data(self, page: str, **kwargs) -> dict:
user_uprn = kwargs.get("uprn")
user_postcode = kwargs.get("postcode")


check_uprn(user_uprn)
check_postcode(user_postcode)

# Start a new session to walk through the form
requests.packages.urllib3.disable_warnings()
s = requests.Session()

headers = {
"Origin": "https://www.centralbedfordshire.gov.uk",
"Referer": "https://www.centralbedfordshire.gov.uk/info/163/bins_and_waste_collections_-_check_bin_collection_day",
api_url = f"https://www.centralbedfordshire.gov.uk/waste-and-recycling/waste-collection-schedule/view/{user_uprn}"

urllib3.disable_warnings(category=urllib3.exceptions.InsecureRequestWarning)
response = requests.get(api_url, timeout=30)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

Keep network I/O out of parse_data.

AbstractGetBinDataClass.get_and_parse_data already fetches address_url and passes the result as page. This implementation ignores page, performs a second request, and defeats skip_get_url. Move the UPRN URL fetch into the retrieval hook, then parse the fetched response once.

🧰 Tools
🪛 ast-grep (0.44.1)

[warning] 22-22: Request-controlled URL passed to requests; validate against an allowlist to prevent SSRF.
Context: requests.get(api_url, timeout=30)
Note: [CWE-918] Server-Side Request Forgery (SSRF).

(ssrf-requests)

🤖 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 `@uk_bin_collection/uk_bin_collection/councils/BedfordshireCouncil.py` around
lines 15 - 23, The parse_data method currently performs redundant network I/O
and ignores its page argument. Move the UPRN-based request into the class’s
retrieval hook used by AbstractGetBinDataClass.get_and_parse_data, ensuring
skip_get_url remains respected, and update parse_data to parse the
already-fetched page response without issuing another request.

robbrad commented Jul 25, 2026

Copy link
Copy Markdown
Owner

Thanks for the rewrite — the council's site redesign definitely needed this. Folded into the consolidated "July Part 2" release in #2189, credited to you there. I rewrote the commit history slightly (squashed to one conventional-commit message) since the original commit message was failing the "Lint Commit Messages" check, but the parser logic is yours unchanged (plus a black formatting pass). Closing this one out.


Generated by Claude Code

@robbrad robbrad closed this Jul 25, 2026
pull Bot pushed a commit to mrw298/UKBinCollectionData that referenced this pull request Jul 25, 2026
Central Bedfordshire's site changed to a new waste-collection-schedule
page layout with duplicated entries. Re-derive bins from the new
li.waste-collection__day markup, mapping raw type strings back to the
original bin names, and de-duplicate repeated entries.

Fixes robbrad#2185. Adapted from PR robbrad#2186 by ChadH360.
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.

Central Bedfordshire Issues

2 participants