from pathlib import Path import zipfile, html, re, unicodedata from datetime import date root = Path("/mnt/data/ankara-nigde-yol-yardim-site") assets = root / "assets" regions_dir = root / "bolgeler" assets.mkdir(parents=True, exist_ok=True) regions_dir.mkdir(parents=True, exist_ok=True) DOMAIN = "https://www.ankaranigdearasiyolyardim.com" PHONE_DISPLAY = "0 (5XX) XXX XX XX" PHONE_TEL = "+905XXXXXXXXX" WHATSAPP = "905XXXXXXXXX" BRAND = "Ankara–Niğde Arası Yol Yardım" regions = [ {"province": "Ankara", "district": "Gölbaşı", "route": "Ankara–Niğde Otoyolu başlangıç bağlantısı"}, {"province": "Ankara", "district": "Bala", "route": "Ankara–Niğde Otoyolu ve çevre yolları"}, {"province": "Ankara", "district": "Şereflikoçhisar", "route": "Ankara–Niğde güzergâhı ve Tuz Gölü çevresi"}, {"province": "Ankara", "district": "Evren", "route": "Evren bağlantısı ve çevre yolları"}, {"province": "Konya", "district": "Kulu", "route": "Kulu bağlantısı ve Ankara–Niğde güzergâhı"}, {"province": "Kırşehir", "district": "Merkez", "route": "Kırşehir bağlantı yolu ve çevresi"}, {"province": "Aksaray", "district": "Ortaköy", "route": "Ortaköy bağlantısı ve otoyol çevresi"}, {"province": "Aksaray", "district": "Sarıyahşi", "route": "Sarıyahşi bağlantısı ve çevre yolları"}, {"province": "Aksaray", "district": "Gülağaç", "route": "Gülağaç bağlantısı ve çevre yolları"}, {"province": "Aksaray", "district": "Ağaçören", "route": "Ağaçören bağlantısı ve çevre yolları"}, {"province": "Aksaray", "district": "Merkez", "route": "Aksaray merkez, çevre yolu ve otoyol bağlantıları"}, {"province": "Nevşehir", "district": "Acıgöl", "route": "Acıgöl bağlantısı ve çevre yolları"}, {"province": "Nevşehir", "district": "Derinkuyu", "route": "Derinkuyu bağlantısı ve çevre yolları"}, {"province": "Niğde", "district": "Merkez", "route": "Niğde merkez ve Ankara–Niğde Otoyolu çıkışları"}, ] def slugify(text): mapping = str.maketrans("çğıöşüÇĞİÖŞÜ", "cgiosuCGIOSU") t = text.translate(mapping).lower() t = re.sub(r"[^a-z0-9]+", "-", t).strip("-") return t for r in regions: suffix = "" if r["district"] != "Merkez" else "-merkez" r["slug"] = f"{slugify(r['province'])}-{slugify(r['district'])}{suffix if slugify(r['province']) != slugify(r['district']) else ''}" # cleaner special cases if r["province"] == "Kırşehir" and r["district"] == "Merkez": r["slug"] = "kirsehir-merkez" if r["province"] == "Aksaray" and r["district"] == "Merkez": r["slug"] = "aksaray-merkez" if r["province"] == "Niğde" and r["district"] == "Merkez": r["slug"] = "nigde-merkez" css = r""" :root{ --bg:#07111f;--panel:#0e1c30;--panel2:#132640;--text:#f6f8fc; --muted:#aab7ca;--accent:#f7b800;--accent2:#ff7900;--line:rgba(255,255,255,.11); --green:#20c866;--shadow:0 24px 70px rgba(0,0,0,.30);--radius:22px } *{box-sizing:border-box} html{scroll-behavior:smooth} body{margin:0;font-family:Inter,ui-sans-serif,system-ui,-apple-system,"Segoe UI",sans-serif;color:var(--text); background:radial-gradient(circle at 10% 5%,rgba(247,184,0,.13),transparent 28rem), linear-gradient(180deg,#07101d,#0a1524);line-height:1.62} a{color:inherit;text-decoration:none}.container{width:min(1160px,calc(100% - 32px));margin:auto} .topbar{position:sticky;top:0;z-index:50;background:rgba(5,12,22,.90);backdrop-filter:blur(16px);border-bottom:1px solid var(--line)} .nav{min-height:74px;display:flex;align-items:center;justify-content:space-between;gap:20px} .brand{display:flex;align-items:center;gap:12px;font-weight:900;letter-spacing:-.03em} .brand-mark{width:46px;height:46px;border-radius:14px;display:grid;place-items:center;color:#101010; background:linear-gradient(135deg,var(--accent),var(--accent2));box-shadow:0 12px 28px rgba(247,184,0,.22)} .brand small{display:block;color:var(--muted);font-size:.7rem;letter-spacing:.08em;text-transform:uppercase} .navlinks{display:flex;gap:22px;font-weight:750;color:#dce5f2}.navlinks a:hover{color:var(--accent)} .btn{display:inline-flex;align-items:center;justify-content:center;gap:8px;min-height:48px;padding:0 20px;border-radius:14px; font-weight:900;border:1px solid transparent;transition:.2s} .btn:hover{transform:translateY(-2px)}.primary{color:#111;background:linear-gradient(135deg,var(--accent),var(--accent2))} .outline{border-color:var(--line);background:rgba(255,255,255,.04)}.whatsapp{background:var(--green);color:#06140b} .hero{padding:88px 0 64px;overflow:hidden}.hero-grid{display:grid;grid-template-columns:1.05fr .95fr;gap:48px;align-items:center} .eyebrow{display:inline-flex;align-items:center;gap:8px;padding:8px 12px;border-radius:999px;background:rgba(247,184,0,.10); border:1px solid rgba(247,184,0,.30);color:#ffd65c;font-weight:900;font-size:.82rem;letter-spacing:.05em;text-transform:uppercase} .dot{width:9px;height:9px;border-radius:50%;background:var(--accent);box-shadow:0 0 0 8px rgba(247,184,0,.10)} h1{font-size:clamp(2.7rem,6.6vw,5.8rem);line-height:.96;letter-spacing:-.065em;margin:22px 0 18px} h1 span{display:block;color:var(--accent)}.lead{font-size:clamp(1.02rem,1.7vw,1.22rem);color:var(--muted);max-width:720px} .actions{display:flex;flex-wrap:wrap;gap:12px;margin-top:30px} .stats{display:grid;grid-template-columns:repeat(3,1fr);gap:12px;margin-top:34px} .stat{padding:16px;border:1px solid var(--line);border-radius:16px;background:rgba(255,255,255,.035)} .stat strong{display:block;font-size:1.12rem}.stat span{color:var(--muted);font-size:.87rem} .visual{min-height:520px;border-radius:32px;border:1px solid var(--line);background: linear-gradient(155deg,rgba(247,184,0,.22),transparent 36%),linear-gradient(180deg,#172a46,#0a1729); box-shadow:var(--shadow);position:relative;overflow:hidden} .road{position:absolute;width:180%;height:260px;left:-40%;bottom:40px;background:#111b29;transform:rotate(-8deg); border-block:2px solid rgba(255,255,255,.08)}.road:after{content:"";position:absolute;left:0;right:0;top:50%; height:8px;background:repeating-linear-gradient(90deg,#e6c450 0 40px,transparent 40px 80px)} .truck{position:absolute;left:10%;right:10%;bottom:132px;filter:drop-shadow(0 24px 20px rgba(0,0,0,.35))} .badge{position:absolute;top:20px;right:20px;padding:14px 16px;border:1px solid var(--line);border-radius:16px; background:rgba(5,12,22,.78);backdrop-filter:blur(12px)}.badge strong{display:block} .routechip{position:absolute;left:20px;bottom:18px;right:20px;padding:14px 16px;border-radius:16px;border:1px solid var(--line); background:rgba(5,12,22,.82);backdrop-filter:blur(12px)} .section{padding:82px 0}.section-head{max-width:760px;margin-bottom:32px}.section-head h2,.page-head h1{ font-size:clamp(2.15rem,4.5vw,3.8rem);line-height:1.04;letter-spacing:-.05em;margin:12px 0} .section-head p,.page-head p{color:var(--muted)} .grid3{display:grid;grid-template-columns:repeat(3,1fr);gap:18px}.grid2{display:grid;grid-template-columns:repeat(2,1fr);gap:18px} .card{padding:26px;border:1px solid var(--line);border-radius:var(--radius);background:linear-gradient(180deg,rgba(255,255,255,.055),rgba(255,255,255,.025))} .card h3{margin:0 0 8px}.card p{margin:0;color:var(--muted)}.icon{width:50px;height:50px;border-radius:15px; display:grid;place-items:center;margin-bottom:18px;background:linear-gradient(135deg,var(--accent),var(--accent2));color:#111;font-size:1.3rem} .region-groups{display:grid;gap:18px}.province{border:1px solid var(--line);background:var(--panel);border-radius:24px;padding:24px} .province h3{margin:0 0 15px;font-size:1.5rem}.chips{display:flex;flex-wrap:wrap;gap:10px} .chip{padding:11px 14px;border:1px solid var(--line);border-radius:999px;background:rgba(255,255,255,.04);font-weight:760} .chip:hover{border-color:rgba(247,184,0,.65);color:var(--accent)} .steps{display:grid;grid-template-columns:repeat(4,1fr);gap:16px;counter-reset:n} .step{padding:24px;border:1px solid var(--line);border-radius:20px;background:var(--panel);counter-increment:n} .step:before{content:"0" counter(n);display:block;color:var(--accent);font-weight:900;margin-bottom:28px}.step p{color:var(--muted);margin-bottom:0} .cta{padding:38px;border-radius:30px;background:linear-gradient(135deg,var(--accent),var(--accent2));color:#111; display:flex;align-items:center;justify-content:space-between;gap:24px;box-shadow:0 24px 65px rgba(247,184,0,.18)} .cta h2{font-size:clamp(2rem,4vw,3.2rem);line-height:1;margin:0 0 9px;letter-spacing:-.05em}.cta p{margin:0;font-weight:650} .cta .btn{background:#091424;color:white;min-width:210px} .page-head{padding:74px 0 40px}.breadcrumb{font-size:.9rem;color:var(--muted)}.breadcrumb a{color:var(--accent)} .info-layout{display:grid;grid-template-columns:1.1fr .9fr;gap:22px}.info-box{padding:28px;border:1px solid var(--line);border-radius:24px;background:var(--panel)} .checks{display:grid;gap:10px;margin:18px 0 0}.check{padding:12px 14px;border-radius:14px;background:rgba(255,255,255,.04);border:1px solid var(--line)} footer{padding:50px 0 105px;color:var(--muted)}.footer-grid{padding-top:28px;border-top:1px solid var(--line);display:grid; grid-template-columns:1.4fr .8fr .8fr;gap:30px}footer h4{color:white;margin:0 0 10px}footer a{display:block;margin:7px 0} .mobilebar{display:none;position:fixed;left:12px;right:12px;bottom:12px;z-index:100;gap:10px;padding:10px;border-radius:18px; background:rgba(5,12,22,.94);border:1px solid var(--line);backdrop-filter:blur(15px)}.mobilebar .btn{flex:1;padding:0 10px} .notice{padding:14px 16px;border-left:4px solid var(--accent);background:rgba(247,184,0,.08);border-radius:10px;color:#e7edf6} @media(max-width:920px){.navlinks{display:none}.hero-grid,.info-layout{grid-template-columns:1fr}.grid3{grid-template-columns:repeat(2,1fr)} .steps{grid-template-columns:repeat(2,1fr)}.visual{min-height:440px}.footer-grid{grid-template-columns:1fr 1fr}} @media(max-width:640px){.container{width:min(100% - 22px,1160px)}.nav>.primary{display:none}.hero{padding:45px 0}.visual{min-height:370px} .truck{left:3%;right:3%;bottom:112px}.stats,.grid3,.grid2,.steps,.footer-grid{grid-template-columns:1fr}.section{padding:62px 0} .cta{flex-direction:column;align-items:flex-start;padding:28px}.cta .btn{width:100%}.mobilebar{display:flex}} """ js = """document.querySelectorAll('[data-year]').forEach(el=>el.textContent=new Date().getFullYear());""" def truck_svg(): return """ """ def header(active=""): return f"""
""" def footer(): return f"""
📞 Ara💬 WhatsApp
""" def html_doc(title, description, canonical, body, schema=None): schema_tag = f'' if schema else "" return f""" {html.escape(title)} {schema_tag}{body}""" schema_main = f"""{{ "@context":"https://schema.org","@type":"TowingService","name":"{BRAND}", "url":"{DOMAIN}","telephone":"{PHONE_TEL}","openingHours":"Mo-Su 00:00-23:59", "description":"Ankara–Niğde Otoyolu ve bağlantı yollarında 7/24 oto kurtarma ve çekici hizmeti.", "areaServed":["Ankara","Konya","Kırşehir","Aksaray","Nevşehir","Niğde"] }}""" # Grouped region links groups = {} for r in regions: groups.setdefault(r["province"], []).append(r) groups_html = "" for province, items in groups.items(): chips = "".join(f'{r["district"]}' for r in items) groups_html += f'

{province}

{chips}
' index_body = header() + f"""
Ankara–Niğde Otoyolu 7/24 Destek

