#!/usr/bin/env python3 """Kombi-Script: Brettspiel-Deals + Multi-Kategorie. Ausführung bei jeder Top-30-Anfrage.""" import os, time from datetime import datetime exec(open('/home/hermes/.hermes/skills/finance/amazon-brettspiel-deals/scripts/search_deals.py').read().split('RESOURCES')[0]) from amazon_creatorsapi import AmazonCreatorsApi, Country from amazon_creatorsapi import models as m PARTNER_TAG = "60pro05-21" COUNTRY = Country.DE R_COMMON = [ m.SearchItemsResource.ITEM_INFO_DOT_TITLE, m.SearchItemsResource.IMAGES_DOT_PRIMARY_DOT_LARGE, m.SearchItemsResource.OFFERS_V2_DOT_LISTINGS_DOT_PRICE, m.SearchItemsResource.ITEM_INFO_DOT_BY_LINE_INFO, ] MULTI_CATEGORIES = [ ("Heißluftfritteusen", ["Heißluftfritteuse", "Airfryer", "Air Fryer"], 10, None), ("Staubsauger & Wischroboter", ["Staubsauger", "Saugroboter", "Wischsauger", "Akkusauger"], 10, None), ("Laptops & Notebooks", ["Laptop", "Notebook"], 5, None), ("Apple-Produkte", ["Apple iPhone", "Apple iPad", "Apple Watch", "Apple AirPods"], 5, None), ("Tablets", ["Tablet"], 5, None), ("Smartphones", ["Smartphone"], 5, None), ] def search_deals(api, keywords, count, node=None, with_savings=True): deals, seen = [], set() for kw in keywords: if len(deals) >= count * 3: break for page in range(1, 5): if len(deals) >= count * 3: break try: kwargs = dict(keywords=kw, item_count=50, item_page=page, resources=R_COMMON) if node: kwargs["browse_node_id"] = node resp = api.search_items(**kwargs) time.sleep(1.1) if not resp or not resp.items: continue for item in resp.items: if len(deals) >= count * 3: break try: asin = str(item.asin) if asin in seen: continue seen.add(asin) title = str(item.item_info.title.display_value) brand = str(item.item_info.by_line_info.brand.display_value) if item.item_info.by_line_info and item.item_info.by_line_info.brand else "" if not item.offers_v2 or not item.offers_v2.listings: continue li = item.offers_v2.listings[0] if not li.price or not li.price.money: continue pr = float(li.price.money.amount) sp, se, lp = 0, 0, pr if li.price.savings and li.price.savings.money: se = float(li.price.savings.money.amount) sp = int(li.price.savings.percentage) if li.price.saving_basis and li.price.saving_basis.money: lp = float(li.price.saving_basis.money.amount) if not with_savings or sp >= 10: img = "" if item.images and item.images.primary and item.images.primary.large: img = str(item.images.primary.large.url) deals.append({"t":title,"b":brand,"img":img,"pr":pr,"lp":lp,"sp":sp,"se":se, "url":f"https://www.amazon.de/dp/{asin}?tag={PARTNER_TAG}"}) except: continue except Exception as e: print(f" E {kw}: {e}") if with_savings: deals.sort(key=lambda x: x["sp"], reverse=True) return deals[:count] def generate_combined_html(board_deal_html_path, multi_results, output_path): # Read board game HTML with open(board_deal_html_path) as f: board_html = f.read() # Build multi-category sections now = datetime.now().strftime("%d.%m.%Y, %H:%M") sec = "" for cat_name, deals in multi_results.items(): if not deals: continue label = f"{cat_name} ({len(deals)})" sec += f'

{label}

\n' for d in deals: img = f'' if d["img"] else "" br = f'
{d["b"]}' if d["b"] else "" pct = f'-{d["sp"]}%' if d["sp"] > 0 else '' saved = f'({d["se"]:.2f} €)' if d["se"] > 0 else '' has_deal = d["sp"] > 0 uvp_line = f'UVP {d["lp"]:.2f} €' if has_deal else '' badge_line = f'{pct}{saved}' if has_deal else '' sec += f"""
{img}
{d['t'][:120]}{br}
{d['pr']:.2f} € {uvp_line} {badge_line}
Zu Amazon →
\n""" footer_marker = '

' combined = board_html.replace(footer_marker, sec + footer_marker) with open(output_path, 'w') as f: f.write(combined) return output_path def main(): import argparse parser = argparse.ArgumentParser() parser.add_argument('--board-html', type=str, required=True, help='Path to board game deals HTML') parser.add_argument('--output', type=str, default=None) args = parser.parse_args() if args.output is None: args.output = os.path.expanduser(f"~/workspace/kombi_deals_{datetime.now().strftime('%Y-%m-%d')}.html") api = AmazonCreatorsApi(CREDENTIAL_ID, CREDENTIAL_SECRET, "3.2", PARTNER_TAG, country=COUNTRY, throttling=1.0) print("Connected!\n") results = {} for cat_name, keywords, count, node in MULTI_CATEGORIES: print(f"--- {cat_name} ---") deals = search_deals(api, keywords, count, node, with_savings=True) results[cat_name] = deals print(f" => {len(deals)}/{count}") for d in deals: print(f" -{d['sp']}% | {d['pr']:.2f}€ | {d['t'][:80]}") # Bücher: Top 5 Bestseller (keine Angebots-Filterung) print("--- Bücher-Bestseller ---") books = search_deals(api, ["Bestseller Roman", "Bestseller Buch", "Thriller Bestseller"], 5, "541686", with_savings=False) results["Bücher-Bestseller (Top 5)"] = books print(f" => {len(books)}/5") for d in books: print(f" {d['pr']:.2f}€ | {d['t'][:80]}") output = generate_combined_html(args.board_html, results, args.output) total = sum(len(v) for v in results.values()) print(f"\n{total} Non-Brettspiel-Deals hinzugefügt → {output}") if __name__ == "__main__": main()