Problem: Neden Elle Göndermek Yoruyor
Bir ecza deposunda 200 hastane müşterisine her ay kişiselleştirilmiş sipariş durumu mesajı göndermek gerekiyordu. Mesajın içinde hastane adı, ürün kodu ve YK numarası değişiyordu. Elle göndermek hem hatalı hem de saatlerce süren bir işti.
İhtiyaç basitti: Excel listesini yükle, mesaj şablonunu yaz, gönder butonu ile hepsini gönder. Ama WhatsApp'ın spam korumasına takılmadan.
Çözüm Mimarisi
Üç katmanlı bir yapı kurdum:
- Veri katmanı: pandas ile Excel okuma, sütun eşleştirme
- Gönderim katmanı: pywhatkit + selenium ile WhatsApp Web otomasyonu
- Kontrol katmanı: PyQt5 ile gerçek zamanlı durum takibi, durdur/devam et
WhatsApp Web otomasyonu resmi API değildir. Yüksek hacimli gönderimde numara ban riski vardır. Günlük 200 mesajın altında kalın ve bekleme sürelerini atlayın.
Excel Okuma ve Şablon Sistemi
Excel dosyasında her satır bir müşteriyi temsil ediyordu. Sütun isimleri: telefon, hastane_adi, urun_adi, yk_no.
import pandas as pd
def load_customers(filepath):
df = pd.read_excel(filepath)
# Telefon numaralarını temizle
df['telefon'] = df['telefon'].astype(str).str.replace(r'[^0-9]', '', regex=True)
# 0 ile başlayanları 90 ile değiştir
df['telefon'] = df['telefon'].apply(
lambda x: '90' + x[1:] if x.startswith('0') else x
)
return df.to_dict('records')
def build_message(template, row):
return template.format(
hastane=row['hastane_adi'],
urun=row['urun_adi'],
yk=row['yk_no']
)
Mesaj şablonu kullanıcı tarafından yazılıyordu. Örnek: Merhaba {hastane}, {urun} ürününüz YK: {yk} numarası ile hazırlanmıştır.
Spam Koruması
WhatsApp'ın spam tespiti iki şeye bakıyor: gönderim hızı ve aynı mesajın tekrarlanması. İkisini de farklı yollarla çözdük.
import time, random
def send_with_protection(phone, message, config):
# Rastgele bekleme: 8-25 saniye arası
base_wait = config.get('base_wait', 12)
jitter = random.uniform(-4, 13)
time.sleep(base_wait + jitter)
# Her 30 mesajda uzun mola: 3-7 dakika
if config['sent_count'] % 30 == 0 and config['sent_count'] > 0:
long_break = random.uniform(180, 420)
print(f"Mola: {long_break:.0f} saniye")
time.sleep(long_break)
# Gönder
pywhatkit.sendwhatmsg_instantly(
phone_no=f"+{phone}",
message=message,
wait_time=10,
tab_close=True,
close_time=3
)
config['sent_count'] += 1
Mesaj içeriğini tamamen aynı tutmayın. Şablona müşteri adını veya tarihi ekleyerek her mesajı biraz farklı yapın. WhatsApp aynı içeriği tekrar tespit ettiğinde ban riskini artırır.
PyQt5 Arayüzü
Arayüz üç bölümden oluştu: Excel yükleme + sütun eşleştirme, mesaj şablonu editörü ve gönderim kontrol paneli.
Gönderim arka planda QThread ile çalışıyor, ana thread'i bloklamıyor. Progress bar ve gerçek zamanlı log listesi ile kullanıcı her mesajın durumunu görebiliyor.
from PyQt5.QtCore import QThread, pyqtSignal
class SenderThread(QThread):
progress = pyqtSignal(int, str) # (index, durum)
finished = pyqtSignal(dict) # istatistikler
def __init__(self, customers, template, config):
super().__init__()
self.customers = customers
self.template = template
self.config = config
self._stop = False
def run(self):
stats = {'ok': 0, 'fail': 0}
for i, row in enumerate(self.customers):
if self._stop:
break
msg = build_message(self.template, row)
try:
send_with_protection(row['telefon'], msg, self.config)
stats['ok'] += 1
self.progress.emit(i, 'OK')
except Exception as e:
stats['fail'] += 1
self.progress.emit(i, f'HATA: {e}')
self.finished.emit(stats)
def stop(self):
self._stop = True
Sonuç ve Dikkat Edilecekler
Sistem günlük 150-200 mesajı sorunsuz gönderiyor. Birkaç önemli not:
- WhatsApp Web'in açık olması gerekiyor — uygulama tarayıcıyı kontrol ediyor
- Günlük 300 mesaj limitini aşmayın — ban riskini ciddi artırıyor
- Gece 1-6 arası göndermeyin — hem şüpheli görünür hem rahatsız eder
- İlk kullanımda test — önce 5 kişilik liste ile test edin
Resmi çözüm için WhatsApp Business API (Meta Cloud API) bakın — mesaj başına küçük bir ücret var ama sınırsız ve güvenli.