Facility: 090747
U-Haul Evansville WY (S.)
- Facility ID
- 090747
- Name
- U-Haul Evansville WY (S.)
- URL
- https://www.uhaul.com/Locations/Self-Storage-near-Evansville-WY-82636/792077/
- Address
- N/A
- Platform
- custom_facility_090747
- Parser File
- src/parsers/custom/facility_090747_parser.py
- Last Scraped
- 2026-03-23 03:21:25.802370
- Created
- 2026-03-06 23:45:35.865957
- Updated
- 2026-03-23 03:21:25.810514
- Parser Status
- ✓ Working
- Status Reason
- N/A
- Last Healing Attempt
- Not attempted
Parser Source (src/parsers/custom/facility_090747_parser.py)
"""Parser for U-Haul Storage of Evansville (facility 090747).
U-Haul uses a Foundation-based layout where each unit type is rendered as a
"callout condensed" div containing dimensions, price, amenity list, and optional
scarcity text (e.g. "2 Units Left!").
"""
from __future__ import annotations
import re
from bs4 import BeautifulSoup
from src.parsers.base import BaseParser, ParseResult, UnitResult
# Matches dimension strings like "5' x 10' x 8'" or "10' x 20'"
_DIM_RE = re.compile(
r"(\d+(?:\.\d+)?)['\u2019\u2032]\s*x\s*(\d+(?:\.\d+)?)['\u2019\u2032]",
re.IGNORECASE,
)
# Matches scarcity text like "2 Units Left!" or "1 Unit Left"
_SCARCITY_RE = re.compile(r"\d+\s+Units?\s+Left", re.IGNORECASE)
class Facility090747Parser(BaseParser):
"""Extract storage units from U-Haul Storage of Evansville.
Unit containers are ``<div class="callout condensed ...">`` elements that
contain a dimension span, a price ``<b class="text-xl">``, an amenity list,
and optional scarcity text.
"""
platform = "custom_facility_090747"
def parse(self, html: str, url: str = "") -> ParseResult:
soup = BeautifulSoup(html, "lxml")
result = ParseResult(platform=self.platform, parser_name=self.__class__.__name__)
# Each rentable unit is wrapped in a "callout condensed" div.
# Filter to only those that contain actual dimension data.
callouts = soup.find_all(
"div",
class_=lambda c: c and "callout" in c and "condensed" in c,
)
for callout in callouts:
text = callout.get_text()
# Skip category header blocks that have no dimensions
if not _DIM_RE.search(text):
continue
unit = UnitResult()
# --- Size ---
dim_span = callout.find("span", class_="nowrap")
if dim_span:
raw_dim = dim_span.get_text(strip=True)
# Use only width x length (first two numbers) for the display size
m = _DIM_RE.search(raw_dim)
if m:
width = float(m.group(1))
length = float(m.group(2))
unit.size = f"{int(width)}' x {int(length)}'"
_, _, sqft = self.normalize_size(f"{int(width)}x{int(length)}")
unit.metadata = {"width": width, "length": length, "sqft": sqft}
# --- Price ---
price_el = callout.find("b", class_="text-xl")
if price_el:
unit.price = self.normalize_price(price_el.get_text(strip=True))
# --- Amenities (description) ---
amenity_ul = callout.find("ul", class_="condensed")
if amenity_ul:
amenities = [li.get_text(strip=True) for li in amenity_ul.find_all("li")]
if amenities:
unit.description = ", ".join(amenities)
# Persist amenity flags in metadata
if unit.metadata is None:
unit.metadata = {}
unit.metadata["amenities"] = amenities
unit.metadata["climate_controlled"] = any(
"climate" in a.lower() for a in amenities
)
unit.metadata["drive_up"] = any(
"drive" in a.lower() for a in amenities
)
# --- Scarcity ---
scarcity_match = _SCARCITY_RE.search(text)
if scarcity_match:
unit.scarcity = scarcity_match.group(0)
if unit.size or unit.price:
result.units.append(unit)
if not result.units:
result.warnings.append("No unit callout elements found on page")
return result
Scrape Runs (5)
-
exported Run #14962026-03-23 03:21:17.219868 | 5 units | Facility090747Parser | View Data →
-
exported Run #10032026-03-21 19:14:34.711502 | 5 units | Facility090747Parser | View Data →
-
exported Run #5562026-03-14 16:56:14.941630 | 6 units | Facility090747Parser | View Data →
-
exported Run #1612026-03-14 05:00:09.002307 | 6 units | Facility090747Parser | View Data →
-
exported Run #842026-03-14 01:01:49.582094 | 6 units | Facility090747Parser | View Data →
Run #556 Details
- Status
- exported
- Parser Used
- Facility090747Parser
- Platform Detected
- storageunitsoftware
- Units Found
- 6
- Stage Reached
- exported
- Timestamp
- 2026-03-14 16:56:14.941630
Timing
| Stage | Duration |
|---|---|
| Fetch | 7077ms |
| Detect | 115ms |
| Parse | 113ms |
| Export | 14ms |
Snapshot: 090747_20260314T165622Z.html · Show Snapshot · Open in New Tab
Parsed Units (6)
5' x 10'
$74.95/mo
2 Units Left
10' x 15'
$139.95/mo
1 Unit Left
10' x 10'
$84.95/mo
10' x 15'
$124.95/mo
10' x 20'
$139.95/mo
15' x 30'
$279.95/mo
1 Unit Left