Finansal portallar hisse senedi fiyatlarını, kazanç verilerini ve analist raporlarını Cloudflare Turnstile ve reCAPTCHA ile korur. CAPTCHA'lar hızlı sembol aramaları, geçmiş veri indirmeleri ve eleme sorguları sırasında tetiklenir. Finansal sitelerde güvenilir veri toplamayı nasıl sürdüreceğiniz aşağıda açıklanmıştır.
Finansal Portallardaki CAPTCHA Kalıpları
| Veri türü | Portal örnekleri | CAPTCHA türü | Tetikleyici |
|---|---|---|---|
| Gerçek zamanlı alıntılar | Finans portalları | Cloudflare Turnstile | Hızlı sembol aramaları |
| Geçmiş fiyatlar | Veri sağlayıcılar | reCAPTCHA v2 | Toplu CSV indirmeleri |
| Mali tablolar | SEC dosyalama siteleri | Resim CAPTCHA'sı | Tekrarlanan EDGAR sorguları |
| Eleme sonuçları | Stok elekleri | Cloudflare doğrulama akışı | Karmaşık filtre sorguları |
| Analist derecelendirmeleri | Araştırma portalları | reCAPTCHA v3 | Çoklu sayfa görüntülemeleri |
Stok Veri Toplayıcı
import requests
import time
import re
from datetime import datetime, timedelta
class StockDataCollector:
def __init__(self, api_key):
self.api_key = api_key
self.session = requests.Session()
self.session.headers.update({
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
})
def get_quote(self, portal_url, symbol):
"""Get current stock quote, solving CAPTCHAs if needed."""
url = f"{portal_url}/quote/{symbol}"
response = self.session.get(url)
if self._is_captcha_page(response):
response = self._solve_and_retry(response, url)
return self._parse_quote(response.text, symbol)
def get_historical(self, portal_url, symbol, days=365):
"""Download historical price data."""
url = f"{portal_url}/history/{symbol}"
params = {
"period": f"{days}d",
"interval": "1d"
}
response = self.session.get(url, params=params)
if self._is_captcha_page(response):
response = self._solve_and_retry(response, url)
return self._parse_historical(response.text)
def scan_symbols(self, portal_url, symbols, delay=2):
"""Collect quotes for multiple symbols."""
results = {}
for symbol in symbols:
try:
results[symbol] = self.get_quote(portal_url, symbol)
time.sleep(delay)
except Exception as e:
results[symbol] = {"error": str(e)}
return results
def _is_captcha_page(self, response):
return (
response.status_code == 403 or
"cf-turnstile" in response.text or
"challenges.cloudflare.com" in response.text
)
def _solve_and_retry(self, response, url):
match = re.search(r'data-sitekey="(0x[^"]+)"', response.text)
if not match:
# Fall back to reCAPTCHA detection
match = re.search(r'data-sitekey="([^"]+)"', response.text)
if match:
return self._solve_recaptcha_and_retry(match.group(1), url)
raise ValueError("No CAPTCHA sitekey found")
resp = requests.post("https://ocr.captchaai.com/in.php", data={
"key": self.api_key,
"method": "turnstile",
"sitekey": match.group(1),
"pageurl": url,
"json": 1
})
task_id = resp.json()["request"]
for _ in range(60):
time.sleep(3)
result = requests.get("https://ocr.captchaai.com/res.php", params={
"key": self.api_key,
"action": "get",
"id": task_id,
"json": 1
})
data = result.json()
if data["status"] == 1:
return self.session.post(url, data={
"cf-turnstile-response": data["request"]
})
raise TimeoutError("CAPTCHA solve timed out")
def _solve_recaptcha_and_retry(self, site_key, url):
resp = requests.post("https://ocr.captchaai.com/in.php", data={
"key": self.api_key,
"method": "userrecaptcha",
"googlekey": site_key,
"pageurl": url,
"json": 1
})
task_id = resp.json()["request"]
for _ in range(60):
time.sleep(3)
result = requests.get("https://ocr.captchaai.com/res.php", params={
"key": self.api_key,
"action": "get",
"id": task_id,
"json": 1
})
data = result.json()
if data["status"] == 1:
return self.session.post(url, data={
"g-recaptcha-response": data["request"]
})
raise TimeoutError("reCAPTCHA solve timed out")
def _parse_quote(self, html, symbol):
from bs4 import BeautifulSoup
soup = BeautifulSoup(html, "html.parser")
def text_or_none(node):
return node.text.strip() if node and node.text else None
return {
"symbol": symbol,
"price": text_or_none(soup.select_one("[data-field='regularMarketPrice'], .price")),
"change": text_or_none(soup.select_one("[data-field='regularMarketChange'], .change")),
"volume": text_or_none(soup.select_one("[data-field='regularMarketVolume'], .volume")),
"market_cap": text_or_none(soup.select_one("[data-field='marketCap'], .market-cap")),
"timestamp": datetime.now().isoformat()
}
def _parse_historical(self, html):
from bs4 import BeautifulSoup
soup = BeautifulSoup(html, "html.parser")
rows = []
for row in soup.select("table tr")[1:]: # Skip header
cells = [td.text.strip() for td in row.select("td")]
if len(cells) >= 6:
rows.append({
"date": cells[0],
"open": cells[1],
"high": cells[2],
"low": cells[3],
"close": cells[4],
"volume": cells[5]
})
return rows
# Usage
collector = StockDataCollector("YOUR_API_KEY")
# Single quote
quote = collector.get_quote("https://finance.example.com", "AAPL")
print(f"AAPL: ${quote['price']} ({quote['change']})")
# Scan multiple symbols
portfolio = collector.scan_symbols(
"https://finance.example.com",
["AAPL", "GOOGL", "MSFT", "AMZN", "TSLA"]
)
CAPTCHA İşleme ile Pazar Takip Aracı (JavaScript)
class MarketScreener {
constructor(apiKey) {
this.apiKey = apiKey;
}
async screenStocks(portalUrl, filters) {
const params = new URLSearchParams(filters);
const response = await fetch(`${portalUrl}/screener?${params}`);
const html = await response.text();
if (html.includes('cf-turnstile') || response.status === 403) {
return this.solveAndScreen(portalUrl, filters, html);
}
return this.parseScreenerResults(html);
}
async solveAndScreen(portalUrl, filters, html) {
const match = html.match(/data-sitekey="(0x[^"]+)"/);
if (!match) throw new Error('Turnstile sitekey not found');
const submitResp = await fetch('https://ocr.captchaai.com/in.php', {
method: 'POST',
body: new URLSearchParams({
key: this.apiKey,
method: 'turnstile',
sitekey: match[1],
pageurl: portalUrl,
json: '1'
})
});
const { request: taskId } = await submitResp.json();
for (let i = 0; i < 60; i++) {
await new Promise(r => setTimeout(r, 3000));
const result = await fetch(
`https://ocr.captchaai.com/res.php?key=${this.apiKey}&action=get&id=${taskId}&json=1`
);
const data = await result.json();
if (data.status === 1) {
const response = await fetch(`${portalUrl}/screener`, {
method: 'POST',
body: new URLSearchParams({
...filters,
'cf-turnstile-response': data.request
})
});
return this.parseScreenerResults(await response.text());
}
}
throw new Error('Turnstile solve timed out');
}
parseScreenerResults(html) {
const rows = [];
const tableMatch = html.match(/<table[^>]*>[\s\S]*?<\/table>/i);
if (!tableMatch) return rows;
const rowMatches = tableMatch[0].matchAll(/<tr[^>]*>([\s\S]*?)<\/tr>/gi);
for (const row of rowMatches) {
const cells = [...row[1].matchAll(/<td[^>]*>([\s\S]*?)<\/td>/gi)]
.map(m => m[1].replace(/<[^>]+>/g, '').trim());
if (cells.length >= 4) {
rows.push({
symbol: cells[0],
price: cells[1],
change: cells[2],
volume: cells[3]
});
}
}
return rows;
}
}
// Usage
const screener = new MarketScreener('YOUR_API_KEY');
const results = await screener.screenStocks('https://finance.example.com', {
sector: 'technology',
marketCap: 'large',
peRatio: '<25'
});
Veri Türüne Göre Toplama Sıklığı
| Veri türü | Önerilen aralık | CAPTCHA sıklığı |
|---|---|---|
| Gerçek zamanlı alıntılar | 1-5 dakika | Yüksek - varsa API'yi kullanın |
| Gün sonu fiyatları | Kapanıştan sonra günde bir kez | Düşük |
| Mali tablolar | Üç ayda bir | Asgari |
| Eleme sonuçları | Günlük | Orta |
| Analist derecelendirmeleri | Haftalık | Düşük |
Sorun giderme
| Sorun | Sebep | Düzeltme |
|---|---|---|
| Her istek üzerine Turnstile | Her seferinde yeni oturum | Çerezleri istekler arasında kalıcı kıl |
| Geçmiş veriler eksik | CAPTCHA'nın arkasında sayfalama | Sayfa başına çözün, sayfalandırılmış bağlantıları takip edin |
| Teklif verileri eski | Önbelleğe alınmış yanıt sunuldu | Önbellek bozan sorgu parametresi ekleyin |
| 429 oran sınırı | Çok fazla istek | Gecikmeyi artırın, proxy'leri döndürün |
SSS
Finansal API'ler CAPTCHA'larla uğraşmaktan daha mı iyi?
Ücretsiz API'ler (bazı sağlayıcıların temel katmanları gibi) ortak verileri kapsar ancak hız sınırları vardır. CaptchaAI ile web kazıma, API'ler aracılığıyla sağlanamayan verilere (eleyici filtreleri, analist yorumları ve niş finansal veriler) erişim sağlar.
Gerçek zamanlı alıntı CAPTCHA'larını gecikmeden nasıl halledebilirim?
Piyasa saatlerinde oturumunuzu önceden doğrulayın. Cloudflare'in qa_session_cookie çerezi 15-30 dakika sürer, bu nedenle bir kez çözün ve o pencerede birden fazla istekte bulunun.
Aynı anda birden fazla finansal portaldan veri toplayabilir miyim?
Evet. Bağımsız CaptchaAI görev gönderimleriyle portal başına ayrı oturumlar kullanın. CaptchaAI, farklı siteler arasında eşzamanlı çözümlemeyi yönetir.
İlgili Makaleler
- Pazar Araştırması Veri Toplama
- Geetest ve Cloudflare Turnstile Karşılaştırması
- Cloudflare Turnstile 403 Token Düzeltmesinden Sonra
Sonraki Adımlar
Piyasa verilerini güvenilir bir şekilde toplayın —CaptchaAI API anahtarınızı alınve finansal portal CAPTCHA'larını otomatik olarak yönetin.