Ankara'dan Niğde'ye yolda yanınızdayız.

Ankara–Niğde Otoyolu, bağlantı yolları ve güzergâhtaki ilçe merkezlerinde oto kurtarma, çekici, akü takviyesi, lastik değişimi ve araç taşıma desteği.

7/24Kesintisiz destek
6 İlGeniş hizmet ağı
14 BölgeOtoyol ve bağlantılar
Ankara ⇄ NiğdeOtoyol ve bağlantı yolları
{truck_svg()}
📍 Konumunuzu WhatsApp'tan gönderin
Bulunduğunuz bölgeye uygun ekip yönlendirilsin.
Hizmetlerimiz

Her yol durumuna uygun çözüm

Aracın durumuna göre uygun ekipman ve güvenli taşıma yöntemiyle destek sağlıyoruz.

🚚

Oto Kurtarma

Arızalı veya kazalı aracın bulunduğu noktadan güvenli alınması.

🛻

Çekici

Otomobil ve hafif ticari araçlar için şehir içi ve güzergâh çekici desteği.

🔋

Akü Takviyesi

Aküsü biten araçlara yerinde ilk çalıştırma desteği.

🛞

Lastik Değişimi

Patlak lastik ve stepne değişimi için yerinde destek.

Yakıt Desteği

