SC Yazılım olarak, 10 yılı aşkın süredir işletmelere dijital pazarlama, SEO ve marka yönetimi alanlarında sonuç odaklı çözümler sunuyoruz.

LATEST NEWS
iletişim
import io import os import re import tempfile import time from datetime import datetime from pathlib import Path from typing import Any import pythoncom import requests import win32com.client import xlsxwriter from bs4 import BeautifulSoup from flask import Flask, jsonify, render_template_string, request, send_file app = Flask(__name__) SOURCE_PAGE = “https://www.istanbuleczaciodasi.org.tr/nobetci-eczane/” SOURCE_API = “https://www.istanbuleczaciodasi.org.tr/nobetci-eczane/index.php” CACHE_SECONDS = 900 cache: dict[str, tuple[float, list[dict[str, Any]]]] = {} ILCELER = [ “Adalar”, “Arnavutköy”, “Ataşehir”, “Avcılar”, “Bağcılar”, “Bahçelievler”, “Bakırköy”, “Başakşehir”, “Bayrampaşa”, “Beşiktaş”, “Beykoz”, “Beylikdüzü”, “Beyoğlu”, “Büyükçekmece”, “Çatalca”, “Çekmeköy”, “Esenler”, “Esenyurt”, “Eyüpsultan”, “Fatih”, “Gaziosmanpaşa”, “Güngören”, “Kadıköy”, “Kağıthane”, “Kartal”, “Küçükçekmece”, “Maltepe”, “Pendik”, “Sancaktepe”, “Sarıyer”, “Silivri”, “Şile”, “Şişli”, “Sultanbeyli”, “Sultangazi”, “Tuzla”, “Ümraniye”, “Üsküdar”, “Zeytinburnu” ] AH_ISTANBUL_ILCELERI = [ “Bağcılar”, “Bahçelievler”, “Bakırköy”, “Başakşehir”, “Bayrampaşa”, “Esenler”, “Fatih”, “Güngören”, “Küçükçekmece”, “Zeytinburnu” ] HEADERS = { “User-Agent”: ( “Mozilla/5.0 (Windows NT 10.0; Win64; x64) ” “AppleWebKit/537.36 (KHTML, like Gecko) ” “Chrome/150.0.0.0 Safari/537.36” ), “Accept-Language”: “tr-TR,tr;q=0.9” } def html_temizle(value: Any) -> str: if value is None: return “” soup = BeautifulSoup(str(value), “html.parser”) text = soup.get_text(” “, strip=True) text = re.sub(r”^(Adres|Tarif)\s*:\s*”, “”, text, flags=re.IGNORECASE) return re.sub(r”\s+”, ” “, text).strip() def telefon_temizle(value: Any) -> str: return re.sub(r”[^0-9+]”, “”, str(value or “”)) def token_al(session: requests.Session) -> str: response = session.get(SOURCE_PAGE, headers=HEADERS, timeout=30) response.raise_for_status() soup = BeautifulSoup(response.text, “html.parser”) token_input = soup.find(“input”, {“name”: “h”}) if token_input and token_input.get(“value”): return str(token_input[“value”]) patterns = [ r’name=[“\’]h[“\’][^>]*value=[“\’]([^”\’]+)[“\’]’, r’value=[“\’]([^”\’]+)[“\’][^>]*name=[“\’]h[“\’]’ ] for pattern in patterns: match = re.search(pattern, response.text) if match: return match.group(1) raise RuntimeError(“Kaynak sayfadaki güvenlik değeri bulunamadı.”) def eczaneleri_getir(ilce: str) -> list[dict[str, Any]]: key = ilce.casefold() now = time.time() if key in cache: cached_time, cached_data = cache[key] if now – cached_time < CACHE_SECONDS: return cached_data session = requests.Session() session.headers.update(HEADERS) token = token_al(session) response = session.post( SOURCE_API, data={ "jx": "1", "islem": "get_ilce_eczane", "ilce": ilce, "h": token }, headers={ "Accept": "application/json, text/javascript, */*; q=0.01", "X-Requested-With": "XMLHttpRequest", "Referer": SOURCE_PAGE, "Origin": "https://www.istanbuleczaciodasi.org.tr" }, timeout=30 ) response.raise_for_status() try: result = response.json() except ValueError as exc: raise RuntimeError("Kaynak site JSON yanıtı döndürmedi.") from exc records = result.get("eczaneler", []) if not isinstance(records, list): raise RuntimeError("Eczane listesi alınamadı.") cleaned = [] for item in records: cleaned.append({ "sicil": html_temizle(item.get("sicil", "")), "eczane_ad": html_temizle(item.get("eczane_ad", "")), "eczane_tel": telefon_temizle(item.get("eczane_tel", "")), "adres": html_temizle(item.get("adres", "")), "tarif": html_temizle(item.get("tarif", "")), "lat": html_temizle(item.get("lat", "")), "lng": html_temizle(item.get("lng", "")), "nobet_bitis": html_temizle(item.get("nobet_bitis", "")) }) cache[key] = (now, cleaned) return cleaned def secili_ilceleri_al_json() -> list[str]: body = request.get_json(silent=True) or {} selected = body.get(“ilceler”, []) return [x for x in selected if x in ILCELER] def secili_ilceleri_al_query() -> list[str]: selected = request.args.getlist(“ilce”) return [x for x in selected if x in ILCELER] def tum_verileri_getir(ilceler: list[str]) -> list[dict[str, Any]]: rows = [] for ilce in ilceler: for pharmacy in eczaneleri_getir(ilce): rows.append({“ilce”: ilce, **pharmacy}) return rows def excel_olustur(ilceler: list[str]) -> tuple[bytes, str]: rows = tum_verileri_getir(ilceler) if not rows: raise RuntimeError(“Excel’e aktarılacak kayıt bulunamadı.”) output = io.BytesIO() workbook = xlsxwriter.Workbook(output, {“in_memory”: True}) worksheet = workbook.add_worksheet(“Nöbetçi Eczaneler”) title_format = workbook.add_format({ “bold”: True, “font_size”: 18, “font_color”: “#FFFFFF”, “bg_color”: “#087A55”, “align”: “center”, “valign”: “vcenter” }) info_format = workbook.add_format({ “bold”: True, “bg_color”: “#D1FAE5” }) header_format = workbook.add_format({ “bold”: True, “font_color”: “#FFFFFF”, “bg_color”: “#0F766E”, “border”: 1, “align”: “center”, “valign”: “vcenter”, “text_wrap”: True }) cell_format = workbook.add_format({ “border”: 1, “valign”: “top”, “text_wrap”: True }) center_format = workbook.add_format({ “border”: 1, “align”: “center”, “valign”: “top”, “text_wrap”: True }) today = datetime.now().strftime(“%d.%m.%Y”) file_date = datetime.now().strftime(“%Y-%m-%d”) worksheet.merge_range(“A1:H1”, “İSTANBUL NÖBETÇİ ECZANELER”, title_format) worksheet.merge_range(“A2:D2″, f”Tarih: {today}”, info_format) worksheet.merge_range(“E2:H2”, “Seçilen ilçeler: ” + “, “.join(ilceler), info_format) headers = [ “Sıra”, “İlçe”, “Sicil”, “Eczane Adı”, “Telefon”, “Adres”, “Tarif”, “Nöbet Bitişi” ] for col, name in enumerate(headers): worksheet.write(3, col, name, header_format) for row_index, item in enumerate(rows, start=4): worksheet.write(row_index, 0, row_index – 3, center_format) worksheet.write(row_index, 1, item[“ilce”], center_format) worksheet.write_string(row_index, 2, item.get(“sicil”, “”), center_format) worksheet.write(row_index, 3, item.get(“eczane_ad”, “”), cell_format) worksheet.write_string(row_index, 4, item.get(“eczane_tel”, “”), center_format) worksheet.write(row_index, 5, item.get(“adres”, “”), cell_format) worksheet.write(row_index, 6, item.get(“tarif”, “”), cell_format) worksheet.write(row_index, 7, item.get(“nobet_bitis”, “”) or “-“, center_format) worksheet.set_column(“A:A”, 7) worksheet.set_column(“B:B”, 17) worksheet.set_column(“C:C”, 12) worksheet.set_column(“D:D”, 28) worksheet.set_column(“E:E”, 17) worksheet.set_column(“F:G”, 45) worksheet.set_column(“H:H”, 18) worksheet.freeze_panes(4, 0) worksheet.autofilter(3, 0, 3 + len(rows), 7) worksheet.set_landscape() worksheet.set_paper(9) worksheet.fit_to_pages(1, 0) worksheet.repeat_rows(0, 3) workbook.close() output.seek(0) filename = f”istanbul_nobetci_eczaneler_{file_date}.xlsx” return output.getvalue(), filename def outlook_taslagi_ac(excel_bytes: bytes, filename: str) -> None: temp_dir = Path(tempfile.gettempdir()) / “NobetciEczane” temp_dir.mkdir(parents=True, exist_ok=True) attachment_path = temp_dir / filename attachment_path.write_bytes(excel_bytes) pythoncom.CoInitialize() try: try: outlook = win32com.client.GetActiveObject(“Outlook.Application”) except Exception: outlook = win32com.client.Dispatch(“Outlook.Application”) mail = outlook.CreateItem(0) mail.To = “” mail.CC = “” mail.Subject = ( “İstanbul Nöbetçi Eczaneler – ” + datetime.now().strftime(“%d.%m.%Y”) ) mail.Body = ( “Merhaba,\r\n\r\n” “Güncel nöbetçi eczane listesi ekte yer almaktadır.\r\n\r\n” “İyi çalışmalar.” ) mail.Attachments.Add(str(attachment_path.resolve())) mail.Display(False) finally: pythoncom.CoUninitialize() @app.get(“/api/eczaneler”) def api_eczaneler(): ilceler = secili_ilceleri_al_query() if not ilceler: ilceler = [“Ataşehir”] results = [] for ilce in ilceler: pharmacies = eczaneleri_getir(ilce) results.append({ “ilce”: ilce, “adet”: len(pharmacies), “eczaneler”: pharmacies }) return jsonify({ “success”: True, “tarih”: datetime.now().strftime(“%d.%m.%Y”), “toplam_adet”: sum(x[“adet”] for x in results), “sonuclar”: results }) @app.get(“/excel”) def excel_indir(): ilceler = secili_ilceleri_al_query() if not ilceler: return jsonify({ “success”: False, “message”: “En az bir ilçe seçmelisiniz.” }), 400 excel_bytes, filename = excel_olustur(ilceler) return send_file( io.BytesIO(excel_bytes), as_attachment=True, download_name=filename, mimetype=( “application/vnd.openxmlformats-officedocument.” “spreadsheetml.sheet” ) ) @app.post(“/outlook-hazirla”) def outlook_hazirla(): ilceler = secili_ilceleri_al_json() if not ilceler: return jsonify({ “success”: False, “message”: “En az bir ilçe seçmelisiniz.” }), 400 try: excel_bytes, filename = excel_olustur(ilceler) outlook_taslagi_ac(excel_bytes, filename) return jsonify({ “success”: True, “message”: ( “Outlook taslağı açıldı. ” “Alıcıları ekleyip Gönder’e basabilirsiniz.” ) }) except Exception as exc: return jsonify({ “success”: False, “message”: ( “Outlook açılamadı. Klasik Outlook kurulu ve açık olmalı. ” f”Detay: {exc}” ) }), 500 PAGE = r””” İstanbul Nöbetçi Eczaneler

İstanbul Nöbetçi Eczaneler

{% for ilce in ilceler %} {% endfor %}
“”” @app.get(“/”) def home(): return render_template_string(PAGE, ilceler=ILCELER) if __name__ == “__main__”: app.run(host=”0.0.0.0″, port=5000, debug=False)