Facility: 109256
T-Voss Storage
- Facility ID
- 109256
- Name
- T-Voss Storage
- URL
- http://tvoss.com/
- Address
- N/A
- Platform
- custom_facility_109256
- Parser File
- src/parsers/custom/facility_109256_parser.py
- Last Scraped
- 2026-03-23 03:17:14.112810
- Created
- 2026-03-06 23:45:35.865957
- Updated
- 2026-03-23 03:17:14.112810
- Parser Status
- ⚠ Needs Fix
- Status Reason
- Parser returned 0 units
- Last Healing Attempt
- Not attempted
Parser Source (src/parsers/custom/facility_109256_parser.py)
"""Parser for Treasure Valley On-Site Storage (TVOSS).
This is a WordPress/Elementor site offering 8x20 and 8x40 shipping container
rentals. Pricing is embedded as plain text within an Elementor icon list element
on the /monthly-container-rentals/ page and on the homepage.
The pricing text reads:
"Competitive rates starting at $80/month for 8×20 containers and
$130/month for 8×40 containers."
"""
from __future__ import annotations
import re
from bs4 import BeautifulSoup
from src.parsers.base import BaseParser, ParseResult, UnitResult
class Facility109256Parser(BaseParser):
"""Extract container rental units from Treasure Valley On-Site Storage.
Pricing is displayed as a sentence in an Elementor icon-list text element:
"Competitive rates starting at $80/month for 8×20 containers and
$130/month for 8×40 containers."
"""
platform = "custom_facility_109256"
# Matches "$<price>/month for <W>×<L> containers"
_PRICE_UNIT_RE = re.compile(
r"\$(\d[\d,]*(?:\.\d+)?)/month\s+for\s+(\d+)\s*[×xX\u00d7]\s*(\d+)\s+containers?",
re.IGNORECASE,
)
def parse(self, html: str, url: str = "") -> ParseResult:
soup = BeautifulSoup(html, "lxml")
result = ParseResult(platform=self.platform, parser_name=self.__class__.__name__)
# Search for any text element that contains pricing
text = soup.get_text(separator=" ", strip=True)
for match in self._PRICE_UNIT_RE.finditer(text):
price_str = match.group(1).replace(",", "")
price = float(price_str)
width = float(match.group(2))
length = float(match.group(3))
size_label = f"{int(width)}' x {int(length)}'"
unit = UnitResult(
size=size_label,
price=price,
description=f"{int(width)}x{int(length)} shipping container rental",
metadata={
"width": width,
"length": length,
"sqft": width * length,
"container_type": "shipping_container",
},
)
result.units.append(unit)
if not result.units:
result.warnings.append("No container pricing lines matched on page")
return result
Scrape Runs (4)
Run #112 Details
- Status
- exported
- Parser Used
- Facility109256Parser
- Platform Detected
- table_layout
- Units Found
- 0
- Stage Reached
- exported
- Timestamp
- 2026-03-14 01:04:12.664991
Timing
| Stage | Duration |
|---|---|
| Fetch | 4743ms |
| Detect | 36ms |
| Parse | 16ms |
| Export | 11ms |
Snapshot: 109256_20260314T010417Z.html · Show Snapshot · Open in New Tab
No units found in this run.
All Failures for this Facility (4)
parse
_WarningAsException
scraper
no_units_extracted
warning
Run #N/A | 2026-03-23 03:17:14.104624
No units extracted for 109256
Stack trace
src.reporting.failure_reporter._WarningAsException: No units extracted for 109256
parse
_WarningAsException
scraper
no_units_extracted
warning
Run #N/A | 2026-03-21 19:10:01.715778
No units extracted for 109256
Stack trace
src.reporting.failure_reporter._WarningAsException: No units extracted for 109256
parse
_WarningAsException
scraper
no_units_extracted
warning
Run #N/A | 2026-03-14 16:52:56.838563
No units extracted for 109256
Stack trace
src.reporting.failure_reporter._WarningAsException: No units extracted for 109256
parse
_WarningAsException
scraper
no_units_extracted
warning
Run #N/A | 2026-03-14 01:04:17.562996
No units extracted for 109256
Stack trace
src.reporting.failure_reporter._WarningAsException: No units extracted for 109256