Yakıtı biten araçlara uygun koşullarda acil destek.

🛣️

Araç Taşıma

Şehirlerarası ve planlı araç taşıma çözümleri.

Hizmet Bölgeleri

Ankara–Niğde güzergâhındaki il ve ilçeler

Otoyol güzergâhı ve bağlantı yollarına göre hazırlanan bölgesel hizmet sayfaları.

{groups_html}
Nasıl Çalışır?

Dört adımda hızlı destek

Bizi arayın

Telefon veya WhatsApp üzerinden ulaşın.

Konum gönderin

Otoyol kilometresi, gişe veya yakın konumu paylaşın.

Ekip yönlensin

Uygun araç ve ekip bölgeye hareket etsin.

Güvenle tamamlayalım

Aracınızı uygun noktaya güvenle ulaştıralım.

Yolda mı kaldınız?

Konumunuzu paylaşın; Ankara–Niğde güzergâhındaki bulunduğunuz bölge için hızlıca yönlendirme yapalım.

📞 Hemen Ara
""" + footer() (root / "index.html").write_text( html_doc( "Ankara Niğde Arası Yol Yardım | 7/24 Oto Kurtarma ve Çekici", "Ankara–Niğde Otoyolu ve bağlantı yollarında 7/24 oto kurtarma, çekici, akü takviyesi, lastik değişimi ve araç taşıma hizmeti.", DOMAIN + "/", index_body, schema_main, ), encoding="utf-8", ) services_body = header() + f"""
7/24 Yol Yardım

