← back to Japan Enrich

onboard_new_wallcoverings.py

71 lines

#!/usr/bin/env python3
"""Onboard the 9 NEW Sangetsu wallcovering patterns the sitemap missed (they sit in the
'uncategorized' category). Colorways come from the Store API pa_full-collection attribute
terms; per-colorway images from the variations; distributor brand scraped from the page.
Appends to staging/sangetsu-staging.jsonl (our format) + staging/sangetsu-brands.json. $0 local."""
import json, os, re, subprocess, urllib.request

HERE = os.path.dirname(__file__)
STORE = os.path.join(HERE, 'staging', 'sangetsu-storeapi.jsonl')
STAGING = os.path.join(HERE, 'staging', 'sangetsu-staging.jsonl')
BRANDS = os.path.join(HERE, 'staging', 'sangetsu-brands.json')
CHROME = "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"
UA = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)'
NEW = {'park-tweed-wallpaper','paisley-park-wallpaper','felt-wallpaper','summer-weave-wallpaper',
       'moondust-rays-wallpaper','cleas-2025-28-wallpaper','essential-wallpaper','trail-line-wallpaper','debonair-wallpaper'}

def api(u): return json.loads(urllib.request.urlopen(urllib.request.Request(u, headers={'User-Agent': UA}), timeout=30).read().decode('utf-8','ignore'))
BR = re.compile(r'psg-single-brands-main"?>(.*?)</div>', re.S | re.I); LN = re.compile(r'/brand/([a-z0-9-]+)/"[^>]*>([^<]+)<', re.I)
def brand_of(url):
    try:
        h = subprocess.run([CHROME,"--headless=new","--disable-gpu","--no-sandbox","--virtual-time-budget=12000","--dump-dom",url],
                           capture_output=True, timeout=45, text=True, errors='ignore').stdout
        m = BR.search(h or ''); a = LN.search(m.group(1)) if m else None
        import html as H
        return (H.unescape(a.group(2).strip()), a.group(1)) if a else (None, None)
    except Exception: return (None, None)

def main():
    prods = {}
    for l in open(STORE):
        p = json.loads(l); s = (p.get('slug') or '').lower()
        perm = (p.get('permalink') or '').rstrip('/').split('/')[-1].lower()
        if s in NEW or perm in NEW: prods[perm or s] = p
    print(f"matched {len(prods)}/9 new patterns")
    brands = json.load(open(BRANDS)) if os.path.exists(BRANDS) else {}
    added = 0
    with open(STAGING, 'a') as out:
        for key, p in prods.items():
            url = p['permalink']
            # colorway SKUs from pa_full-collection terms
            skus = []
            for at in (p.get('attributes') or []):
                if at.get('taxonomy') == 'pa_full-collection':
                    skus = [t['name'] for t in at.get('terms', [])]
            # per-colorway images from variations (match variation attr value → image)
            imgs = {}
            try:
                for v in api(f"https://www.sangetsu-goodrich.co.th/wp-json/wc/store/v1/products?type=variation&per_page=100&parent={p['id']}"):
                    val = None
                    for va in (v.get('attributes') or []):
                        if 'collection' in (va.get('name','').lower()): val = va.get('value')
                    src = (v.get('images') or [{}])[0].get('src')
                    if val and src: imgs[val] = src
            except Exception: pass
            if not imgs and p.get('images'):  # fallback: main image for all
                for s in skus: imgs[s] = p['images'][0]
            dist, slug = brand_of(url)
            rec = {"source":"sangetsu","source_url":url,"pattern":p['name'],"overview":None,
                   "spec":{"width":None,"type":None,"weight":None,"backing":None,"is_grasscloth":False,"is_metallic":False},
                   "colorway_skus":skus,"colorway_count":len(skus),"sku_images":imgs,
                   "mfr_prefix":None,"status":"storeapi-new","distributor":dist,"distributor_direct":False}
            out.write(json.dumps(rec, ensure_ascii=False) + '\n')
            brands[url] = {"distributor": dist, "slug": slug}
            added += 1
            print(f"  + {p['name']:28s} {len(skus):3d} colorways  brand={dist}")
    json.dump(brands, open(BRANDS,'w'), ensure_ascii=False, indent=0)
    print(f"\nappended {added} new wallcovering patterns to staging + brand map")

if __name__ == '__main__':
    main()