Facility: 004533
Store More Self Storage
- Facility ID
- 004533
- Name
- Store More Self Storage
- URL
- https://www.bagbytransfer.com/storage-locations
- Address
- 117 Huffaker Rd NW, Rome, GA 30165, USA, Rome, Georgia 30165
- Platform
- custom_facility_004533
- Parser File
- src/parsers/custom/facility_004533_parser.py
- Last Scraped
- 2026-03-27 13:58:55.454235
- Created
- 2026-03-14 16:21:53.706708
- Updated
- 2026-03-27 13:58:55.486877
- Parser Status
- ✓ Working
- Status Reason
- N/A
- Last Healing Attempt
- Not attempted
Parser Source (src/parsers/custom/facility_004533_parser.py)
"""Parser for Store More Self Storage (Bagby Transfer & Storage).
StorEdge-powered site with unit data embedded as JSON-LD Product entries.
URL: https://www.bagbytransfer.com/storage-locations
This is a multi-location site with 5+ "Sites" distinguished by the product
``category`` field (e.g. "Site 5 WEST ROME-HUFFAKER - CC"). We filter to
only the site matching the target facility's address.
"""
from __future__ import annotations
import json
from bs4 import BeautifulSoup
from src.parsers.base import BaseParser, ParseResult, UnitResult
class Facility004533Parser(BaseParser):
"""Extract storage units from Bagby Transfer & Storage JSON-LD.
Filters to the target facility location based on address keywords
matched against the product category field.
"""
platform = "custom_facility_004533"
# The target facility is at 117 Huffaker Rd NW, Rome, GA 30165.
# Products for this location have "HUFFAKER" or "Huff" in their category.
_LOCATION_KEYWORDS = ["huffaker", "huff"]
def parse(self, html: str, url: str = "") -> ParseResult:
soup = BeautifulSoup(html, "lxml")
result = ParseResult(platform=self.platform, parser_name=self.__class__.__name__)
all_products = self._extract_products(soup)
if not all_products:
result.warnings.append("No units found in JSON-LD Product entries")
return result
# Group products by category to detect multi-location pages
categories: dict[str, list[dict]] = {}
for product in all_products:
cat = (
product.get("category", "")
or product.get("offers", {}).get("category", "")
or ""
)
categories.setdefault(cat, []).append(product)
is_multi_location = len(categories) > 1
if is_multi_location:
# Filter to categories matching our target location
matched_cats = [
cat
for cat in categories
if any(kw in cat.lower() for kw in self._LOCATION_KEYWORDS)
]
if not matched_cats:
result.warnings.append(
f"Multi-location page with {len(categories)} site categories "
f"({', '.join(sorted(categories.keys())[:5])}...) but could not "
f"identify target facility (Huffaker Rd). "
f"Returning 0 units to avoid data contamination."
)
return result
target_products = []
for cat in matched_cats:
target_products.extend(categories[cat])
result.warnings.append(
f"Multi-location page with {len(categories)} site categories; "
f"filtered to {len(matched_cats)} matching categories "
f"({', '.join(matched_cats)}) with {len(target_products)} units "
f"(excluded {len(all_products) - len(target_products)} units "
f"from other locations)"
)
else:
target_products = all_products
# Build UnitResult objects from filtered products
for product in target_products:
size_text = product.get("description", "")
if not size_text:
continue
offers = product.get("offers", {})
if isinstance(offers, list):
offers = offers[0] if offers else {}
price_raw = offers.get("price")
category = product.get("category", "") or offers.get("category", "")
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}
if price_raw is not None:
unit.price = self.normalize_price(str(price_raw))
if category:
unit.description = f"{size_text} - {category}"
else:
unit.description = size_text
if unit.size or unit.price:
result.units.append(unit)
if not result.units:
result.warnings.append("No units found after filtering to target facility")
return result
def _extract_products(self, soup: BeautifulSoup) -> list[dict]:
"""Collect all JSON-LD Product entries from the page."""
products: list[dict] = []
for script in soup.find_all("script", type="application/ld+json"):
try:
data = json.loads(script.string or "")
except (json.JSONDecodeError, TypeError):
continue
if isinstance(data, dict) and "@graph" in data:
products.extend(
item
for item in data["@graph"]
if isinstance(item, dict) and item.get("@type") == "Product"
)
elif isinstance(data, dict) and data.get("@type") == "Product":
products.append(data)
elif isinstance(data, list):
products.extend(
item
for item in data
if isinstance(item, dict) and item.get("@type") == "Product"
)
return products
Scrape Runs (4)
-
exported Run #19892026-03-27 13:58:49.207530 | 56 units | Facility004533Parser | View Data →
-
exported Run #12602026-03-23 03:00:18.680847 | 56 units | Facility004533Parser | View Data →
-
exported Run #7672026-03-21 18:51:56.995452 | 56 units | Facility004533Parser | View Data →
-
exported Run #3162026-03-14 16:32:53.451360 | 126 units | Facility004533Parser | View Data →
Run #1989 Details
- Status
- exported
- Parser Used
- Facility004533Parser
- Platform Detected
- storageunitsoftware
- Units Found
- 56
- Stage Reached
- exported
- Timestamp
- 2026-03-27 13:58:49.207530
Timing
| Stage | Duration |
|---|---|
| Fetch | 6146ms |
| Detect | 32ms |
| Parse | 10ms |
| Export | 24ms |
Snapshot: 004533_20260327T135855Z.html · Show Snapshot · Open in New Tab
Parsed Units (56)
15x15
$225.00/mo
10x15
$145.00/mo
10x30
$280.00/mo
10x15
$155.00/mo
5x10
$0.00/mo
10x15
$155.00/mo
5x10
$90.00/mo
10x15
$145.00/mo
10x30
$260.00/mo
15x15
$225.00/mo
10x10
$115.00/mo
15x15
$225.00/mo
10x15
$155.00/mo
10x15
$155.00/mo
10x12
$125.00/mo
10x15
$155.00/mo
20x25
$455.00/mo
20x50
$615.00/mo
20x25
$455.00/mo
20x50
$615.00/mo
20x20
$345.00/mo
5x10
$90.00/mo
5x10
$0.00/mo
15x15
$260.00/mo
10x15
$145.00/mo
10x15
$145.00/mo
10x15
$155.00/mo
10x15
$150.00/mo
20x25
$425.00/mo
10x10
$115.00/mo
15x20
$280.00/mo
10x15
$155.00/mo
10x10
$109.25/mo
15x20
$260.00/mo
10x20
$185.00/mo
10x15
$155.00/mo
15x15
$260.00/mo
10x12
$115.00/mo
10x12
$120.00/mo
10x10
$105.00/mo
10x15
$155.00/mo
10x10
$115.00/mo
10x7.5
$100.00/mo
20x25
$700.00/mo
15x15
$210.00/mo
15x15
$210.00/mo
10x30
$280.00/mo
10x12
$125.00/mo
10x15
$155.00/mo
10x12.5
$125.00/mo
7.5x10
$100.00/mo
20x20
$370.00/mo
10x10
$115.00/mo
5x10
$85.00/mo
10x10
$115.00/mo
5x10
$90.00/mo