Oto kurtarma ve yol yardım hizmetleri

Ankara–Niğde güzergâhında araç arızası, kaza veya acil yol yardım ihtiyaçları için sunulan hizmetler.

🚚

Oto Kurtarma

Arızalı veya kazalı aracın güvenli biçimde kurtarılması ve taşınması.

🛻

Çekici Hizmeti

Otomobil ve hafif ticari araçlar için çekici desteği.

🔋

Akü Takviyesi

Aküsü biten araçlara uygun ekipmanla yerinde takviye.

🛞

Lastik Değişimi

Patlak lastik ve stepne değişimi için yerinde yardım.

Yakıt Desteği

Yakıt bitmesi durumunda uygun koşullarda acil destek.

🛣️

Şehirlerarası Taşıma

Planlı veya acil araç taşıma ihtiyaçlarına güvenli çözüm.

Konumunuzu gönderin

Bulunduğunuz gişeyi, kilometreyi veya en yakın yerleşim yerini WhatsApp üzerinden paylaşın.

WhatsApp
""" + footer() (root / "hizmetler.html").write_text(html_doc( "Yol Yardım Hizmetleri | Ankara Niğde Oto Kurtarma", "Ankara–Niğde güzergâhında oto kurtarma, çekici, akü takviyesi, lastik değişimi, yakıt desteği ve araç taşıma hizmetleri.", DOMAIN + "/hizmetler.html", services_body, schema_main), encoding="utf-8") regions_body = header() + f"""
6 İl • 14 Bölge

