🛠️ Google Maps'ten İşletme Verisi Çeken Ücretsiz Python Scripti
Firma adı · Telefon · Adres · Web sitesi · Puan · Fotoğraf → Excel & CSV
📌 Bu Script Ne Yapıyor?
Google Maps'te istediğiniz şehirde istediğiniz aramayı yapıp çıkan tüm işletmelerin;
- Firma adı
- Telefon numarası (05xxxxxxxxx formatında)
- Adres
- Web sitesi
- Google puanı ve yorum sayısı
- Çalışma saatleri
- Öne çıkan fotoğraf URL'si
- Google Maps linki
bilgilerini otomatik olarak
Excel (.xlsx) ve
CSV dosyasına kaydeder.
📋 KURULUM REHBERİ (Adım Adım) ADIM 1 — Python'u Kurun- python.org/downloads adresine gidin
- Büyük sarı "Download Python 3.x" butonuna tıklayın
- İndirilen .exe dosyasını çalıştırın
- ÖNEMLİ: Kurulum ekranında "Add Python to PATH" kutucuğunu işaretleyin!
ADIM 2 — Klasör Oluşturun
C: sürücüsünde
googlemap klasörü oluşturun →
C:googlemap
Ekteki
google_maps_scraper.py dosyasını bu klasöre koyun.
ADIM 3 — CMD'yi Açın- Dosya Gezgini'nde C:googlemap klasörüne girin
- Üstteki adres çubuğuna tıklayıp içini silin
- cmd yazıp Enter'a basın
ADIM 4 — Kütüphaneleri Kurun (Sadece 1 kez)
CMD'ye sırasıyla yapıştırın:
pip install playwright openpyxl
Bitmesini bekleyin, sonra:
python -m playwright install chromium
⏳ Bu komut ~150 MB indirir, 1-3 dakika sürebilir.
ADIM 5 — Ayarları Yapın google_maps_scraper.py dosyasına sağ tıklayın →
"Not Defteri ile Aç"
Dosyanın en üstündeki bu satırları düzenleyin:
ARAMA_TERIMI = "Beyaz esya tamircileri" # ← İstediğiniz aramayı yazın
SEHIR = "Ankara" # ← İstediğiniz şehri yazın
MAX_ISLETME = 50 # ← Kaç işletme çeksin?
Değiştirdikten sonra
Ctrl+S ile kaydedin.
ADIM 6 — Çalıştırın python google_maps_scraper.py
Otomatik bir tarayıcı açılır ve Google Maps'te arama yapılır. Siz sadece izleyin!
Bitince
C:googlemap klasöründe
isletmeler.xlsx ve
isletmeler.csv oluşur.
❓ Sık Sorulan Sorular Script hiçbir şey yazmadan kapandı?
CMD'de şunu deneyin:
python google_maps_scraper.py 2>&1 | more
Farklı şehir veya sektör?
AYARLAR bölümünden ARAMA_TERIMI ve SEHIR'i değiştirin, hepsi bu!
Kaç işletmeye kadar çeker?
Google Maps ~120 sonuç gösterir. MAX_ISLETME'yi 120'ye kadar artırabilirsiniz.
Ücretli bir şey var mı?
Hayır! Tamamen ücretsiz, API key gerektirmez.
"""
Google Maps Isletme Veri Toplayici v5
"""
import sys
import csv
import asyncio
import traceback
import re
if sys.platform == "win32":
asyncio.set_event_loop_policy(asyncio.WindowsProactorEventLoopPolicy())
# ============================================================
# AYARLAR
# ============================================================
ARAMA_TERIMI = "Beyaz Eşya Tamirhanesi"
SEHIR = "Ankara"
MAX_ISLETME = 10
CIKTI_DOSYA = "isletmeler"
# ============================================================
async def gorsel_url_al(page):
selectors = [
'button.aoRNLd img', 'div.RZ66Rb img',
'img.t0ejtc', 'div.ZKCDEc img', 'div.brR1M img',
]
for sel in selectors:
try:
el = await page.query_selector(sel)
if el:
src = await el.get_attribute("src")
if src and src.startswith("http") and "googleusercontent" in src:
src = re.sub(r'=w\d+-h\d+', '=w800-h600', src)
src = re.sub(r'=s\d+', '=s800', src)
return src
except:
pass
try:
imgs = await page.query_selector_all('img[src*="googleusercontent"]')
for img in imgs:
src = await img.get_attribute("src")
if src:
src = re.sub(r'=w\d+-h\d+', '=w800-h600', src)
return src
except:
pass
return ""
async def detay_cek(page):
veri = {}
# Firma Adı
for sel in ['h1.DUwDvf', 'h1.fontHeadlineLarge', 'h1']:
try:
ad = (await page.inner_text(sel, timeout=2000)).strip()
if ad:
veri["Firma Adi"] = ad
break
except:
pass
veri.setdefault("Firma Adi", "")
# Kategori
for sel in ['button.DkEaL', 'span.YkuOqf']:
try:
kat = (await page.inner_text(sel, timeout=1500)).strip()
if kat:
veri["Kategori"] = kat
break
except:
pass
veri.setdefault("Kategori", "")
# Puan
try:
el = await page.query_selector('span.ceNzKf[aria-label]')
lbl = await el.get_attribute("aria-label") if el else ""
m = re.search(r"[\d,\.]+", lbl or "")
veri["Puan"] = m.group().replace(",", ".") if m else ""
except:
try:
t = await page.inner_text('div.F7nice', timeout=1500)
m = re.search(r"[\d,\.]+", t)
veri["Puan"] = m.group().replace(",", ".") if m else ""
except:
veri["Puan"] = ""
# Yorum Sayısı
try:
el = await page.query_selector('span[aria-label*="yorum"], span[aria-label*="review"]')
lbl = await el.get_attribute("aria-label") if el else ""
m = re.search(r"\d[\d\.]*", lbl or "")
veri["Yorum Sayisi"] = m.group() if m else ""
except:
veri["Yorum Sayisi"] = ""
# ✅ ADRES — aria-label'dan al: "Adres: Başak, Karapürçek..."
try:
el = await page.query_selector('button[data-item-id="address"]')
if el:
lbl = await el.get_attribute("aria-label") or ""
# "Adres: " prefix'ini temizle
adres = re.sub(r'^Adres:\s*', '', lbl, flags=re.IGNORECASE).strip()
# Sondaki boşlukları temizle
veri["Adres"] = adres.rstrip()
else:
veri["Adres"] = ""
except:
veri["Adres"] = ""
# ✅ TELEFON — aria-label'dan al, sadece rakam bırak, 90 ile başlıyorsa 0'a çevir
try:
el = await page.query_selector('button[data-item-id^="phone:tel"]')
if el:
lbl = await el.get_attribute("aria-label") or ""
# Sadece rakamları al
tel = re.sub(r'\D', '', lbl)
# +90 veya 90 ile başlıyorsa → 0 ile başlat
if tel.startswith("90") and len(tel) == 12:
tel = "0" + tel[2:]
veri["Telefon"] = tel
else:
veri["Telefon"] = ""
except:
veri["Telefon"] = ""
# Web Sitesi
try:
el = await page.query_selector('a[data-item-id="authority"]')
veri["Web Sitesi"] = (await el.get_attribute("href")).strip() if el else ""
except:
veri["Web Sitesi"] = ""
# Çalışma Saatleri — aria-label'dan al: "24 saat açık·..."
try:
el = await page.query_selector('button[data-item-id="oh"]')
if el:
lbl = await el.get_attribute("aria-label") or ""
# Sadece ilk kısım (· sonrasını at)
veri["Calisma Saatleri"] = lbl.split("·")[0].strip()
else:
veri["Calisma Saatleri"] = ""
except:
veri["Calisma Saatleri"] = ""
# Google Maps Linki (kısa)
url = page.url
m = re.search(r"(https://www\.google\.com/maps/place/[^@]+/@[\d\.,]+)", url)
veri["Google Maps"] = m.group(1) if m else url.split("!")[0]
# Görsel URL
veri["Gorsel URL"] = await gorsel_url_al(page)
return veri
async def haritadan_veri_cek():
from playwright.async_api import async_playwright
isletmeler = []
sorgu = f"{ARAMA_TERIMI} {SEHIR}"
print("Tarayici baslatiliyor...")
async with async_playwright() as p:
browser = await p.chromium.launch(headless=False, args=["--no-sandbox"])
context = await browser.new_context(locale="tr-TR")
page = await context.new_page()
url = "https://www.google.com/maps/search/" + sorgu.replace(" ", "+")
print(f"Aciliyor: {url}")
await page.goto(url, wait_until="domcontentloaded", timeout=30000)
await page.wait_for_timeout(4000)
for btn_text in ["Tumunu kabul et", "Accept all", "Kabul et"]:
try:
await page.click(f'button:has-text("{btn_text}")', timeout=2000)
await page.wait_for_timeout(1000)
break
except:
pass
try:
await page.wait_for_selector('div[role="feed"]', timeout=15000)
except Exception as e:
print(f"HATA: Liste paneli bulunamadi - {e}")
await page.screenshot(path="hata_ekran.png")
await browser.close()
return []
print("Sonuclar yukleniyor...")
for i in range(MAX_ISLETME // 4 + 2):
await page.evaluate("""
const feed = document.querySelector('div[role="feed"]');
if (feed) feed.scrollTop += 2000;
""")
await page.wait_for_timeout(1000)
sys.stdout.write(f"\r Scroll {i+1}...")
sys.stdout.flush()
print()
kartlar = await page.query_selector_all('a.hfpxzc')
print(f"{len(kartlar)} isletme bulundu, detaylar cekiliyor...\n")
for i, kart in enumerate(kartlar[:MAX_ISLETME]):
try:
await kart.click()
await page.wait_for_timeout(3000)
veri = await detay_cek(page)
isletmeler.append(veri)
ad = veri.get("Firma Adi", "?")[:25]
tel = veri.get("Telefon", "") or "YOK"
adr = (veri.get("Adres", "") or "YOK")[:30]
img = "VAR" if veri.get("Gorsel URL") else "YOK"
print(f" [{i+1:02d}] {ad:<25} | Tel:{tel:<16} | Adres:{adr:<30} | Img:{img}")
except Exception as e:
print(f" [{i+1:02d}] Hata: {e}")
continue
await browser.close()
return isletmeler
def xlsx_kaydet(isletmeler, dosya):
try:
from openpyxl import Workbook
from openpyxl.styles import Font, PatternFill, Alignment, Border, Side
wb = Workbook()
ws = wb.active
ws.title = "Isletmeler"
basliklar = [
"Firma Adi", "Telefon", "Adres", "Web Sitesi",
"Kategori", "Puan", "Yorum Sayisi", "Calisma Saatleri",
"Google Maps", "Gorsel URL"
]
baslik_font = Font(name="Arial", bold=True, color="FFFFFF", size=11)
baslik_fill = PatternFill("solid", start_color="1A73E8")
kenar = Border(
left=Side(style="thin"), right=Side(style="thin"),
top=Side(style="thin"), bottom=Side(style="thin")
)
for col, b in enumerate(basliklar, 1):
c = ws.cell(row=1, column=col, value=b)
c.font = baslik_font
c.fill = baslik_fill
c.alignment = Alignment(horizontal="center", vertical="center")
c.border = kenar
ws.row_dimensions[1].height = 22
for satir, isletme in enumerate(isletmeler, 2):
renk = "EAF4FF" if satir % 2 == 0 else "FFFFFF"
for col, b in enumerate(basliklar, 1):
deger = isletme.get(b, "")
c = ws.cell(row=satir, column=col, value=deger)
c.font = Font(name="Arial", size=10)
c.fill = PatternFill("solid", start_color=renk)
c.alignment = Alignment(vertical="center", wrap_text=(b == "Adres"))
c.border = kenar
if b == "Gorsel URL" and deger and deger.startswith("http"):
c.hyperlink = deger
c.font = Font(name="Arial", size=10, color="0563C1", underline="single")
genislikler = [32, 18, 38, 28, 20, 7, 10, 18, 42, 18]
for col, g in enumerate(genislikler, 1):
ws.column_dimensions[ws.cell(row=1, column=col).column_letter].width = g
ws.freeze_panes = "A2"
path = f"{dosya}.xlsx"
wb.save(path)
print(f"XLSX kaydedildi: {path}")
except Exception as e:
print(f"XLSX hatasi: {e}")
traceback.print_exc()
def csv_kaydet(isletmeler, dosya):
try:
basliklar = [
"Firma Adi", "Telefon", "Adres", "Web Sitesi",
"Kategori", "Puan", "Yorum Sayisi", "Calisma Saatleri",
"Google Maps", "Gorsel URL"
]
path = f"{dosya}.csv"
with open(path, "w", newline="", encoding="utf-8-sig") as f:
w = csv.DictWriter(f, fieldnames=basliklar, extrasaction="ignore")
w.writeheader()
w.writerows(isletmeler)
print(f"CSV kaydedildi: {path}")
except Exception as e:
print(f"CSV hatasi: {e}")
def main():
print("=" * 60)
print(" Google Maps Scraper v5 - Telefon/Adres Duzeltildi")
print("=" * 60)
try:
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
isletmeler = loop.run_until_complete(haritadan_veri_cek())
loop.close()
except Exception as e:
print(f"\nKRITIK HATA: {e}")
traceback.print_exc()
input("\nEnter'a basin...")
return
if not isletmeler:
print("\nHic veri cekilemedi!")
input("\nEnter'a basin...")
return
xlsx_kaydet(isletmeler, CIKTI_DOSYA)
csv_kaydet(isletmeler, CIKTI_DOSYA)
telefon_var = sum(1 for x in isletmeler if x.get("Telefon"))
adres_var = sum(1 for x in isletmeler if x.get("Adres"))
gorsel_var = sum(1 for x in isletmeler if x.get("Gorsel URL"))
web_var = sum(1 for x in isletmeler if x.get("Web Sitesi"))
print(f"\n--- OZET ---")
print(f"Toplam isletme : {len(isletmeler)}")
print(f"Telefon : {telefon_var}")
print(f"Adres : {adres_var}")
print(f"Web Sitesi : {web_var}")
print(f"Gorsel URL : {gorsel_var}")
input("\nEnter'a basin...")
if __name__ == "__main__":
main()