Compare commits

..

No commits in common. "main" and "0.1" have entirely different histories.
main ... 0.1

17 changed files with 63 additions and 739 deletions

3
.idea/.gitignore generated vendored
View file

@ -1,3 +0,0 @@
# Default ignored files
/shelf/
/workspace.xml

8
.idea/Lotto2PY.iml generated
View file

@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="PYTHON_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="jdk" jdkName="Python 3.9" jdkType="Python SDK" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

View file

@ -1,6 +0,0 @@
<component name="InspectionProjectProfileManager">
<settings>
<option name="USE_PROJECT_PROFILE" value="false" />
<version value="1.0" />
</settings>
</component>

7
.idea/misc.xml generated
View file

@ -1,7 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Black">
<option name="sdkName" value="Python 3.9" />
</component>
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.9" project-jdk-type="Python SDK" />
</project>

8
.idea/modules.xml generated
View file

@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/Lotto2PY.iml" filepath="$PROJECT_DIR$/.idea/Lotto2PY.iml" />
</modules>
</component>
</project>

6
.idea/vcs.xml generated
View file

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>

View file

@ -1,291 +0,0 @@
# /opt/lotto/app.py
import os
from datetime import date, datetime
from typing import List, Optional
from fastapi import FastAPI, Query, Request, HTTPException
from fastapi.responses import HTMLResponse
from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates
from pydantic import BaseModel
from sqlalchemy import create_engine, text
from sqlalchemy.engine import Engine, Row
from sqlalchemy.pool import NullPool
from dotenv import load_dotenv
# --------------------------------------------------------
# 0) Konfiguration laden
# --------------------------------------------------------
load_dotenv()
DATABASE_URL = os.getenv("DATABASE_URL")
if not DATABASE_URL:
raise RuntimeError("DATABASE_URL nicht gesetzt (.env prüfen)")
PAGE_SIZE = int(os.getenv("PAGE_SIZE", "10"))
# --------------------------------------------------------
# 1) App und DB initialisieren
# --------------------------------------------------------
engine: Engine = create_engine(DATABASE_URL, poolclass=NullPool, future=True)
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
STATIC_DIR = os.path.join(BASE_DIR, "static")
TEMPLATE_DIR = os.path.join(BASE_DIR, "templates")
app = FastAPI(title="Lotto Ziehungen API")
app.mount("/static", StaticFiles(directory=STATIC_DIR), name="static")
templates = Jinja2Templates(directory=TEMPLATE_DIR)
# --------------------------------------------------------
# 2) Modelle (Pydantic)
# --------------------------------------------------------
class Draw(BaseModel):
datum: Optional[date]
z1: Optional[int]
z2: Optional[int]
z3: Optional[int]
z4: Optional[int]
z5: Optional[int]
z6: Optional[int]
sz: Optional[int]
sz1: Optional[int]
sz2: Optional[int]
super6: Optional[str]
spiel77: Optional[str]
class DrawList(BaseModel):
total: int
items: List[Draw]
# --------------------------------------------------------
# 3) Hilfsfunktionen
# --------------------------------------------------------
def normalize_date_sql(column: str) -> str:
return (
f"COALESCE("
f" (CASE WHEN {column} REGEXP '^[0-9]{{4}}-[0-9]{{2}}-[0-9]{{2}}$' THEN DATE({column}) END),"
f" STR_TO_DATE({column}, '%d.%m.%Y'),"
f" STR_TO_DATE(SUBSTRING_INDEX({column}, '/', -1), '%d.%m.%y')"
f")"
)
def row_to_draw(row: Row) -> Draw:
return Draw(**row)
def _to_date(s: Optional[str]) -> Optional[date]:
if not s:
return None
t = s.strip()
if not t:
return None
try:
return date.fromisoformat(t)
except ValueError:
pass
for fmt in ("%d.%m.%Y", "%d.%m.%y"):
try:
return datetime.strptime(t, fmt).date()
except ValueError:
continue
return None
# --------------------------------------------------------
# 4) Routen
# --------------------------------------------------------
@app.get("/", response_class=HTMLResponse)
async def index(request: Request):
return templates.TemplateResponse(
"index.html", {"request": request, "page_size": PAGE_SIZE}
)
# -------------------- API: Ziehungen (JSON) ---------------------
@app.get("/api/draws", response_model=DrawList)
async def list_draws(
game: str = Query("6aus49", pattern="^(6aus49|euro)$"),
date_from: Optional[date] = Query(None),
date_to: Optional[date] = Query(None),
limit: int = Query(PAGE_SIZE, ge=1, le=500),
offset: int = Query(0, ge=0),
order: str = Query("desc", pattern="^(asc|desc)$"),
):
tbl = "`6aus49`" if game == "6aus49" else "`euro`"
dx = normalize_date_sql(f"{tbl}.datum")
if game == "6aus49":
base_select = f"""
SELECT {dx} AS datum,
z1, z2, z3, z4, z5, z6, sz,
CAST(super6 AS CHAR) AS super6,
CAST(spiel77 AS CHAR) AS spiel77,
NULL AS sz1, NULL AS sz2
FROM {tbl}
"""
else:
base_select = f"""
SELECT {dx} AS datum,
z1, z2, z3, z4, z5,
NULL AS z6, NULL AS sz,
NULL AS super6, NULL AS spiel77,
sz1, sz2
FROM {tbl}
"""
where_parts = []
params = {}
if date_from:
where_parts.append("datum >= :date_from")
params["date_from"] = date_from
if date_to:
where_parts.append("datum <= :date_to")
params["date_to"] = date_to
where_sql = "WHERE " + " AND ".join(where_parts) if where_parts else ""
order_sql = "ORDER BY datum DESC" if order == "desc" else "ORDER BY datum ASC"
count_sql = f"SELECT COUNT(*) AS cnt FROM ({base_select}) AS t {where_sql}"
data_sql = f"SELECT * FROM ({base_select}) AS t {where_sql} {order_sql} LIMIT :limit OFFSET :offset"
with engine.begin() as conn:
total = conn.execute(text(count_sql), params).scalar_one()
rows = conn.execute(text(data_sql), {**params, "limit": limit, "offset": offset}).mappings().all()
items = [row_to_draw(r) for r in rows]
return DrawList(total=total, items=items)
# -------------------- API: Detail (JSON) ------------------------
@app.get("/api/draw/{game}/{draw_date}", response_model=Draw)
async def get_draw(game: str, draw_date: date):
tbl = "`6aus49`" if game == "6aus49" else "`euro`"
dx = normalize_date_sql(f"{tbl}.datum")
if game == "6aus49":
sql = text(f"""
SELECT {dx} AS datum,
z1, z2, z3, z4, z5, z6, sz,
CAST(super6 AS CHAR) AS super6,
CAST(spiel77 AS CHAR) AS spiel77,
NULL AS sz1, NULL AS sz2
FROM {tbl}
WHERE {dx} = :d
""")
else:
sql = text(f"""
SELECT {dx} AS datum,
z1, z2, z3, z4, z5,
NULL AS z6, NULL AS sz,
NULL AS super6, NULL AS spiel77,
sz1, sz2
FROM {tbl}
WHERE {dx} = :d
""")
with engine.begin() as conn:
row = conn.execute(sql, {"d": draw_date}).mappings().first()
if not row:
raise HTTPException(status_code=404, detail="Ziehung nicht gefunden")
return row_to_draw(row)
# -------------------- UI / HTMX (HTML) -------------------------
@app.get("/ui/draws", response_class=HTMLResponse)
async def ui_draws(
request: Request,
game: str = Query("6aus49", pattern="^(6aus49|euro)$"),
date_from: Optional[str] = Query(None),
date_to: Optional[str] = Query(None),
limit: int = Query(PAGE_SIZE, ge=1, le=500),
offset: int = Query(0, ge=0),
order: str = Query("desc", pattern="^(asc|desc)$"),
):
d_from = _to_date(date_from)
d_to = _to_date(date_to)
result = await list_draws(game, d_from, d_to, limit, offset, order) # type: ignore
rows_html = []
if game == "6aus49":
header = (
"<tr><th>Datum</th><th>Zahlen</th><th>Superzahl</th><th>Super 6</th><th>Spiel 77</th></tr>"
)
for r in result.items:
numbers = " ".join(
f"<span class='badge'>{getattr(r, f'z{i}')}</span>"
for i in range(1, 7)
if getattr(r, f"z{i}") is not None
)
sz_html = "" if r.sz is None else r.sz
rows_html.append(
f"<tr><td>{r.datum or ''}</td><td class='numbers'>{numbers}</td>"
f"<td><b>{sz_html}</b></td><td>{r.super6 or ''}</td><td>{r.spiel77 or ''}</td></tr>"
)
else:
header = "<tr><th>Datum</th><th>Zahlen</th><th>Super 1</th><th>Super 2</th></tr>"
for r in result.items:
numbers = " ".join(
f"<span class='badge'>{getattr(r, f'z{i}')}</span>"
for i in range(1, 6)
if getattr(r, f"z{i}") is not None
)
sz1_html = "" if r.sz1 is None else r.sz1
sz2_html = "" if r.sz2 is None else r.sz2
rows_html.append(
f"<tr><td>{r.datum or ''}</td><td class='numbers'>{numbers}</td>"
f"<td><b>{sz1_html}</b></td><td><b>{sz2_html}</b></td></tr>"
)
html = (
f"<p class='muted'>Treffer: {result.total}</p>"
f"<table role='grid'><thead>{header}</thead><tbody>{''.join(rows_html)}</tbody></table>"
)
return HTMLResponse(html)
# -------------------- UI: Header-Kugeln (inkl. Datum) -------------------------
@app.get("/ui/header", response_class=HTMLResponse)
async def ui_header(
game: str = Query("6aus49", pattern="^(6aus49|euro)$"),
date_from: Optional[str] = Query(None),
date_to: Optional[str] = Query(None),
order: str = Query("desc", pattern="^(asc|desc)$"),
):
d_from = _to_date(date_from)
d_to = _to_date(date_to)
result = await list_draws(game, d_from, d_to, limit=1, offset=0, order=order) # type: ignore
if not result.items:
return HTMLResponse("<div class='balls' aria-hidden='true'></div>")
r = result.items[0]
date_label = r.datum.strftime("%d.%m.%Y") if r.datum else ""
if game == "6aus49":
nums = " ".join(
f"<div class='ball'>{getattr(r, f'z{i}')}</div>"
for i in range(1, 7)
if getattr(r, f"z{i}") is not None
)
sz_html = "" if r.sz is None else f"<div class='ball super-ball'><b>{r.sz}</b></div>"
html = f"""
<div class="balls" title="Letzte Ziehung {date_label}">
{nums}{sz_html}
<span class="label">Stand: {date_label}</span>
</div>
"""
else:
nums = " ".join(
f"<div class='ball'>{getattr(r, f'z{i}')}</div>"
for i in range(1, 6)
if getattr(r, f"z{i}") is not None
)
s1 = "" if r.sz1 is None else f"<div class='star'>{r.sz1}</div>"
s2 = "" if r.sz2 is None else f"<div class='star'>{r.sz2}</div>"
html = f"""
<div class="balls" title="Letzte Ziehung {date_label}">
{nums}{s1}{s2}
<span class="label">Stand: {date_label}</span>
</div>
"""
return HTMLResponse(html)
# -------------------- Healthcheck --------------------------
@app.get("/health")
def health():
return {"status": "ok"}

