Google Cloud Functions, sunucu yönetimi olmadan kod çalıştırmak için serverless bir platformdur. Veri çekme, API isteklerinin otomasyonu veya veri toplama ile çalışırken, genellikle engelleri aşmak, IP döngüsü yapmak ve coğrafi hedefleme için trafiği proxy üzerinden yönlendirmek gerekebilir. Bu rehberde, Python ve Node.js ile Cloud Functions'da proxy ayarlarını pratik örneklerle inceleyeceğiz.
Cloud Functions'da proxy kullanmanın nedenleri
Google Cloud Functions, Google veri merkezlerinin ortak IP adresleri ile izole bir ortamda çalışır. Dış API'lere veya web sitelerine sık sık istek yapıldığında bazı sorunlar ortaya çıkar:
- IP engellemeleri — birçok hizmet (Google, Facebook, pazar yerleri) veri merkezi trafiğini tanır ve oran sınırlaması veya tam engelleme uygular.
- Coğrafi kısıtlamalar — belirli ülkelerde yalnızca erişilebilen içeriklere erişim (örneğin, Wildberries veya Ozon'daki bölgesel fiyatların çekilmesi).
- Oran sınırlaması — bir IP adresinin dakikada sınırlı sayıda istek yapmasına izin verilir. Proxy'ler yükü dağıtmaya yardımcı olur.
- Anonimlik — hassas verilerle veya rekabet istihbaratıyla çalışırken gerçek istek kaynaklarını gizleme.
Cloud Functions'da proxy kullanmanın tipik senaryoları:
- Pazar yerlerinin (Wildberries, Ozon, Amazon) fiyatlarını izlemek için veri çekme
- Sosyal medya verilerini (Instagram, TikTok) API veya web kazıma yoluyla toplama
- Farklı bölgelerde reklamların kontrolünü otomatikleştirme
- SEO analizi için arama motorlarına (Google, Yandex) toplu istekler yapma
- Uygulamaların coğrafi konum fonksiyonlarını test etme
Cloud Functions için uygun proxy türleri
Proxy türünün seçimi, görev, bütçe ve anonimlik gereksinimlerine bağlıdır. İşte temel seçeneklerin karşılaştırması:
| Proxy Türü | Hız | Anonimlik | En iyi kullanım alanları |
|---|---|---|---|
| Veri Merkezi Proxy | Yüksek (50-200 ms) | Orta | Basit web siteleri, API istekleri, SEO izleme |
| Konut Proxy | Orta (200-800 ms) | Yüksek | Sosyal medya, pazar yerleri, anti-bot sistemlerini aşma |
| Mobil Proxy | Orta (300-1000 ms) | Çok yüksek | Instagram, TikTok, mobil uygulamalar, Facebook API |
Seçim önerileri:
- Pazar yerleri için (Wildberries, Ozon, Amazon) — her isteğin yeni bir IP ile yapılması için döngüsel konut proxy.
- API istekleri için (Google Maps API, OpenWeatherMap) — yüksek hızda veri merkezi proxy, eğer IP üzerinde katı kısıtlamalar yoksa.
- Sosyal medya için (Instagram, TikTok) — mobil proxy, çünkü bunlar mobil operatörlerin IP'lerine sahiptir ve nadiren engellenir.
- SEO veri çekimi için (Google, Yandex) — gerekli bölgeye coğrafi bağlı konut proxy.
Python'da proxy ayarları (requests, aiohttp)
Python, veri çekme ve otomasyon ile çalışırken Cloud Functions için en popüler dildir. requests (senkron istekler) ve aiohttp (asenkron istekler) kütüphaneleri ile proxy entegrasyonunu inceleyelim.
Requests kütüphanesi ile örnek (HTTP proxy)
import requests
import os
def parse_with_proxy(request):
# Proxy verilerini ortam değişkenlerinden alıyoruz
proxy_host = os.environ.get('PROXY_HOST', 'proxy.example.com')
proxy_port = os.environ.get('PROXY_PORT', '8080')
proxy_user = os.environ.get('PROXY_USER', 'username')
proxy_pass = os.environ.get('PROXY_PASS', 'password')
# Kimlik doğrulaması ile proxy URL'sini oluşturuyoruz
proxy_url = f"http://{proxy_user}:{proxy_pass}@{proxy_host}:{proxy_port}"
proxies = {
'http': proxy_url,
'https': proxy_url
}
try:
# Proxy üzerinden zaman aşımı ile istek yapıyoruz
response = requests.get(
'https://api.example.com/data',
proxies=proxies,
timeout=10,
headers={'User-Agent': 'Mozilla/5.0'}
)
# Yanıtın durumunu kontrol ediyoruz
response.raise_for_status()
return {
'statusCode': 200,
'body': response.json(),
'ip_used': response.headers.get('X-Forwarded-For', 'unknown')
}
except requests.exceptions.ProxyError as e:
return {'statusCode': 502, 'error': f'Proxy hatası: {str(e)}'}
except requests.exceptions.Timeout:
return {'statusCode': 504, 'error': 'İstek zaman aşımına uğradı'}
except requests.exceptions.RequestException as e:
return {'statusCode': 500, 'error': f'İstek başarısız oldu: {str(e)}'}
Önemli noktalar:
- Ortam değişkenleri — proxy verilerini (host, port, kullanıcı adı, şifre) Secret Manager veya Cloud Functions ortam değişkenlerinde saklayın, kodda değil.
- Zaman aşımı — proxy ile ilgili sorunlarda fonksiyonun takılmaması için
timeoutayarlayın. - User-Agent — isteklerin gerçek bir tarayıcıdan geliyormuş gibi görünmesi için User-Agent başlığını ekleyin.
- Hata yönetimi — ProxyError (proxy sorunları) ve Timeout (yavaş proxy) hatalarını ayrı olarak yönetin.
Aiohttp ile örnek (asenkron istekler)
Yüksek yük altında görevler için (örneğin, 1000+ sayfa çekme) asenkron istekler kullanın:
import aiohttp
import asyncio
import os
async def fetch_with_proxy(url, proxy_url):
async with aiohttp.ClientSession() as session:
try:
async with session.get(
url,
proxy=proxy_url,
timeout=aiohttp.ClientTimeout(total=10),
headers={'User-Agent': 'Mozilla/5.0'}
) as response:
return await response.text()
except aiohttp.ClientProxyConnectionError:
return {'error': 'Proxy bağlantısı başarısız oldu'}
except asyncio.TimeoutError:
return {'error': 'İstek zaman aşımına uğradı'}
def parse_multiple_urls(request):
proxy_url = f"http://{os.environ['PROXY_USER']}:{os.environ['PROXY_PASS']}@{os.environ['PROXY_HOST']}:{os.environ['PROXY_PORT']}"
urls = [
'https://example.com/page1',
'https://example.com/page2',
'https://example.com/page3'
]
# Asenkron istekleri paralel olarak başlatıyoruz
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
tasks = [fetch_with_proxy(url, proxy_url) for url in urls]
results = loop.run_until_complete(asyncio.gather(*tasks))
return {'statusCode': 200, 'results': results}
Asenkron yaklaşım, proxy üzerinden 10-100 paralel istek yapmanıza olanak tanır, bu da Cloud Functions'ın sınırlı çalışma süresi içinde büyük veri hacimlerini çekmek için kritik öneme sahiptir (en fazla 9 dakika).
SOCKS5 proxy ile çalışma
Bazı proxy sağlayıcıları, UDP trafiği ile daha güvenilir çalışmak veya engelleri aşmak için SOCKS5 proxy sağlar. Python'da SOCKS5 ile çalışmak için requests[socks] kütüphanesini kullanın:
# requirements.txt'e ekleyin:
# requests[socks]
import requests
def use_socks5_proxy(request):
proxy_url = f"socks5://{os.environ['PROXY_USER']}:{os.environ['PROXY_PASS']}@{os.environ['PROXY_HOST']}:{os.environ['PROXY_PORT']}"
proxies = {
'http': proxy_url,
'https': proxy_url
}
response = requests.get(
'https://api.ipify.org?format=json',
proxies=proxies,
timeout=10
)
return {'statusCode': 200, 'ip': response.json()}
Node.js'de proxy ayarları (axios, node-fetch)
Node.js, Cloud Functions için ikinci en popüler dildir. axios ve node-fetch kütüphaneleri ile proxy entegrasyonunu inceleyelim.
Axios ile örnek
const axios = require('axios');
const HttpsProxyAgent = require('https-proxy-agent');
exports.parseWithProxy = async (req, res) => {
const proxyUrl = `http://${process.env.PROXY_USER}:${process.env.PROXY_PASS}@${process.env.PROXY_HOST}:${process.env.PROXY_PORT}`;
const agent = new HttpsProxyAgent(proxyUrl);
try {
const response = await axios.get('https://api.example.com/data', {
httpsAgent: agent,
timeout: 10000,
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
}
});
res.status(200).json({
success: true,
data: response.data,
proxyUsed: proxyUrl.split('@')[1] // Şifre olmadan host:port döndürüyoruz
});
} catch (error) {
if (error.code === 'ECONNREFUSED') {
res.status(502).json({ error: 'Proxy bağlantısı reddedildi' });
} else if (error.code === 'ETIMEDOUT') {
res.status(504).json({ error: 'Proxy zaman aşımı' });
} else {
res.status(500).json({ error: error.message });
}
}
};
package.json için bağımlılıklar:
{
"dependencies": {
"axios": "^1.6.0",
"https-proxy-agent": "^7.0.2"
}
}
Node-fetch ve SOCKS5 ile örnek
const fetch = require('node-fetch');
const { SocksProxyAgent } = require('socks-proxy-agent');
exports.fetchWithSocks5 = async (req, res) => {
const proxyUrl = `socks5://${process.env.PROXY_USER}:${process.env.PROXY_PASS}@${process.env.PROXY_HOST}:${process.env.PROXY_PORT}`;
const agent = new SocksProxyAgent(proxyUrl);
try {
const response = await fetch('https://api.ipify.org?format=json', {
agent,
timeout: 10000
});
const data = await response.json();
res.status(200).json({
success: true,
yourIP: data.ip
});
} catch (error) {
res.status(500).json({ error: error.message });
}
};
SOCKS5 için bağımlılıklar:
{
"dependencies": {
"node-fetch": "^2.7.0",
"socks-proxy-agent": "^8.0.2"
}
}
Proxy kimlik doğrulaması: kullanıcı adı/şifre ve IP beyaz listesi
Proxy ile çalışırken iki ana kimlik doğrulama yöntemi vardır:
1. Kullanıcı adı ve şifre ile kimlik doğrulama
En yaygın yöntem, kimlik bilgilerini proxy URL'sinde iletmektir:
http://username:password@proxy.example.com:8080
Avantajlar: Kolay yapılandırma, sabit IP kaynağı gerektirmez.
Dezavantajlar: Kimlik bilgileri her istekte iletilir, küçük bir yük getirir.
2. IP beyaz listesi ile kimlik doğrulama
Bazı sağlayıcılar, Cloud Functions'ın IP adreslerini beyaz listeye eklemeye izin verir. Sorun: Cloud Functions, Google Cloud'dan dinamik IP'ler kullanır.
Çözüm: Çıkış trafiğini statik bir dış IP üzerinden yönlendirmek için Cloud NAT kullanın:
- Google Cloud'da bir VPC ağı ve alt ağ oluşturun
- Statik IP ile Cloud NAT'ı yapılandırın
- Cloud Functions'ı VPC Bağlayıcısına bağlayın
- Statik IP'yi proxy sağlayıcısının beyaz listesine ekleyin
Proxy ayarlandıktan sonra kullanıcı adı ve şifre gerektirmez:
proxies = {
'http': 'http://proxy.example.com:8080',
'https': 'http://proxy.example.com:8080'
}
Öneri: Çoğu durumda kullanıcı adı/şifre ile kimlik doğrulama kullanın — bu daha kolaydır ve Cloud NAT için ek maliyet gerektirmez (saatte $0.044'ten başlayarak + trafik).
IP döngüsü ve proxy havuzunu yönetme
Büyük veri hacimlerini çekerken, engellemeleri önlemek için IP döngüsü kullanmak kritik öneme sahiptir. Birkaç yaklaşım vardır:
1. Sağlayıcı tarafında döngü (Döngüsel Proxy)
Birçok sağlayıcı, her istekte veya zamanlayıcıya göre IP'yi otomatik olarak değiştiren döngüsel proxy'ler sunar:
# Tek bir endpoint, IP otomatik olarak değişiyor
proxy_url = "http://username:password@rotating.proxy.com:8080"
# Her istek yeni bir IP ile yapılıyor
for i in range(100):
response = requests.get('https://api.ipify.org', proxies={'http': proxy_url})
print(f"İstek {i}: IP = {response.text}")
Avantajlar: Proxy havuzunu manuel olarak yönetmeye gerek yok, basit entegrasyon.
Dezavantajlar: Belirli IP'ler üzerinde kontrol yok, daha pahalı olabilir.
2. Proxy havuzunu manuel yönetme
Eğer elinizde statik proxy listesi varsa, kod düzeyinde döngü uygulayın:
import random
import requests
# Proxy havuzu (Secret Manager'dan yüklenebilir)
PROXY_POOL = [
"http://user:pass@proxy1.example.com:8080",
"http://user:pass@proxy2.example.com:8080",
"http://user:pass@proxy3.example.com:8080",
]
def get_random_proxy():
return random.choice(PROXY_POOL)
def parse_with_rotation(urls):
results = []
for url in urls:
proxy = get_random_proxy()
try:
response = requests.get(
url,
proxies={'http': proxy, 'https': proxy},
timeout=10
)
results.append({
'url': url,
'status': response.status_code,
'proxy': proxy.split('@')[1]
})
except Exception as e:
# Eğer proxy çalışmıyorsa, başka birini deneyelim
proxy = get_random_proxy()
response = requests.get(url, proxies={'http': proxy, 'https': proxy})
results.append({'url': url, 'status': response.status_code})
return results
3. Oturum bazlı proxy (sticky sessions)
Bir oturum içinde tek bir IP'yi korumanız gereken görevler için (örneğin, bir web sitesinde oturum açma) proxy URL'sine oturum kimliğini ekleyin:
# Oturum kimliğini kullanıcı adı olarak ekleyin
import uuid
session_id = str(uuid.uuid4())
proxy_url = f"http://username-session-{session_id}:password@proxy.example.com:8080"
# Bu session_id ile tüm istekler tek bir IP üzerinden yapılacak
session = requests.Session()
session.proxies = {'http': proxy_url, 'https': proxy_url}
# Oturum açma
session.post('https://example.com/login', data={'user': 'test', 'pass': '123'})
# Aynı oturumda sonraki istekler
session.get('https://example.com/dashboard')
Hata yönetimi ve zaman aşımı
Cloud Functions'da proxy ile çalışırken, verileri kaybetmemek ve çalışma süresi sınırlarını aşmamak için hataları doğru bir şekilde yönetmek kritik öneme sahiptir.
Hata türleri ve yönetim yöntemleri
| Hata | Sebep | Çözüm |
|---|---|---|
| ProxyError | Proxy erişilemez veya yanlış kimlik bilgileri | Havuzdan başka bir proxy'ye geçin |
| Timeout | Yavaş proxy veya aşırı yüklenmiş sunucu | 5-10 saniye zaman aşımı ayarlayın, başka bir IP ile tekrar deneyin |
| 407 Proxy Authentication Required | Yanlış kullanıcı adı/şifre | Ortam değişkenlerindeki kimlik bilgilerini kontrol edin |
| 429 Too Many Requests | Hedef sitede oran sınırlaması | İstekler arasında gecikme ekleyin, daha fazla IP kullanın |
| 403 Forbidden | Proxy IP'si site tarafından engellendi | IP'yi değiştirin, veri merkezi yerine konut kullanın |
Kapsamlı hata yönetimi örneği
import requests
import time
from requests.exceptions import ProxyError, Timeout, RequestException
def fetch_with_retry(url, proxy_pool, max_retries=3):
"""
Otomatik yeniden deneme ve hatalarda proxy değiştirme ile istek
"""
for attempt in range(max_retries):
proxy = random.choice(proxy_pool)
try:
response = requests.get(
url,
proxies={'http': proxy, 'https': proxy},
timeout=10,
headers={'User-Agent': 'Mozilla/5.0'}
)
# Durum kodunu kontrol ediyoruz
if response.status_code == 200:
return {'success': True, 'data': response.text, 'proxy': proxy}
elif response.status_code == 429:
# Oran sınırlaması — bekleyin ve tekrar deneyin
time.sleep(2 ** attempt) # Üstel geri dönüş
continue
elif response.status_code == 403:
# IP engellendi — proxy'yi değiştirin
continue
else:
return {'success': False, 'status': response.status_code}
except ProxyError:
# Proxy çalışmıyor — bir sonraki denemeyi yapın
print(f"Proxy {proxy} başarısız oldu, başka birini deniyoruz...")
continue
except Timeout:
# Zaman aşımı — başka bir proxy ile deneyin
print(f"{proxy} ile zaman aşımı, yeniden deniyoruz...")
continue
except RequestException as e:
# Diğer hatalar
print(f"İstek başarısız oldu: {e}")
if attempt == max_retries - 1:
return {'success': False, 'error': str(e)}
continue
return {'success': False, 'error': 'Maksimum deneme sayısına ulaşıldı'}
Cloud Functions'da zaman aşımı ayarları
Cloud Functions'ın çalışma süresi sınırlaması vardır (varsayılan olarak 60 saniye, maksimum 540 saniye). Proxy zaman aşımı ayarlarını yaparken bunu dikkate alın:
- Bağlantı zaman aşımı — proxy ile bağlantı kurma süresi (5 saniye önerilir)
- Okuma zaman aşımı — proxy üzerinden hedef sunucudan yanıt alma süresi (10-15 saniye önerilir)
- Toplam zaman aşımı — tüm istek için toplam süre (fonksiyonun zaman aşımından daha az olmalıdır)
# Python: ayrı zaman aşımı
response = requests.get(
url,
proxies=proxies,
timeout=(5, 15) # (bağlantı zaman aşımı, okuma zaman aşımı)
)
# Node.js ile axios
const response = await axios.get(url, {
httpsAgent: agent,
timeout: 10000 // toplam zaman aşımı milisaniye cinsinden
});
En iyi uygulamalar ve performans optimizasyonu
Cloud Functions'da proxy ile etkili bir şekilde çalışmak için öneriler:
1. Kimlik bilgileri için ortam değişkenlerini kullanın
Proxy kullanıcı adı ve şifrelerini asla kodda saklamayın. Secret Manager veya ortam değişkenlerini kullanın:
# Google Cloud'da bir gizli oluşturma
gcloud secrets create proxy-credentials \
--data-file=proxy-config.json
# Cloud Functions'a erişim sağlama
gcloud secrets add-iam-policy-binding proxy-credentials \
--member=serviceAccount:PROJECT_ID@appspot.gserviceaccount.com \
--role=roles/secretmanager.secretAccessor
# Kodu gizli okuma
from google.cloud import secretmanager
import json
def get_proxy_config():
client = secretmanager.SecretManagerServiceClient()
name = f"projects/{PROJECT_ID}/secrets/proxy-credentials/versions/latest"
response = client.access_secret_version(request={"name": name})
return json.loads(response.payload.data.decode('UTF-8'))
2. Veri çekme sonuçlarını önbelleğe alın
Tekrar eden proxy istekleri yapmamak için Cloud Storage veya Firestore kullanarak verileri önbelleğe alın:
import hashlib
from google.cloud import storage
def fetch_with_cache(url, proxy):
# URL'ye dayalı önbellek anahtarı oluşturma
cache_key = hashlib.md5(url.encode()).hexdigest()
# Cloud Storage'da önbelleği kontrol etme
bucket = storage.Client().bucket('my-cache-bucket')
blob = bucket.blob(f"cache/{cache_key}.json")
if blob.exists():
# Önbelleğe alınmış verileri döndürme
return json.loads(blob.download_as_text())
# Proxy üzerinden istek yapma
response = requests.get(url, proxies={'http': proxy})
data = response.json()
# Önbelleğe kaydetme
blob.upload_from_string(json.dumps(data))
return data
3. İzleme ve günlükleme
Proxy performansını ve hata sıklığını Cloud Logging ile izleyin:
import logging
import time
def fetch_with_logging(url, proxy):
start_time = time.time()
try:
response = requests.get(url, proxies={'http': proxy}, timeout=10)
duration = time.time() - start_time
logging.info({
'url': url,
'proxy': proxy.split('@')[1],
'status': response.status_code,
'duration': duration,
'success': True
})
return response
except Exception as e:
duration = time.time() - start_time
logging.error({
'url': url,
'proxy': proxy.split('@')[1],
'error': str(e),
'duration': duration,
'success': False
})
raise
4. Soğuk başlatma optimizasyonu
Cloud Functions, soğuk başlatma (cold start) gecikmesine sahiptir. Bağımlılıkları en aza indirin ve kütüphanelerin minimum sürümlerini kullanın:
# requirements.txt — yalnızca gerekli kütüphaneler
requests==2.31.0
# Kritik değilse ağır kütüphanelerden (pandas gibi) kaçının
Bağlantıları yeniden kullanmak için global değişkenler kullanın:
# Soğuk başlatma sırasında bir kez oturum oluşturun
session = requests.Session()
session.proxies = {'http': PROXY_URL, 'https': PROXY_URL}
def parse_data(request):
# Çağrılar arasında oturumu yeniden kullanın
response = session.get('https://api.example.com/data')
return response.json()
5. Proxy'nin coğrafi bağlılığı
Coğrafi hedefleme gerektiren görevler için (örneğin, bölgesel fiyatların çekilmesi) belirli bir ülkeye veya şehre bağlı proxy kullanın:
# Ülke belirtilerek konut proxy örneği
proxy_url = f"http://username-country-ru:password@proxy.example.com:8080"
# Farklı ülkeler için farklı endpoint'ler kullanın
PROXIES_BY_COUNTRY = {
'RU': 'http://user:pass@ru.proxy.example.com:8080',
'US': 'http://user:pass@us.proxy.example.com:8080',
'DE': 'http://user:pass@de.proxy.example.com:8080'
}
def parse_by_country(country_code):
proxy = PROXIES_BY_COUNTRY.get(country_code)
response = requests.get('https://example.com', proxies={'http': proxy})
return response.text
Sonuç
Google Cloud Functions ile proxy entegrasyonu, IP kısıtlaması olmadan veri çekme, otomasyon ve API ile çalışma için geniş olanaklar sunar. Dikkate alınması gereken ana noktalar: hata yönetimi ile yeniden deneme mantığı, takılmaları önlemek için zaman aşımı kullanımı, engellemeleri önlemek için IP döngüsü ve kimlik bilgilerini Secret Manager'da güvenli bir şekilde saklama.
Çoğu veri çekme ve otomasyon görevi için en iyi seçim konut proxy'leri olacaktır — bunlar yüksek anonimlik sağlar ve gerçek kullanıcıların IP'lerini kullanarak engellenme oranı düşüktür. Sosyal medya ve mobil uygulamalarla çalışırken, mobil proxy'leri öneriyoruz, çünkü bunlar mobil operatörlerin IP'lerine sahiptir ve Instagram ve TikTok gibi platformlar tarafından neredeyse hiç engellenmezler.
Proxy ile doğru yapılandırılmış Cloud Functions, büyük veri hacimlerini işlemek için ölçeklenebilir ve ekonomik bir çözüm sunar, altyapı yönetimi gerektirmez.