Crawler-Parser: og/product:price-Meta (toom 799 €, Hornbach) + Hornbach.ch als erste Ausland-Live-Quelle (cc)

This commit is contained in:
2026-06-28 09:50:50 +00:00
parent 5b0d0e6a19
commit c5adbb34db
2 changed files with 22 additions and 1 deletions
+19 -1
View File
@@ -36,6 +36,22 @@ def _num(s):
g=m.groups()
return float(g[0]) + (float(g[1])/100 if len(g)>1 and g[1] else 0)
def clean_price(v):
v=(v or "").strip()
if not v: return None
if "," in v: v=v.replace(".","").replace(",",".")
m=re.search(r"\d+(?:\.\d+)?", v)
return float(m.group()) if m else None
def price_from_meta(h):
for pat in ("product:price:amount","og:price:amount"):
m=re.search(r'<meta[^>]+(?:property|name)=["\']'+pat+r'["\'][^>]+content=["\']([^"\']+)', h, re.I) or \
re.search(r'<meta[^>]+content=["\']([^"\']+)["\'][^>]+(?:property|name)=["\']'+pat+r'["\']', h, re.I)
if m:
p=clean_price(m.group(1))
if p: return p
return None
def parse(htmltext):
# 1) JSON-LD Offer
price=None; avail=None
@@ -56,6 +72,8 @@ def parse(htmltext):
low=htmltext.lower()
in_store = ("vorrätig" in low or "verfügbar" in low) and not ("nicht vorrätig" in low or "nicht verfügbar" in low)
online = ("in den warenkorb" in low) or ("lieferung" in low and "nicht möglich" not in low) or (avail and "instock" in avail.lower())
if price is None:
price=price_from_meta(htmltext)
if price is None:
mp=_num(htmltext[:200000])
price=mp
@@ -75,7 +93,7 @@ async def fetch_one(client, src):
if r.status_code!=200:
return {**src,"price":None,"availability":"unknown","status":r.status_code}
price, avail = parse(r.text)
return {"chain":src["chain"],"kind":src["kind"],"productId":src["productId"],"name":src["name"],
return {"chain":src["chain"],"kind":src["kind"],"cc":src.get("cc","DE"),"productId":src["productId"],"name":src["name"],
"url":src["url"],"price":price,"availability":avail}
except Exception as e:
log.warning("fetch fail %s: %s", src["url"], e)