Facility: 085428
Tietan Storage Walla Walla
- Facility ID
- 085428
- Name
- Tietan Storage Walla Walla
- URL
- https://www.tietanstoragewallawalla.com/#Units
- Address
- N/A
- Platform
- custom_facility_085428
- Parser File
- src/parsers/custom/facility_085428_parser.py
- Last Scraped
- 2026-03-23 03:22:02.615820
- Created
- 2026-03-06 23:45:35.865957
- Updated
- 2026-03-23 03:22:02.623973
- Parser Status
- ✓ Working
- Status Reason
- N/A
- Last Healing Attempt
- Not attempted
Parser Source (src/parsers/custom/facility_085428_parser.py)
"""Parser for Tietan Storage Depot (Walla Walla, WA) facility.
This is a Webflow site that lists unit sizes and prices as card headings
in the format "5' x 10' = $65" inside `.various-section-card` elements.
"""
from __future__ import annotations
import re
from bs4 import BeautifulSoup
from src.parsers.base import BaseParser, ParseResult, UnitResult
class Facility085428Parser(BaseParser):
"""Extract storage units from Tietan Storage Depot.
Units are displayed as cards with headings in the format:
5' x 10' = $65
10' x 10' = $85
8' x 20' = $105
10' x 22' = $125
"""
platform = "custom_facility_085428"
# Matches "5' x 10' = $65" or "10' x 22' = $125"
_UNIT_RE = re.compile(
r"(\d+(?:\.\d+)?)['\u2019\u2032]?\s*[xX\u00d7]\s*(\d+(?:\.\d+)?)['\u2019\u2032]?"
r"\s*=\s*\$"
r"([\d,]+(?:\.\d+)?)",
re.IGNORECASE,
)
def parse(self, html: str, url: str = "") -> ParseResult:
soup = BeautifulSoup(html, "lxml")
result = ParseResult(platform=self.platform, parser_name=self.__class__.__name__)
# Find all unit cards
cards = soup.find_all(class_="various-section-card")
if not cards:
result.warnings.append("No .various-section-card elements found on page")
return result
for card in cards:
# The heading contains the size and price, e.g. "5' x 10' = $65"
heading = card.find(class_="various-card-head")
if not heading:
continue
heading_text = heading.get_text(separator=" ", strip=True)
match = self._UNIT_RE.search(heading_text)
if not match:
continue
width = float(match.group(1))
length = float(match.group(2))
price_str = match.group(3).replace(",", "")
price = float(price_str)
# Get the description from the card paragraph
paragraph = card.find(class_="various-card-paragraph")
description = paragraph.get_text(strip=True) if paragraph else heading_text
unit = UnitResult(
size=self.normalize_size(f"{int(width)}x{int(length)}"),
price=price,
description=description,
url=url,
metadata={
"width": width,
"length": length,
"sqft": width * length,
},
)
result.units.append(unit)
if not result.units:
result.warnings.append("Unit cards found but no size/price patterns matched")
return result
Scrape Runs (5)
-
exported Run #15042026-03-23 03:21:58.969472 | 4 units | Facility085428Parser | View Data →
-
exported Run #10112026-03-21 19:15:23.390264 | 4 units | Facility085428Parser | View Data →
-
exported Run #5642026-03-14 16:56:52.934374 | 4 units | Facility085428Parser | View Data →
-
exported Run #1762026-03-14 05:03:56.107921 | 4 units | Facility085428Parser | View Data →
-
exported Run #962026-03-14 01:02:45.970551 | 4 units | Facility085428Parser | View Data →
Run #1011 Details
- Status
- exported
- Parser Used
- Facility085428Parser
- Platform Detected
- unknown
- Units Found
- 4
- Stage Reached
- exported
- Timestamp
- 2026-03-21 19:15:23.390264
Timing
| Stage | Duration |
|---|---|
| Fetch | 3835ms |
| Detect | 13ms |
| Parse | 11ms |
| Export | 8ms |
Snapshot: 085428_20260321T191527Z.html · Show Snapshot · Open in New Tab
Parsed Units (4)
(5.0,10.0,50.0)
$65.00/mo
(10.0,10.0,100.0)
$85.00/mo
(8.0,20.0,160.0)
$105.00/mo
(10.0,22.0,220.0)
$125.00/mo