Ankara–Niğde yol yardım bölgeleri

Resmî otoyol güzergâhı ve bağlantı yolları boyunca hazırlanan ilçe bazlı hizmet sayfaları.

{groups_html}
Hizmet talebinde bulunurken bulunduğunuz gişeyi, kilometreyi, yönü ve en yakın yerleşim yerini paylaşmanız yönlendirmeyi kolaylaştırır.
""" + footer() (root / "bolgeler.html").write_text(html_doc( "Hizmet Bölgeleri | Ankara Niğde Arası Yol Yardım", "Ankara, Konya, Kırşehir, Aksaray, Nevşehir ve Niğde güzergâhındaki yol yardım ve çekici hizmet bölgeleri.", DOMAIN + "/bolgeler.html", regions_body, schema_main), encoding="utf-8") contact_body = header() + f"""
7 Gün 24 Saat

Yol yardım için hemen ulaşın

Konumunuzu, araç türünü ve arıza durumunu paylaşarak hızlı yönlendirme talep edin.

Telefon

{PHONE_DISPLAY}

Gönderilecek bilgiler

✓ Canlı konum veya otoyol kilometresi
✓ Ankara/Niğde yönü
✓ Araç marka ve modeli
✓ Arıza veya kaza durumu
""" + footer() (root / "iletisim.html").write_text(html_doc( "İletişim | Ankara Niğde Yol Yardım", "Ankara–Niğde güzergâhında 7/24 yol yardım ve çekici hizmeti için telefon veya WhatsApp üzerinden ulaşın.", DOMAIN + "/iletisim.html", contact_body, schema_main), encoding="utf-8") # Unique regional pages service_items = ["7/24 oto kurtarma", "çekici hizmeti", "akü takviyesi", "lastik değişimi", "yakıt desteği", "araç taşıma"] for r in regions: title_loc = f"{r['district']} Yol Yardım ve Çekici" if r["district"] == "Merkez": title_loc = f"{r['province']} Merkez Yol Yardım ve Çekici" loc_name = f"{r['district']}, {r['province']}" if r["district"] != "Merkez" else f"{r['province']} Merkez" canonical = f"{DOMAIN}/bolgeler/{r['slug']}.html" desc = f"{loc_name} ve {r['route']} çevresinde 7/24 oto kurtarma, çekici, akü takviyesi ve yol yardım hizmeti." schema = f"""{{ "@context":"https://schema.org","@type":"TowingService","name":"{title_loc}", "url":"{canonical}","telephone":"{PHONE_TEL}","openingHours":"Mo-Su 00:00-23:59", "description":"{desc}","areaServed":{{"@type":"AdministrativeArea","name":"{loc_name}"}} }}""" cards = "".join(f'
✓ {s.title()}
' for s in service_items) body = header() + f"""
7/24 Bölgesel Destek

