Files
openclaw/tools/dba-search.py
Clawd Bot ca9b510922 chore: align with upstream openclaw/openclaw and overlay local additions
- Reset master to upstream/main (16,697 commits)
- Overlay 2,271 local-only files (skills, tools, workspace, configs, apps)
- Restore IDENTITY.md and USER.md templates
- Build verified, gateway running, Discord working

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 07:40:46 +01:00

111 lines
4.0 KiB
Python

#!/usr/bin/env python3
"""
DBA.dk søge-tool — henter listings og returnerer JSON.
Bruges af dba-scout agenten til at finde billige ting.
Brug:
python3 dba-search.py "rtx 3090" [--max-price 5000] [--location herning] [--limit 10]
"""
import sys, re, json, argparse
def search_dba(query: str, max_price: int = None, location: str = None, limit: int = 10) -> list[dict]:
try:
from scrapling import StealthyFetcher
except ImportError:
print(json.dumps({"error": "scrapling not installed"}))
sys.exit(1)
# DBA søge-URL (sort by price ascending)
url = f"https://www.dba.dk/recommerce/forsale/search?q={query.replace(' ','+')}&sort=PRICE_ASC"
if location:
# DBA bruger county-filter, vi filtrerer manuelt i stedet
pass
try:
page = StealthyFetcher.fetch(url, stealthy_headers=True)
except Exception as e:
return [{"error": str(e)}]
results = []
# Primær kilde: SEO structured data (JSON-LD)
for s in page.css('script[type="application/ld+json"]'):
try:
raw = s.get().extract()
data_str = raw.split('>', 1)[1].rsplit('<', 1)[0]
data = json.loads(data_str)
items = data.get('mainEntity', {}).get('itemListElement', [])
for item in items:
listing = item.get('item', item)
price_str = listing.get('offers', {}).get('price', '')
try:
price = int(float(str(price_str))) if price_str else 0
except Exception:
price = 0
if max_price and price > max_price:
continue
entry = {
'title': listing.get('name', ''),
'price': price,
'url': listing.get('url', ''),
'id': listing.get('sku', ''),
'description': (listing.get('description') or '')[:200],
'condition': listing.get('itemCondition', '').replace('https://schema.org/', ''),
}
# Lokation fra URL ikke mulig via structured data — flag hvis i location
if location:
combined = (entry['title'] + entry['description']).lower()
if location.lower() not in combined:
# Hent listing for at tjekke by — skip for hastighed, marker som unknown
entry['location'] = 'unknown'
else:
entry['location'] = location
if entry['title']:
results.append(entry)
if len(results) >= limit:
break
except Exception:
pass
return results
def format_result(r: dict) -> str:
price = f"{r['price']} kr" if r['price'] else "ukendt pris"
loc = f" [{r['location']}]" if r.get('location') else ""
cond = " (brugt)" if 'Used' in r.get('condition', '') else ""
url = r.get('url', '')
return f"{r['title']}{cond}{price}{loc}\n {url}"
def main():
parser = argparse.ArgumentParser(description='Søg på DBA.dk')
parser.add_argument('query', help='Søgeord')
parser.add_argument('--max-price', type=int, default=None, help='Max pris i kr')
parser.add_argument('--location', default=None, help='By/lokation')
parser.add_argument('--limit', type=int, default=10, help='Max antal resultater')
parser.add_argument('--json', action='store_true', help='Output som JSON')
args = parser.parse_args()
results = search_dba(args.query, args.max_price, args.location, args.limit)
if args.json or not sys.stdout.isatty():
print(json.dumps(results, ensure_ascii=False, indent=2))
else:
if not results:
print(f"Ingen resultater for '{args.query}'")
else:
print(f"\nFandt {len(results)} resultater for '{args.query}':\n")
for r in results:
print(format_result(r))
print()
if __name__ == '__main__':
main()