#!/usr/bin/env python3 """Scrape en pris fra en URL via Scrapling. Returnerer heltal eller N/A.""" import sys, re, json if len(sys.argv) < 2: print("N/A"); sys.exit(1) url = sys.argv[1] try: from scrapling import StealthyFetcher except ImportError: print("ERROR:scrapling-not-installed"); sys.exit(1) try: page = StealthyFetcher.fetch(url, stealthy_headers=True, auto_match=False) except Exception as e: print(f"ERROR:{e}"); sys.exit(1) # Metode 1: JSON-LD structured data for el in page.css('script[type="application/ld+json"]'): try: obj = json.loads(el.get().extract()) offers = obj.get('offers', {}) if isinstance(offers, list): offers = offers[0] if offers else {} p = offers.get('price') or offers.get('lowPrice') if p: price = float(str(p).replace(',', '.')) if 100 < price < 100000: print(int(price)); sys.exit(0) except Exception: pass # Metode 2: itemprop="price" content attribut for el in page.css('[itemprop="price"]'): try: content = el.get().extract() m = re.search(r'content=["\']([0-9.,]+)["\']', content) if m: p = float(m.group(1).replace(',', '.')) if 100 < p < 100000: print(int(p)); sys.exit(0) except Exception: pass # Metode 3: Next.js __NEXT_DATA__ for el in page.css('script#__NEXT_DATA__'): try: raw = el.get().extract() data = json.loads(raw.split('>', 1)[1].rsplit('<', 1)[0]) prices = [] def find_prices(obj, depth=0): if depth > 15: return if isinstance(obj, dict): for k, v in obj.items(): if k in ('price', 'lowestPrice', 'minPrice', 'amount'): try: p = float(str(v).replace(',', '.')) if 100 < p < 100000: prices.append(p) except Exception: pass else: find_prices(v, depth+1) elif isinstance(obj, list): for item in obj: find_prices(item, depth+1) find_prices(data) if prices: print(int(min(prices))); sys.exit(0) except Exception: pass # Metode 4: Synlig tekst (get_all_text) — undgår afbetalingspriser og SVG-data visible = page.get_all_text(separator="\n") # Ekskluder linjer med afdrag (kr./md, kr/måned, betalinger af) lines = [l for l in visible.split("\n") if not re.search(r'kr\./md|kr/m[åa]ned|betalinger\s+af', l, re.I)] text4 = "\n".join(lines) matches4 = re.findall(r'(\d{1,2}[.\s]?\d{3}|\d{3,5})\s*(?:\xa0|[\s\u202f])*(?:kr\.?|DKK|,-)', text4) prices4 = [] for raw in matches4: try: p = float(re.sub(r'[\s.]', '', raw)) if 100 < p < 100000: prices4.append(p) except: pass if prices4: print(int(min(prices4))); sys.exit(0) print("N/A")