## GIRDI โ€” yalniz bu blogu doldur ```text ScrapeUnblocker API anahtarim: BURAYA_YAPISTIR Yaptigim is: BURAYA_TEK_CUMLE Kendi Instagram hesabim: @BURAYA Rakip Instagram hesaplari: @BURAYA, @BURAYA Rakip TikTok hesaplari: (istege bagli, bos kalabilir) Tarama: Hizli ``` Girdin bu bloktur. Sohbette bana soru sorma, eksik alani makul varsayimla doldurup devam et. Anahtar satiri bos ya da hala `BURAYA_YAPISTIR` ise canli veri toplamaya HIC girme: urunu kur, testleri kos, agsiz ornek ciktiyi uret ve sonunda tek satirla anahtarin eksik oldugunu soyle. `@` isareti ve tam profil adresi de kabul. Tek satira virgul, noktali virgul ya da "ve" ile birden cok hesap yazilabilir; hepsini ayri hesap say. Baslamadan once hedefi tek satir geri oku. Yerel bir **Icerik Firsat Radari** kur: Instagram hesabimi rakiplerle karsilastirsin, TikTok verildiyse ikincil kaynak olarak eklesin, tek dosyalik koyu HTML rapor uretsin. Urunu kur, test et, veriyi topla, raporu ac. Bana terminal isi birakma. Zorunlu veri yolu `business_context -> run_radar -> data.json -> adapt_brief`. Normalize is cumlesi `data.json` dosyasinin ICINDE de yazili dursun; anahtar adi serbest. `adapt_brief(business_context, evidence)` UC KEZ cagrilsin; her cagri tek kanit alip tek brief dondursun, toplu donus yasak. Her `adaptation` normalize is cumlesini birebir icersin ve raporda **Isine uyarlama** diye gorunsun. Sabit `DEFAULT_ADAPTATIONS` kabul edilmez: kanit ayni kalirken is cumlesi degisince uc adaptation da degismeli. ## Kuracagin dosyalar Yeni ve bos bir `icerik-firsat-radari` klasoru ac. En az: `sosyal_rontgen.py` (urun ve rapor), `baslat.py` (otomatik kurulum), `requirements.txt` (`scrapeunblocker==0.1.8`, `httpx==0.28.1`), `.gitignore` (`.env`, `.venv/`, `cache/`, `runs/`, `son_kosu.json`, `son_rapor.html`), `tests/fixtures/` (Instagram profil + gonderi, TikTok, SERP cevaplari), `tests/test_social_radar.py` (agsiz `unittest`), `README.md`. `baslat.py` ilk kosuda `.venv` ve paketleri kursun; requirements hash'i degismediyse kurulumu atlayip urunu `.venv` Python ile acsin. Kullaniciya `pip install` yaptirma. Python 3.10+ gerekli; surumu dogrula, dusukse net uyariyla dur. Ilk kosuyu yukaridaki bloktan okudugun degerlerle sen baslat. Urun sonraki kosular icin su CLI'yi birebir tasisin: ```text --is METIN --ben KULLANICI # Instagram kullanici adi --rakip KULLANICI # 1-4 kez tekrarlanabilir, Instagram --tiktok KULLANICI # istege bagli, tekrarlanabilir --mod {hizli,derin} --yenile ``` Tek `--rakip` degerinin icine virgulle birden cok hesap yazilabilsin; ayrilmazsa "@a,@b" tek ve sahte bir hesap olur, iki rakip birden sessizce kaybolur. `--hesap`, `--instagram`, `--refresh`, `--key` veya baska alias uretme. `--help` hicbir kurulum ya da ag islemi yapmadan yardimi basip `0` ile ciksin. `baslat.py` kendi kurulumundan sonra ayni arguman listesini degistirmeden urune iletsin; `baslat.py --help` de kurulumsuz `0` donsun. ## ScrapeUnblocker veri yolu Tek web veri saglayicisi ScrapeUnblocker. Resmi Python SDK: ```python from scrapeunblocker import Client su = Client(api_key=anahtar, timeout=180.0, max_retries=0) ``` SDK tekrarlarini kapat; tekrar, butce ve sayac kontrolu urunde olsun, boylece manifestteki deneme sayisi dogru kalir. `main` stub olamaz. `build_live_transports(api_key, client_cls=None)` `Client`i tembel import edip yukaridaki argumanlarla kursun ve uc adapteri `{"get_parsed": ..., "serp": ..., "get_page_source": ...}` sozluguyle dondursun; degerler dogrudan cagrilabilir olsun. Gercek `get_parsed()` bir `ParsedPage(page_type, source, data, raw)` nesnesi dondurur; mutlaka `{"status_code":200,"data":{"page_type":obj.page_type,"source":obj.source,"data":obj.data}}` diye normalize et. Nesneyi oldugu gibi gecmek ya da yalniz `obj.data`yi alip `page_type/source`u kaybetmek yasak. SDK hatayi ISTISNA atarak bildirir (`ScrapeUnblockerError` soyu, `status_code` tasir), sozluk dondurmez. Uc adapterin UCUNUN de govdesi `try/except` icinde olsun ve istisnayi politikana cevirsin; ham SDK istisnasi adapterin disina cikmasin, kullaniciya traceback dusmesin. `main` girdi -> anahtar -> canli transport -> `run_radar` -> atomik cikti yolunu izler, offline erken-cikis yoktur. `main(argv=None, kok=None, client_cls=None)` imzasi zorunlu; `kok` verilirse `runs/`, `son_kosu.json`, `son_rapor.html` ve `.env` dahil TUM ciktilar oraya yazilsin, `client_cls` verilirse transportlar o sinifla kurulsun. Resmi cevap genelde `{data:{page_type,source,data}}` bicimindedir; gecici `data`, `result`, `parsed_data`, `payload` sarmallarini dolas. Alan uydurma, temel sayilar yoksa reddet. `page_type` uydurma: canli olcumde yalniz iki deger dondu, profilde `social_profile`, gonderi/videoda `social_post`. `instagram_post` gibi platform adli deger YOKTUR. Platformu adresten ayirt et. Baska deger taninmamis semadir, kontrollu ham fallback devreye girer. ### Instagram birincil yoldur Profil, hesap basina tek istek: `su.get_parsed(f"https://www.instagram.com/{kullanici}/")`. Alanlar: `username`, `full_name`, `verified`, `private`, `biography`, `followers`, `following`, `external_urls`, `avatar_url`, `recent_posts`. `posts_count` cogu zaman `None` doner, kullanma. `recent_posts` 12 gonderi tasir: `shortcode`, `url`, `caption`, `thumbnail_url`, `media_type`, `product_type`. Bu liste gonderi adreslerini BEDAVA verir; Instagram gonderisi bulmak icin SERP kullanma. Icindeki `likes`, `comments`, `counts_hidden` 12/12 kayitta `None` geldi; profilden etkilesim sayisi BEKLEME. Sayilar yalniz gonderi adresinden gelir, gonderi basina bir istek: `su.get_parsed(gonderi_adresi)`. Alanlar: `likes`, `comments`, `counts_hidden`, `posted_at`, `posted_timestamp`, `post_id`, `media_type`, `product_type`, `carousel_count`, `caption`, `thumbnail_url`, `video_url`, `location`, `hashtags`, `author`. **`counts_hidden: true` gelen gonderinin begeni sayisi SAHTEDIR**; Instagram begeniyi gizleyince `likes` alanina 3 gibi kucuk bir sayi koyar. Bu gonderi ortancaya, ortalamaya, brief aday havuzuna, "kazanan acilislar" listesine ve ekrandaki "kesin olcum" sayacina HIC girmesin; kanit tablosunda begeni hucresi sayi degil "gizli" yazsin, yorum sayisi gorunsun. Filtre `counts_hidden` alanina baksin; yalniz "sayac `None` mi" kontrolu gizlileri sizdirip dusuk yorumlu bir gonderiyi brief kazanan yapmisti. `author` bir Mapping'dir ve `username` icerir, fakat bu **taranan hesap degildir**: ortak (collab) paylasimda Instagram oraya obur yazari koyar. Her gonderiyi tarandigi hesabin adiyla etiketle; kanit cumlesinde etiket taranan hesaptir, `author` farkliysa "(@X ile ortak)" eklenir. Aksi halde kanit cumlesi baska hesabin ortancasina atifta bulunup kendi icinde yalan olur. Instagram'da izlenme, oynatma, paylasim, kaydetme ve altyazi sayaci **HIC YOKTUR**; isteme, tahmin etme, sifir yazma. `product_type` uc deger alir: `clips` (Reels), `carousel_container`, `feed`. `recent_posts` sirasi tarih sirasi DEGILDIR; sirayi `posted_at` ile kendin kur. ### TikTok ikincil ve istege baglidir TikTok hesabi verilmediyse bu bolumu hic calistirma ve raporda "TikTok verilmedi" yaz. Verildiyse Instagram isi bittikten SONRA, kalan butceyle calistir. Video adreslerini ham Google HTML'inden arama, resmi metodu kullan: `su.serp("site:tiktok.com/@KULLANICI/video", pages_to_check=SAYFA)`. Cevabin her yerinde yalniz `https://www.tiktok.com/@KULLANICI/video/15-25_HANELI_KIMLIK` desenini kabul et, kullanici adi tam eslessin, tekrarlari ele. `su.serp()` HAZIR sozluk dondurur; icinde AYRICA `data` sarmali arama, `cevap.get("data")` gibi bir soyma payload'i bosaltir. Normalize etme zorunlulugu yalniz `get_parsed` icindir. Kanonik video adresi metrik DONDURMUYOR, 567 baytlik "Site Maintenance" sayfasi geliyor. Metrigi embed'den al: `su.get_page_source(f"https://www.tiktok.com/embed/v2/{kimlik}")`. Sayilar `