Facility: 7
A&D Storage
- Facility ID
- 7
- Name
- A&D Storage
- URL
- https://a-dstorage.com/Prices.html
- Address
- N/A
- Platform
- custom_facility_7
- Parser File
- src/parsers/custom/facility_7_parser.py
- Last Scraped
- 2026-03-23 03:16:08.808441
- Created
- 2026-03-14 16:21:53.706708
- Updated
- 2026-03-23 03:16:08.815728
- Parser Status
- ✓ Working
- Status Reason
- N/A
- Last Healing Attempt
- Not attempted
Parser Source (src/parsers/custom/facility_7_parser.py)
"""Parser for A & D Self Storage (Barberton, Ohio)."""
from __future__ import annotations
import re
from bs4 import BeautifulSoup
from src.parsers.base import BaseParser, ParseResult, UnitResult
class Facility7Parser(BaseParser):
"""Extract storage units from A & D Self Storage.
Pricing is embedded in paragraph text with patterns like:
"The 5 x 10 units are $45 per month"
"the 10 x 10 units are $75 per month"
"""
platform = "custom_facility_7"
# Match: "{size} units are ${price}" or "{size} are ${price}"
_UNIT_RE = re.compile(
r"(\d+)\s*x\s*(\d+)\s+(?:units\s+)?are\s+\$([\d,]+(?:\.\d+)?)",
re.IGNORECASE,
)
# Match parking: "$XX per month for a car or RV"
_PARKING_RE = re.compile(
r"\$([\d,]+(?:\.\d+)?)\s+per\s+month\s+for\s+a\s+car\s+or\s+RV",
re.IGNORECASE,
)
def parse(self, html: str, url: str = "") -> ParseResult:
soup = BeautifulSoup(html, "lxml")
result = ParseResult(platform=self.platform, parser_name=self.__class__.__name__)
content = soup.find(id="content")
if not content:
result.warnings.append("No #content section found")
return result
text = content.get_text(separator=" ", strip=True)
seen_sizes: set[tuple[float, float]] = set()
for match in self._UNIT_RE.finditer(text):
width = float(match.group(1))
length = float(match.group(2))
price = self.normalize_price(match.group(3))
key = (width, length)
if key in seen_sizes:
continue
seen_sizes.add(key)
unit = UnitResult(
size=f"{int(width)} x {int(length)}",
sale_price=price,
description=match.group(0).strip(),
metadata={"width": width, "length": length, "sqft": width * length},
)
result.units.append(unit)
# Extract parking
parking_match = self._PARKING_RE.search(text)
if parking_match:
price = self.normalize_price(parking_match.group(1))
unit = UnitResult(
size="Outdoor Parking",
sale_price=price,
description=parking_match.group(0).strip(),
)
result.units.append(unit)
if not result.units:
result.warnings.append("No unit pricing found in page text")
return result
Scrape Runs (3)
Run #1438 Details
- Status
- exported
- Parser Used
- Facility7Parser
- Platform Detected
- unknown
- Units Found
- 4
- Stage Reached
- exported
- Timestamp
- 2026-03-23 03:16:06.841009
Timing
| Stage | Duration |
|---|---|
| Fetch | 1942ms |
| Detect | 2ms |
| Parse | 2ms |
| Export | 5ms |
Snapshot: 7_20260323T031608Z.html · Show Snapshot · Open in New Tab
Parsed Units (4)
5 x 10
$45.00/mo
10 x 10
$75.00/mo
10 x 20
$102.00/mo
Outdoor Parking
$45.00/mo