Facility: 086007
Walla Walla Self Storage - Eastgate
- Facility ID
- 086007
- Name
- Walla Walla Self Storage - Eastgate
- URL
- https://www.wallawallaselfstorage.com/eastgate-self-storage/
- Address
- N/A
- Platform
- custom_facility_086007
- Parser File
- src/parsers/custom/facility_086007_parser.py
- Last Scraped
- 2026-03-23 03:22:18.621772
- Created
- 2026-03-06 23:45:35.865957
- Updated
- 2026-03-23 03:22:18.627723
- Parser Status
- ✓ Working
- Status Reason
- N/A
- Last Healing Attempt
- Not attempted
Parser Source (src/parsers/custom/facility_086007_parser.py)
"""Parser for Eastgate Self Storage (Walla Walla, WA) facility 086007.
The site uses the StorEdge/storedge platform. Unit listings appear in
``<div id="NxM-Storage">`` blocks, each containing a title, a green
sale price, a crossed-out regular price, amenity bullets and an
optional red promotion / scarcity badge.
"""
from __future__ import annotations
import re
from bs4 import BeautifulSoup
from src.parsers.base import BaseParser, ParseResult, UnitResult
# Matches IDs like "5x5-Storage", "10x20-Storage", "12x24-Storage"
_UNIT_ID_RE = re.compile(r"^\d+x\d+-Storage$", re.IGNORECASE)
# Scarcity indicator in the red promo badge
_LAST_UNIT_RE = re.compile(r"last\s+unit", re.IGNORECASE)
class Facility086007Parser(BaseParser):
"""Extract storage units from Eastgate Self Storage (facility 086007).
Each unit group is wrapped in a ``<div id="NxM-Storage">`` block
and contains:
- A bold title div with the size label (e.g. "5x5 Storage")
- A green ``<span>`` with the sale / starting-at price
- A struck-through div (``.sutv2-cross-out``) with the regular price
- A ``<ul>`` with amenity bullets; the first ``<li>`` may be a red
promotion badge that includes scarcity language ("Last Unit …")
"""
platform = "custom_facility_086007"
def parse(self, html: str, url: str = "") -> ParseResult:
soup = BeautifulSoup(html, "lxml")
result = ParseResult(platform=self.platform, parser_name=self.__class__.__name__)
unit_divs = soup.find_all("div", id=_UNIT_ID_RE)
if not unit_divs:
result.warnings.append("No unit blocks found (expected <div id='NxM-Storage'>)")
return result
for block in unit_divs:
# --- size ---
title_div = block.find("div", class_=lambda c: c and "font-bold" in c and "text-xl" in c)
raw_title = title_div.get_text(strip=True) if title_div else block.get("id", "")
width, length, sqft = self.normalize_size(raw_title)
if width is not None and length is not None:
size = f"{int(width)}x{int(length)}"
else:
# Fall back to the block id (e.g. "5x5-Storage" → "5x5")
size = block.get("id", "").replace("-Storage", "").replace("-storage", "")
# --- sale price (green bold span) ---
sale_span = block.find("span", class_=lambda c: c and "text-wcgreen" in c)
sale_price = self.normalize_price(sale_span.get_text(strip=True)) if sale_span else None
# --- regular price (struck-through) ---
crossout_div = block.find("div", class_=lambda c: c and "sutv2-cross-out" in c)
regular_price = self.normalize_price(crossout_div.get_text(strip=True)) if crossout_div else None
# --- amenities & promotion ---
amenities: list[str] = []
promotion: str | None = None
scarcity: str | None = None
for li in block.find_all("li"):
li_text = li.get_text(strip=True)
li_classes = " ".join(li.get("class", []))
if "text-wcred" in li_classes:
# Red badge = promotion / scarcity text
promotion = li_text
if _LAST_UNIT_RE.search(li_text):
scarcity = "Last unit available"
else:
amenities.append(li_text)
# Build description from amenities list
description = "; ".join(amenities) if amenities else None
metadata: dict = {}
if width is not None:
metadata["width"] = width
if length is not None:
metadata["length"] = length
if sqft is not None:
metadata["sqft"] = sqft
if amenities:
metadata["amenities"] = amenities
unit = UnitResult(
size=size,
description=description,
price=regular_price,
sale_price=sale_price,
promotion=promotion,
scarcity=scarcity,
url=url,
metadata=metadata if metadata else None,
)
result.units.append(unit)
return result
Scrape Runs (5)
-
exported Run #15072026-03-23 03:22:11.506727 | 6 units | Facility086007Parser | View Data →
-
exported Run #10142026-03-21 19:15:37.952824 | 6 units | Facility086007Parser | View Data →
-
exported Run #5672026-03-14 16:57:06.127691 | 6 units | Facility086007Parser | View Data →
-
exported Run #1792026-03-14 05:04:08.472839 | 6 units | Facility086007Parser | View Data →
-
exported Run #992026-03-14 01:02:58.038773 | 6 units | Facility086007Parser | View Data →
Run #179 Details
- Status
- exported
- Parser Used
- Facility086007Parser
- Platform Detected
- storageunitsoftware
- Units Found
- 6
- Stage Reached
- exported
- Timestamp
- 2026-03-14 05:04:08.472839
Timing
| Stage | Duration |
|---|---|
| Fetch | 4644ms |
| Detect | 32ms |
| Parse | 16ms |
| Export | 8ms |
Snapshot: 086007_20260314T050413Z.html · Show Snapshot · Open in New Tab
Parsed Units (6)
5x5
$12.00/mo
Street: $24.00
Last unit available
10x10
$25.00/mo
Street: $50.00
10x15
$27.00/mo
Street: $54.00
10x20
$42.00/mo
Street: $84.00
12x24
$69.00/mo
Street: $137.00
5x10
$128.00/mo