View file

@ -1,15 +0,0 @@
fastapi==0.115.0
uvicorn[standard]==0.30.0
SQLAlchemy==2.0.34
PyMySQL==1.1.1
python-dotenv==1.0.1
jinja2==3.1.4
pydantic==2.9.2
fastapi==0.115.0
uvicorn[standard]==0.30.0
SQLAlchemy==2.0.34
psycopg2-binary==2.9.9
python-dotenv==1.0.1
jinja2==3.1.4
pydantic==2.9.2

View file

@ -1,41 +0,0 @@
function renderDrawsTable(data) {
if (!data || !Array.isArray(data.items)) {
return '<p class="muted">Keine Daten</p>';
}
const rows = data.items.map(d => `
<tr>
<td class="nowrap"><a href="/api/draw/${d.datum}" target="_blank">${d.datum}</a></td>
<td class="numbers">${[d.z1,d.z2,d.z3,d.z4,d.z5,d.z6].map(n => `<span class="badge">${n}</span>`).join(' ')}</td>
<td class="nowrap"><strong>${d.sz}</strong></td>
</tr>
`).join('');
return `
<p class="muted">Treffer: ${data.total}</p>
<table role="grid">
<thead>
<tr><th>Datum</th><th>Zahlen</th><th>Superzahl</th></tr>
</thead>
<tbody>${rows}</tbody>
</table>`;
}
function renderFrequencyPanels(data) {
const z = (data.zahlen || []).map(x => `<tr><td>${x.zahl}</td><td>${x.haeufigkeit}</td></tr>`).join('');
const sz = (data.superzahl || []).map(x => `<tr><td>${x.zahl}</td><td>${x.haeufigkeit}</td></tr>`).join('');
return `
<div>
<h3>Häufigkeit Zahlen (149)</h3>
<table role="grid">
<thead><tr><th>Zahl</th><th>Häufigkeit</th></tr></thead>
<tbody>${z}</tbody>
</table>
</div>
<div>
<h3>Häufigkeit Superzahl (09)</h3>
<table role="grid">
<thead><tr><th>Superzahl</th><th>Häufigkeit</th></tr></thead>
<tbody>${sz}</tbody>
</table>
</div>`;
}

