Facility: 025061
Self Storage WYO - Casper
- Facility ID
- 025061
- Name
- Self Storage WYO - Casper
- URL
- https://www.selfstoragewyo.com/324-n-walsh-dr-casper-wy-82609
- Address
- N/A
- Platform
- custom_facility_025061
- Parser File
- src/parsers/custom/facility_025061_parser.py
- Last Scraped
- 2026-03-23 03:19:25.913987
- Created
- 2026-03-06 23:45:35.865957
- Updated
- 2026-03-23 03:19:25.921604
- Parser Status
- ✓ Working
- Status Reason
- N/A
- Last Healing Attempt
- Not attempted
Parser Source (src/parsers/custom/facility_025061_parser.py)
"""Parser for Walsh Drive Self Storage (Self Storage Wyo) in Casper, WY.
This is a Storable.io / storedge React SPA. The server-rendered HTML only
exposes two MuiCard unit cards, but the page embeds a JSON-LD ``@graph``
block (type ``application/ld+json``) that lists *all* available unit groups
as ``Product`` objects with description (e.g. "10x10") and offer price.
Multiple ``Product`` entries may share the same (size, price) pair when
there are several units of that type. We deduplicate by (size, price) and
emit one ``UnitResult`` per unique pair.
The JSON-LD does not carry amenity information; amenities visible in the
rendered cards (e.g. "Outside") are noted in the parser but cannot be
reliably attributed to every size without live API access.
"""
from __future__ import annotations
import json
import re
from bs4 import BeautifulSoup
from src.parsers.base import BaseParser, ParseResult, UnitResult
class Facility025061Parser(BaseParser):
"""Extract storage units from Walsh Drive Self Storage (selfstoragewyo.com)."""
platform = "custom_facility_025061"
# Matches dimensions like "10x10", "5x10", "12x30" in JSON-LD description field
_SIZE_RE = re.compile(r"^(\d+)\s*[xX]\s*(\d+)$")
def parse(self, html: str, url: str = "") -> ParseResult:
soup = BeautifulSoup(html, "lxml")
result = ParseResult(platform=self.platform, parser_name=self.__class__.__name__)
# Locate all JSON-LD script blocks
ld_scripts = soup.find_all("script", type="application/ld+json")
products: list[dict] = []
for script in ld_scripts:
raw = script.string or ""
if not raw.strip():
continue
try:
data = json.loads(raw)
except json.JSONDecodeError:
continue
# The unit data is in a @graph block containing Product objects
if isinstance(data, dict) and "@graph" in data:
for item in data["@graph"]:
if isinstance(item, dict) and item.get("@type") == "Product":
products.append(item)
if not products:
result.warnings.append("No JSON-LD Product entries found on page")
return result
# Deduplicate by (size_raw, price) — keep first occurrence of each pair
seen: set[tuple[str, float | None]] = set()
for product in products:
desc = (product.get("description") or "").strip()
offer = product.get("offers") or {}
raw_price = offer.get("price")
price: float | None = None
if raw_price is not None:
try:
price = float(raw_price)
except (TypeError, ValueError):
price = self.normalize_price(str(raw_price))
key = (desc, price)
if key in seen:
continue
seen.add(key)
# Normalise size string from "10x10" → "10 x 10"
size_label = desc
metadata: dict = {}
m = self._SIZE_RE.match(desc)
if m:
width = float(m.group(1))
length = float(m.group(2))
size_label = f"{int(width)} x {int(length)}"
metadata = {"width": width, "length": length, "sqft": width * length}
unit = UnitResult(
size=size_label,
price=price,
description=desc,
url=url,
metadata=metadata,
)
if unit.size or unit.price:
result.units.append(unit)
if not result.units:
result.warnings.append("No units found on page")
return result
Scrape Runs (5)
-
exported Run #14812026-03-23 03:19:21.602128 | 11 units | Facility025061Parser | View Data →
-
exported Run #9882026-03-21 19:12:19.007144 | 11 units | Facility025061Parser | View Data →
-
exported Run #5412026-03-14 16:54:41.914582 | 11 units | Facility025061Parser | View Data →
-
exported Run #1432026-03-14 04:58:00.597360 | 11 units | Facility025061Parser | View Data →
-
exported Run #662026-03-14 00:59:52.661535 | 11 units | Facility025061Parser | View Data →
Run #541 Details
- Status
- exported
- Parser Used
- Facility025061Parser
- Platform Detected
- storageunitsoftware
- Units Found
- 11
- Stage Reached
- exported
- Timestamp
- 2026-03-14 16:54:41.914582
Timing
| Stage | Duration |
|---|---|
| Fetch | 3983ms |
| Detect | 24ms |
| Parse | 9ms |
| Export | 14ms |
Snapshot: 025061_20260314T165445Z.html · Show Snapshot · Open in New Tab
Parsed Units (11)
10 x 10
$88.00/mo
10 x 15
$104.00/mo
10 x 20
$104.00/mo
10 x 20
$115.00/mo
5 x 10
$67.00/mo
5 x 10
$72.00/mo
12 x 30
$196.00/mo
10 x 20
$120.00/mo
10 x 30
$176.00/mo
10 x 15
$109.00/mo
10 x 10
$93.00/mo