· Engineering · 3 min read
Neo4j + Exa + Tavily ile Otomatik İşletme Veri Zenginleştirme Pipeline'ı
Google Maps'ten bulunan işletmeleri Neo4j'e kaydedip Exa ve Tavily API'leri ile otomatik olarak zenginleştiren bir pipeline nasıl kurulur?

Proje Nedir?
Bodrum’daki işletmeleri ve turistik yerleri dijital ortamda daha görünür kılmak için bir veri zenginleştirme pipeline’ı kurdum. Sistem üç aşamadan oluşuyor:
- Google Maps API → Yeni işletmeleri bulur ve Neo4j’ye kaydeder
- Place Enrichment → Exa + Tavily ile iletişim bilgileri ve sosyal medya linkleri bulur
- Auto Website Creation → Zenginleştirilen verilerle otomatik web sitesi oluşturur ve deploy eder
Bu yazıda ikinci aşamayı — Place Enrichment sistemini — detaylı olarak anlatacağım.
Mimari Genel Bakış
Google Maps API → Neo4j (ham veri)
↓
Place Enrichment (cron, her 2dk)
↓
Exa API (web, sosyal medya)
Tavily API (telefon, email)
↓
Neo4j (zenginleştirilmiş veri)
↓
Auto Website Creation & Deploy
Neo4j Veri Modeli
Her işletme Neo4j’de bir Place node’u olarak tutuluyur. Temel alanlar:
CREATE (p:Place {
name: "Bodrum Butik Otel",
google_place_id: "ChIJ...",
latitude: 37.034,
longitude: 27.430,
enriched: false,
created_at: datetime()
})
enriched: false flag’i, Place Enrichment sisteminin hangi kayıtları işleyeceğini belirliyor.
Place Enrichment Sistemi
Cron Kurulumu
Sistem her 2 dakikada bir çalışacak şekilde crontab’a eklendi:
*/2 * * * * /Users/ebartan/clawd/agents/egecrew/projects/place-enrichment/run.sh
İşlem Akışı
Her çalışmada sistem şu adımları izliyor:
1. Neo4j’den zenginleştirilmemiş bir yer al:
query = """
MATCH (p:Place {enriched: false})
RETURN p LIMIT 1
"""
2. Exa API ile web arama:
Exa, nöral arama motoru özelliği sayesinde işletmenin web sitesini, sosyal medya profillerini ve fotoğraflarını buluyor:
exa_results = exa_client.search(
f"{place_name} {location} official website",
num_results=5,
use_autoprompt=True,
include_domains=["instagram.com", "facebook.com", "tripadvisor.com"]
)
3. Tavily API ile iletişim bilgisi arama:
Tavily, özellikle Türkçe formatlı telefon numaraları ve email adreslerini bulmakta güçlü:
tavily_results = tavily_client.search(
f"{place_name} telefon iletişim email",
search_depth="advanced",
max_results=3
)
4. Verileri birleştir ve Neo4j’i güncelle:
enriched_data = {
"website": extract_website(exa_results),
"phone": extract_phone(tavily_results),
"email": extract_email(tavily_results),
"facebook_url": extract_social(exa_results, "facebook.com"),
"instagram_url": extract_social(exa_results, "instagram.com"),
"tripadvisor_url": extract_social(exa_results, "tripadvisor.com"),
"photos": extract_photos(exa_results, limit=5),
"enriched": True,
"enriched_at": datetime.now().isoformat()
}
update_neo4j_place(place_id, enriched_data)
Bulunan Veri Türleri
Sistem başarıyla şu bilgileri buluyor:
| Veri Türü | Kaynak | Başarı Oranı |
|---|---|---|
| Website URL | Exa | ~85% |
| Telefon (TR formatı) | Tavily | ~70% |
| Tavily | ~45% | |
| Facebook URL | Exa | ~60% |
| Instagram URL | Exa | ~55% |
| TripAdvisor URL | Exa | ~40% |
| Fotoğraflar (max 5) | Exa | ~75% |
Performans
- Her çalışmada 1 işletme zenginleştiriliyor
- 103 işletme için ~3.5 saat sürüyor (2 dakika × 103)
- Log dosyası:
logs/enricher.log
Yüksek hacimli senaryolar için paralel işleme eklenebilir, ancak API rate limit’lerine dikkat etmek gerekiyor.
Örnek Log Çıktısı
2026-03-16 14:32:01 INFO Processing: Bodrum Butik Otel (ID: abc123)
2026-03-16 14:32:02 INFO Exa search completed: 5 results
2026-03-16 14:32:03 INFO Tavily search completed: 3 results
2026-03-16 14:32:03 INFO Found: website=bodrumbutik.com, phone=+90 252 316 XXXX
2026-03-16 14:32:03 INFO Found: instagram=@bodrumbutik, facebook=/bodrumbutik
2026-03-16 14:32:04 INFO Neo4j updated successfully
2026-03-16 14:32:04 INFO Enrichment complete for abc123
Zorluklar ve Çözümler
1. Türkçe karakter problemi: Exa ve Tavily API’lerine gönderilen sorgularda Türkçe karakterler (ş, ğ, ü, ö, ç, ı) doğru encode edilmeli.
2. Rate limiting: İki ayrı API kullanıldığı için her çalışmada sadece 1 işletme işleniyor. Bu, 2 dakikalık bekleme süresini verimli kullanıyor.
3. Veri kalitesi: Bazen yanlış telefon numaraları veya farklı işletmelere ait web siteleri dönüyor. Bunu azaltmak için işletme adı + şehir kombinasyonuyla arama yapıyorum.
Sonuç
Bu pipeline, manuel araştırma gerektiren işletme veri zenginleştirme sürecini tamamen otomatikleştiriyor. Exa’nın nöral arama motoru ve Tavily’nin web içeriği çıkarma yeteneği, Neo4j graph veritabanıyla birleşince güçlü bir veri katmanı oluşturuyor.
Bir sonraki yazıda bu zenginleştirilmiş verilerle otomatik web sitesi oluşturma ve deploy sürecini anlatacağım.
Kaynak kodu ve setup talimatları için GitHub repomu inceleyebilirsiniz.