View file

@ -1,143 +0,0 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="utf-8" />
<title>Lotto-Ziehungen</title>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<script src="https://unpkg.com/htmx.org@1.9.12"></script>
<link rel="icon" href="{{ request.url_for('static', path='favicon.ico') if request else '/static/favicon.ico' }}">
<style>
:root{
--brand-green:#0a6;
--brand-green-dark:#085f42;
--table-border:#ddd;
--paper:#fff;
--bg:#f6f6f6;
--ink:#222;
--muted:#666;
--gold:#c6a100;
--gold2:#f1d65c;
}
body{
font-family:"Segoe UI", Arial, sans-serif;
background:var(--bg);
color:var(--ink);
margin:0; padding:2rem;
}
main{
max-width:960px; margin:0 auto;
background:var(--paper);
border:1px solid #ddd; border-radius:8px;
box-shadow:0 2px 5px rgba(0,0,0,.05);
padding:2rem 2.5rem;
}
.brandbar{ display:flex; align-items:center; justify-content:space-between; gap:1rem; margin-bottom:.2rem; }
.brand-left{ display:flex; align-items:center; gap:.8rem; }
.brand-left img{ height:54px; width:auto; display:block; filter:drop-shadow(0 2px 2px rgba(0,0,0,.15)); }
h1{ margin:0; font-size:1.9rem; font-weight:600; letter-spacing:.02em; }
/* Kugeln */
.balls{ display:flex; align-items:center; gap:.35rem; flex-wrap:wrap; }
.ball, .star{
display:inline-flex; align-items:center; justify-content:center;
width:34px; height:34px; border-radius:50%;
font-weight:700; font-size:.95rem; color:#fff;
box-shadow:inset 0 2px 6px rgba(0,0,0,.25), 0 1px 2px rgba(0,0,0,.08);
user-select:none;
}
.ball{
background:radial-gradient(120% 120% at 30% 30%, #15b77d 0%, var(--brand-green) 55%, var(--brand-green-dark) 100%);
text-shadow:0 1px 1px rgba(0,0,0,.35);
border:1px solid var(--brand-green-dark);
}
/* Superzahl jetzt goldfarben */
.super-ball {
background: radial-gradient(120% 120% at 30% 30%, var(--gold2) 0%, var(--gold) 70%, #8a6f00 100%);
color: #231;
border: 1px solid #a88600;
font-weight: 800;
text-shadow: 0 1px 1px rgba(255,255,255,.4);
}
/* Eurojackpot Sterne */
.star{
background:radial-gradient(120% 120% at 30% 30%, var(--gold2) 0%, var(--gold) 70%, #8a6f00 100%);
color:#231; border:1px solid #a88600; font-weight:800;
}
.balls .label{
margin-left:.5rem; font-size:.85rem; color:#666; font-weight:600; white-space:nowrap;
}
p.service-note{ text-align:center; margin:.4rem 0 1.6rem 0; font-size:.95rem; color:var(--muted); font-style:italic; }
form{ display:flex; flex-wrap:wrap; align-items:center; justify-content:center; gap:.6rem; margin-bottom:1rem; }
label{ font-weight:500; }
input, select, button{ padding:.35rem .6rem; border:1px solid #bbb; border-radius:4px; background:#fff; font-size:.95rem; }
button{ background:var(--brand-green); color:#fff; border:none; font-weight:600; cursor:pointer; transition:background .2s; }
button:hover{ background:#098557; }
table{ width:100%; border-collapse:collapse; margin-top:.5rem; font-size:.95rem; }
th, td{ border:1px solid var(--table-border); padding:.45rem .5rem; text-align:center; }
th{ background:#efefef; font-weight:600; }
.numbers{ text-align:left; }
.badge{ display:inline-block; background:var(--brand-green); color:#fff; padding:.25em .5em; border-radius:.4em; margin:0 .1em; font-weight:600; }
.muted{ color:#555; font-size:.9rem; margin-top:.5rem; text-align:right; }
</style>
</head>
<body>
<main>
<!-- Kopf mit Logo links + dynamischen Kugeln rechts -->
<div class="brandbar">
<div class="brand-left">
<img src="{{ request.url_for('static', path='logo.png') }}" alt="Hintergasse Logo">
<h1>Lotto-Ziehungen</h1>
</div>
<div id="header-balls"
hx-get="/ui/header"
hx-include="#filter-form"
hx-trigger="load, change from:#filter-form"
hx-target="#header-balls"
hx-swap="innerHTML"></div>
</div>
<p class="service-note">Ein Service der Hintergasse Angaben ohne Gewähr!</p>
<!-- Filterformular -->
<form id="filter-form"
hx-get="/ui/draws"
hx-target="#results"
hx-trigger="change, submit"
hx-swap="innerHTML">
<label for="game">Spiel:</label>
<select name="game" id="game">
<option value="6aus49">6 aus 49</option>
<option value="euro">Eurojackpot</option>
</select>
<label for="date_from">von:</label>
<input type="date" name="date_from" />
<label for="date_to">bis:</label>
<input type="date" name="date_to" />
<label for="order">Sortierung:</label>
<select name="order">
<option value="desc" selected>neueste zuerst</option>
<option value="asc">älteste zuerst</option>
</select>
<label for="limit">Limit:</label>
<input type="number" name="limit" value="{{ page_size }}" min="1" max="500" />
<button type="submit">Anzeigen</button>
</form>
<!-- Ergebnisliste -->
<div id="results"
hx-get="/ui/draws"
hx-trigger="load"
hx-target="#results"
hx-swap="innerHTML"></div>
</main>
</body>
</html>

View file

@ -1,56 +0,0 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>6aus49 Auswertung</title>
<script src="https://unpkg.com/htmx.org@1.9.12"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@picocss/pico@2/css/pico.min.css">
<style>
body { max-width: 1100px; margin: auto; }
.grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px,1fr)); gap: .5rem; }
.nowrap { white-space: nowrap; }
.numbers span { display:inline-block; min-width: 2.2ch; text-align: center; }
.badge { border: 1px solid var(--pico-primary); border-radius: 4px; padding: 0 .3rem; margin: 0 .1rem; }
</style>
</head>
<body>
<h1>6aus49 Ziehungen</h1>
<!-- Reduziertes Filterformular -->
<form id="filterForm" class="grid"
hx-get="/ui/draws"
hx-target="#result"
hx-trigger="change, submit"
hx-include="#filterForm">
<label>
Von
<input type="date" name="date_from">
</label>
<label>
Bis
<input type="date" name="date_to">
</label>
<label>
Limit
<input type="number" name="limit" min="1" max="500" value="10">
</label>
<label>
Reihenfolge
<select name="order">
<option value="desc" selected>Neueste zuerst</option>
<option value="asc">Älteste zuerst</option>
</select>
</label>
<div style="grid-column: 1 / -1; display:flex; gap:.5rem;">
<button type="submit" class="primary">Anzeigen</button>
<button type="reset">Zurücksetzen</button>
</div>
</form>
<!-- Ergebniscontainer: lädt initial -->
<div id="result" hx-get="/ui/draws" hx-trigger="load" hx-target="#result">
<!-- Tabelle wird hier eingefügt -->
</div>
</body>
</html>

42
Euro2SQL.py Normal file
View file

@ -0,0 +1,42 @@
import requests
from bs4 import BeautifulSoup
# URL der Zielseite (Eurojackpot bei ARD-Text)
url = "https://lotto.gmx.de/eurojackpot/zahlen-quoten"
# HTTP-Request senden
response = requests.get(url)
response.raise_for_status() # Fehlerprüfung
# HTML mit BeautifulSoup parsen
soup = BeautifulSoup(response.text, "html.parser")
# Formatierten HTML-Code ausgeben
formatted_html = soup.prettify()
# Ausgabe in der Konsole
#print(formatted_html)
url = "https://lotto.gmx.de/eurojackpot/zahlen-quoten"
response = requests.get(url)
soup = BeautifulSoup(response.text, "html.parser")
# Finde den ersten div mit einer bestimmten Klasse
html_code = soup.find("div", class_="std")
print(html_code)
# HTML parsen
soup = BeautifulSoup(response.text, "html.parser")
# Robust: finde <b>-Tag mit "Gewinnzahlen" (normalisiert auf Whitespace!)
b_tag = soup.find("b", string=lambda s: s and "gewinnzahlen" in s.lower())
if b_tag:
table = b_tag.find_parent().find_next_sibling("table")
if table:
gewinnzahlen = [int(td.get_text(strip=True)) for td in table.find_all("td")]
print("Gewinnzahlen:", gewinnzahlen)
else:
print("Tabelle nicht gefunden.")
else:
print("<b>Gewinnzahlen</b> nicht gefunden.")

View file

@ -3,21 +3,15 @@
Der Neustart eines längst aufgegeben Projektes:
Es werden die aktuell gezogenen Lottozahlen per Cronjob
(00 21 * * 3,6 python3 /home/scripts/lotto2py.py)
von den drei Seiten
von den beiden Seiten
* https://www.ard-text.de/mobil/581 (Samstagsziehung)
* https://www.ard-text.de/mobil/582 (Mittwochsziehung)
* https://www.ard-text.de/mobil/583 (EuroJackpot)
gescrapt.
Todos:
1. [x] https://www.ard-text.de/mobil/583 (Eurojackpot)
2. [x] Ablage in SQL-Datenbank (MariaDB)
3. [x] Webinterface https://lotto.hintergasse.de
3. [ ] Webinterface
![](/screen1.jpg)
_Hinweis:
Ein Teil des Codes wurde durch Chat-GPT (GPT-4o) generiert. Dieser wurde durch den Inhaber des Repositorys modifiziert und angepast._
.

View file

@ -1,33 +0,0 @@
import pymysql
# --- Verbindung herstellen ---
connection = pymysql.connect(
host='10.0.1.123',
user='hubobel',
password='polier2003',
database='hubobel',
charset='utf8mb4',
cursorclass=pymysql.cursors.Cursor
)
try:
with connection.cursor() as cursor:
# Beispielwerte
z1, z2, z3, z4, z5 = 10, 22, 38, 42, 48
# --- Prüfabfrage: existiert diese Kombination? ---
sql_check = """
SELECT 1 FROM `euro`
WHERE z1 = %s AND z2 = %s AND z3 = %s AND z4 = %s AND z5 = %s
LIMIT 1
"""
cursor.execute(sql_check, (z1, z2, z3, z4, z5))
exists = cursor.fetchone() is not None
if exists:
print("✅ Kombination existiert bereits.")
else:
print("🆕 Kombination ist neu kann eingefügt werden.")
finally:
connection.close()

View file

@ -1,12 +0,0 @@
{
"Telegram": {
"Chat_ID": "322673713",
"TOKEN": "680737840:AAEaa7Vxl_kZz_LWS1_S-lH6Eda7HXqu6Y4"
},
"mail": {
"mail_folder": "",
"mail_host": "",
"mail_pass": "",
"mail_user": ""
}
}

View file

@ -44,12 +44,10 @@ def notify_telegram(text):
requests.post(url, params=params)
def Euro():
url = 'https://www.ard-text.de/mobil/583'
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36"
}
response = requests.get(url, headers=headers)
response = requests.get(url)
response.raise_for_status()
soup = BeautifulSoup(response.text, "html.parser")
ziffern = []
ZahlenEuro = {
'Freitag': {'Datum': '', 'Z1': '', 'Z2': '', 'Z3': '', 'Z4': '', 'Z5': '', 'Eurozahl1': '', 'Eurozahl2': ''},
'Dienstag': {'Datum': '', 'Z1': '', 'Z2': '', 'Z3': '', 'Z4': '', 'Z5': '', 'Eurozahl1': '', 'Eurozahl2': ''}}
@ -71,22 +69,19 @@ def Euro():
bb = 'Eurozahl' + str(aa)
ZahlenEuro[Tag][bb] = int(c)
aa = aa + 1
jahr = datetime.now().year
tag = datetime.now().day
monat = datetime.now().month
ZahlenEuro[Tag]['Datum'] = f"{jahr}-{monat}-{tag}"
Tag = 'Dienstag'
for b in soup.find("p", string=lambda s: s and "dienstag" in s.lower()):
ZahlenEuro[Tag]['Datum'] = b
tabelle = b.find_parent().find_next_sibling("table")
a = 1
#print(b)
print(b)
for n in tabelle.find_all("td"):
c = (n.get_text(strip=True))
b = 'Z' + str(a)
ZahlenEuro[Tag][b] = int(c)
a = a + 1
eurozahlen_tags = soup.find_all("b", string=lambda s: s and "eurozahlen" in s.lower())
aa = 1
if len(eurozahlen_tags) >= 2:
eurozahlen_table_2 = eurozahlen_tags[1].find_next("table")
@ -95,16 +90,10 @@ def Euro():
bb = 'Eurozahl' + str(aa)
ZahlenEuro[Tag][bb] = int(i)
aa = aa + 1
jahr = datetime.now().year
tag = datetime.now().day
monat = datetime.now().month
ZahlenEuro[Tag]['Datum'] = f"{jahr}-{monat}-{tag}"
return ZahlenEuro
def Normalziehung(a):
wochentag = datetime.today().weekday()
jahr = datetime.now().year
tag = f"{datetime.now().day:02d}"
monat = datetime.now().month
url = "https://www.ard-text.de/mobil/" + str(a)
@ -135,7 +124,7 @@ def Normalziehung(a):
datum_woche = line.strip()
break
# Regex: Hauptzahlen finden (z.B. Zeile enthält "11 20 28 30 35 41")
match_haupt = re.search(r"\s(\d{1,2}(?:\s+\d{1,2}){6})\s", text)
match_haupt = re.search(r"\s(\d{1,2}(?:\s+\d{1,2}){5})\s", text)
if match_haupt:
lottozahlen = [int(n) for n in match_haupt.group(1).split()]
@ -173,7 +162,7 @@ def Normalziehung(a):
ef = str((ab + str(cd)))
Lottozahlen[ef] = i
cd = cd + 1
Lottozahlen['Datum'] = f"{jahr}-{monat}-{tag}"
Lottozahlen['Datum'] = str(jahr) + ' / ' + str(datum_woche)
Lottozahlen['Superzahl'] = superzahl
Lottozahlen['Spiel77'] = int(game77)
Lottozahlen['Super6'] = int(subber6)
@ -194,14 +183,9 @@ def SQLnorm(data):
"','" + str(data['Super6']) + "','" + str(data['Spiel77']) + "')"
sql_q = "SELECT * FROM 6aus49 WHERE datum like '%" + data['Datum'] + "%'"
resp = cursor.execute(sql_q)
if test == 0:
if resp == 0:
cursor.execute(sql)
notify_telegram(str(data))
connection.commit()
cursor.close()
connection.close()
@ -219,10 +203,9 @@ def SQLdienstag(data):
data['Eurozahl2']) + "')"
sql_q = "SELECT * FROM euro WHERE datum like '%" + data['Datum'] + "%'"
resp = cursor.execute(sql_q)
if test == 0:
if resp == 0:
cursor.execute(sql)
notify_telegram(str(data))
#print(resp)
print(resp)
connection.commit()
cursor.close()
connection.close()
@ -239,9 +222,8 @@ def SQLfreitag(data):
data['Eurozahl2']) + "')"
sql_q = "SELECT * FROM euro WHERE datum like '%" + data['Datum'] + "%'"
resp = cursor.execute(sql_q)
if test == 0:
if resp == 0:
cursor.execute(sql)
notify_telegram(str(data))
connection.commit()
cursor.close()
@ -258,7 +240,7 @@ def SQLsamstag(data):
"','" + str(data['Super6']) + "','" + str(data['Spiel77']) + "')"
sql_q = "SELECT * FROM samstag WHERE datum like '%" + data['Datum'] + "%'"
resp = cursor.execute(sql_q)
if test == 0:
if resp == 0:
cursor.execute(sql)
connection.commit()
cursor.close()
@ -275,101 +257,36 @@ def SQLmittwoch(data):
"','" + str(data['Super6']) + "','" + str(data['Spiel77']) + "')"
sql_q = "SELECT * FROM samstag WHERE datum like '%" + data['Datum'] + "%'"
resp = cursor.execute(sql_q)
if test == 0:
if resp == 0:
cursor.execute(sql)
connection.commit()
cursor.close()
connection.close()
def SQLtesteuro(data):
print(data)
connection = pymysql.connect(
host='10.0.1.123',
user='hubobel',
password='polier2003',
database='hubobel',
charset='utf8mb4',
cursorclass=pymysql.cursors.Cursor
)
try:
with connection.cursor() as cursor:
# Beispielwerte
z1, z2, z3, z4, z5 = data['Z1'], data['Z2'],data['Z3'],data['Z4'],data['Z5']
sql_check = """
SELECT 1 FROM `euro`
WHERE z1 = %s AND z2 = %s AND z3 = %s AND z4 = %s AND z5 = %s
LIMIT 1
"""
cursor.execute(sql_check, (z1, z2, z3, z4, z5))
exists = cursor.fetchone() is not None
if exists:
print("✅ Kombination existiert bereits.")
a = 1
else:
print("🆕 Kombination ist neu kann eingefügt werden.")
a = 0
finally:
connection.close()
return a
def SQLtestsechs(data):
print(data)
connection = pymysql.connect(
host='10.0.1.123',
user='hubobel',
password='polier2003',
database='hubobel',
charset='utf8mb4',
cursorclass=pymysql.cursors.Cursor
)
try:
with connection.cursor() as cursor:
# Beispielwerte
z1, z2, z3, z4, z5, z6 = data['Z1'], data['Z2'],data['Z3'],data['Z4'],data['Z5'],data['Z6']
sql_check = """
SELECT 1 FROM `6aus49`
WHERE z1 = %s AND z2 = %s AND z3 = %s AND z4 = %s AND z5 = %s AND z6 = %s
LIMIT 1
"""
cursor.execute(sql_check, (z1, z2, z3, z4, z5, z6))
exists = cursor.fetchone() is not None
if exists:
print("✅ Kombination existiert bereits.")
a = 1
else:
print("🆕 Kombination ist neu kann eingefügt werden.")
a = 0
finally:
connection.close()
return a
passw = conf()
telegram_chat_id = passw['Telegram']['Chat_ID']
telegram_token = passw['Telegram']['TOKEN']
wochentag = datetime.today().weekday()
#wochentag = 4
#wochentag = 2
if wochentag == 2:
Zahl = Normalziehung(582)
test = SQLtestsechs(Zahl)
SQLnorm(Zahl)
SQLmittwoch(Zahl)
notify_telegram(str(Zahl))
elif wochentag == 5:
Zahl = Normalziehung(581)
test = SQLtestsechs(Zahl)
SQLnorm(Zahl)
SQLsamstag(Zahl)
notify_telegram(str(Zahl))
elif wochentag == 1:
Zahl = Euro()
test = SQLtesteuro(Zahl['Dienstag'])
SQLdienstag(Zahl['Dienstag'])
notify_telegram(str(Zahl['Dienstag']))
elif wochentag == 4:
Zahl = Euro()
test = SQLtesteuro(Zahl['Freitag'])
SQLfreitag(Zahl['Freitag'])
notify_telegram(str(Zahl['Freitag']))
else:
quit()

Binary file not shown.

Before

Width:  |  Height:  |  Size: 413 KiB