{html.escape(title_loc)}

{html.escape(desc)}

{html.escape(loc_name)} bölgesinde yol yardım

{html.escape(r['route'])} üzerinde aracınız arızalandığında veya kaza durumunda, bulunduğunuz konumu ve araç bilgilerini paylaşarak destek talep edebilirsiniz.

Konum bildirirken otoyol kilometresi, gişe adı, sürüş yönü ve yakınınızdaki tesis veya kavşak bilgisini eklemeniz doğru yönlendirmeyi kolaylaştırır.

Güvenliğiniz için mümkünse aracı emniyet şeridine alın, dörtlüleri yakın ve reflektör yerleştirin.

Sunulan hizmetler

{cards}

{html.escape(loc_name)} için yardım alın

Telefonla arayın veya WhatsApp üzerinden canlı konumunuzu gönderin.

Hemen Ara
""" + footer() (regions_dir / f"{r['slug']}.html").write_text( html_doc(f"{title_loc} | 7/24 Oto Kurtarma", desc, canonical, body, schema), encoding="utf-8" ) (assets / "styles.css").write_text(css, encoding="utf-8") (assets / "script.js").write_text(js, encoding="utf-8") # robots.txt and sitemap.xml urls = [ DOMAIN + "/", DOMAIN + "/hizmetler.html", DOMAIN + "/bolgeler.html", DOMAIN + "/iletisim.html", ] + [f"{DOMAIN}/bolgeler/{r['slug']}.html" for r in regions] sitemap = ['', ''] for u in urls: sitemap.append(f"{u}{date.today().isoformat()}") sitemap.append("") (root / "sitemap.xml").write_text("\n".join(sitemap), encoding="utf-8") (root / "robots.txt").write_text(f"User-agent: *\nAllow: /\nSitemap: {DOMAIN}/sitemap.xml\n", encoding="utf-8") readme = f"""ANKARA–NİĞDE ARASI YOL YARDIM SİTESİ DOSYALAR - index.html: Ana sayfa - hizmetler.html: Hizmetler - bolgeler.html: Tüm il ve ilçeler - iletisim.html: İletişim - bolgeler/: 14 ayrı bölge SEO sayfası - sitemap.xml: Google site haritası - robots.txt: Arama motoru tarama dosyası - assets/: CSS ve JavaScript YAYINLAMA 1. ZIP içindeki tüm dosya ve klasörleri hosting hesabındaki public_html klasörüne yükleyin. 2. Dosya yapısını bozmadan yükleyin. 3. Ücretsiz SSL'yi etkinleştirin. 4. Google Search Console'a domaini ekleyip sitemap.xml adresini gönderin. DEĞİŞTİRİLMESİ GEREKENLER - {PHONE_DISPLAY} - {PHONE_TEL} - {WHATSAPP} Telefon numarası tüm dosyalarda yer tutucu olarak bırakılmıştır. DOMAIN - Kodlar {DOMAIN} alan adına göre hazırlanmıştır. - Farklı domain alınırsa tüm dosyalarda bu adresi değiştirin. """ (root / "README.txt").write_text(readme, encoding="utf-8") zip_path = Path("/mnt/data/ankara-nigde-yol-yardim-site.zip") with zipfile.ZipFile(zip_path, "w", zipfile.ZIP_DEFLATED) as zf: for p in root.rglob("*"): if p.is_file(): zf.write(p, p.relative_to(root)) print(f"Site klasörü: {root}") print(f"ZIP: {zip_path}") print(f"Toplam HTML sayfası: {len(list(root.rglob('*.html')))}") print("Bölgeler:", ", ".join(f"{r['province']} {r['district']}" for r in regions))