Facility: 000323
Secure It Self Storage in Cheney
- Facility ID
- 000323
- Name
- Secure It Self Storage in Cheney
- URL
- http://www.secure-itstorage.com/
- Address
- 100 W Betz Rd, Cheney, WA 99004, USA, Cheney, Washington 99004
- Platform
- custom_facility_000323
- Parser File
- src/parsers/custom/facility_000323_parser.py
- Last Scraped
- 2026-03-27 13:51:06.807575
- Created
- 2026-03-14 16:21:53.706708
- Updated
- 2026-03-27 13:51:06.836650
- Parser Status
- ✓ Working
- Status Reason
- N/A
- Last Healing Attempt
- Not attempted
Parser Source (src/parsers/custom/facility_000323_parser.py)
"""Parser for Secure It Self Storage in Cheney."""
from __future__ import annotations
import re
from bs4 import BeautifulSoup
from src.parsers.base import BaseParser, ParseResult, UnitResult
class Facility000323Parser(BaseParser):
"""Extract storage units from Secure It Self Storage in Cheney."""
platform = "custom_facility_000323"
_UNIT_RE = re.compile(
r"(\d+\s*[\'\'\u2032]?\s*[xX\u00d7]\s*\d+\s*[\'\'\u2032]?)"
r"[^\$]{0,120}"
r"\$(\d[\d,.]*)",
re.DOTALL,
)
_PRICE_SIZE_RE = re.compile(
r"\$(\d[\d,.]*)"
r".{0,120}"
r"(\d+\s*[\'\'\u2032]?\s*[xX\u00d7]\s*\d+\s*[\'\'\u2032]?)",
re.DOTALL,
)
_SIZE_ONLY_RE = re.compile(
r"(\d+\s*[\'\'\u2032]?\s*[xX\u00d7]\s*\d+\s*[\'\'\u2032]?)"
)
def parse(self, html: str, url: str = "") -> ParseResult:
soup = BeautifulSoup(html, "lxml")
result = ParseResult(platform=self.platform, parser_name=self.__class__.__name__)
for tag in soup.find_all(["script", "style"]):
tag.decompose()
body_text = soup.get_text(separator="\n")
seen: set[tuple[str, str]] = set()
# Try size-then-price pattern
for m in self._UNIT_RE.finditer(body_text):
size_text = m.group(1).strip()
price_text = m.group(2).strip()
key = (size_text, price_text)
if key in seen:
continue
seen.add(key)
unit = UnitResult()
unit.size = size_text
w, ln, sq = self.normalize_size(size_text)
if w is not None:
unit.metadata = {"width": w, "length": ln, "sqft": sq}
unit.price = self.normalize_price(price_text)
unit.description = m.group(0).strip()[:200]
if unit.size or unit.price:
result.units.append(unit)
# Try price-then-size pattern if no results
if not result.units:
for m in self._PRICE_SIZE_RE.finditer(body_text):
price_text = m.group(1).strip()
size_text = m.group(2).strip()
key = (size_text, price_text)
if key in seen:
continue
seen.add(key)
unit = UnitResult()
unit.size = size_text
w, ln, sq = self.normalize_size(size_text)
if w is not None:
unit.metadata = {"width": w, "length": ln, "sqft": sq}
unit.price = self.normalize_price(price_text)
unit.description = m.group(0).strip()[:200]
if unit.size or unit.price:
result.units.append(unit)
# Fallback: extract sizes without prices
if not result.units:
seen_sizes: set[str] = set()
for m in self._SIZE_ONLY_RE.finditer(body_text):
size_text = m.group(1).strip()
if size_text in seen_sizes:
continue
w, ln, sq = self.normalize_size(size_text)
if w is None or w < 3 or ln < 3:
continue
seen_sizes.add(size_text)
unit = UnitResult()
unit.size = size_text
unit.metadata = {"width": w, "length": ln, "sqft": sq}
result.units.append(unit)
if not result.units:
result.warnings.append("No units found via regex")
return result
Scrape Runs (5)
-
exported Run #17992026-03-27 13:51:04.831844 | 13 units | Facility000323Parser | View Data →
-
exported Run #17982026-03-27 13:51:04.753271 | 13 units | Facility000323Parser | View Data →
-
exported Run #11622026-03-23 02:52:43.459044 | 13 units | Facility000323Parser | View Data →
-
exported Run #6692026-03-21 18:43:53.444459 | 13 units | Facility000323Parser | View Data →
-
exported Run #2182026-03-14 16:26:07.380231 | 13 units | Facility000323Parser | View Data →
Run #669 Details
- Status
- exported
- Parser Used
- Facility000323Parser
- Platform Detected
- table_layout
- Units Found
- 13
- Stage Reached
- exported
- Timestamp
- 2026-03-21 18:43:53.444459
Timing
| Stage | Duration |
|---|---|
| Fetch | 2399ms |
| Detect | 24ms |
| Parse | 16ms |
| Export | 9ms |
Snapshot: 000323_20260321T184355Z.html · Show Snapshot · Open in New Tab
Parsed Units (13)
5x5
No price
5x10
No price
10x10
No price
10x15
No price
10x20
No price
10x25
No price
10x30
No price
12x40
No price
12x50
No price
14x50
No price
20x40
No price
34x60
No price
93x60
No price