notebookvb

This commit is contained in:
Vladimir Buzalka
2026-05-08 13:30:47 +02:00
parent ee6fd79f5c
commit c9903646f1
20 changed files with 2024 additions and 56 deletions
@@ -0,0 +1,103 @@
"""
Stáhne daily Kakuro puzzle data ze solitaire.org a uloží do MySQL.
PDF generování bude doplněno později.
"""
import asyncio
import json
import sys
sys.stdout.reconfigure(encoding="utf-8")
sys.stderr.reconfigure(encoding="utf-8")
from datetime import date
from pathlib import Path
from playwright.async_api import async_playwright
sys.path.insert(0, str(Path(__file__).parent.parent.parent / "Knihovny"))
from mysql_db import connect_mysql
URL = "https://www.solitaire.org/daily-kakuro/"
DIFFICULTIES = ["easy", "medium", "hard", "expert"]
async def fetch_all_levels() -> dict:
async with async_playwright() as p:
browser = await p.chromium.launch(headless=True)
context = await browser.new_context(viewport={"width": 1280, "height": 900})
page = await context.new_page()
print(f"Načítám {URL} ...")
await page.goto(URL, wait_until="networkidle", timeout=60_000)
game_url = None
for frame in page.frames:
if frame.url != page.url and frame.url.strip() not in ("", "about:blank"):
game_url = frame.url
break
if not game_url:
iframe_src = await page.get_attribute("iframe", "src")
if iframe_src:
game_url = iframe_src if iframe_src.startswith("http") else f"https://www.solitaire.org{iframe_src}"
await page.close()
game_page = await context.new_page()
target_url = game_url if game_url else URL
print(f"Načítám hru: {target_url} ...")
await game_page.goto(target_url, wait_until="networkidle", timeout=60_000)
raw = await game_page.evaluate("() => JSON.stringify(gameLevels)")
await browser.close()
return json.loads(raw)
def grid_size(data_str: str) -> int:
"""Vrátí rozměr mřížky z raw dat (počet sloupců prvního řádku + 1 pro prepended 0)."""
first_row = data_str.split(",")[0]
return len(first_row) + 1
def save_to_mysql(game_levels: dict, start_date: date, end_date: date):
conn = connect_mysql(database="puzzle")
cur = conn.cursor()
inserted = 0
d = start_date
while d <= end_date:
mmdd = d.strftime("%m-%d")
date_str = d.strftime("%Y-%m-%d")
for diff in DIFFICULTIES:
if diff not in game_levels or mmdd not in game_levels[diff]:
continue
data_str = game_levels[diff][mmdd]
size = grid_size(data_str)
cur.execute(
"INSERT IGNORE INTO puzzles (game_type, difficulty, puzzle_date, puzzle, solution, extra, source) "
"VALUES (%s, %s, %s, %s, %s, %s, %s)",
("kakuro", diff, date_str, data_str, data_str,
json.dumps({"grid_size": size}), "solitaire.org"),
)
if cur.rowcount > 0:
inserted += 1
d += __import__("datetime").timedelta(days=1)
cur.close()
conn.close()
return inserted
async def main():
today = date.today()
game_levels = await fetch_all_levels()
print(f"gameLevels: {sum(len(game_levels.get(d, {})) for d in DIFFICULTIES)} záznamů")
inserted = save_to_mysql(game_levels, date(2026, 1, 1), date(2026, 12, 31))
print(f"MySQL: vloženo {inserted} nových řádků (celý rok 2026)")
if __name__ == "__main__":
asyncio.run(main())