{"id":42363,"date":"2026-06-07T21:04:45","date_gmt":"2026-06-07T18:04:45","guid":{"rendered":"https:\/\/fatihsoysal.com\/blog\/gercek-zamanli-haber-verilerini-python-ve-postgresql-ile-yakalamak-bir-etl-yolculugu\/"},"modified":"2026-06-07T21:05:13","modified_gmt":"2026-06-07T18:05:13","slug":"gercek-zamanli-haber-verilerini-python-ve-postgresql-ile-yakalamak-bir-etl-yolculugu","status":"publish","type":"post","link":"https:\/\/fatihsoysal.com\/blog\/gercek-zamanli-haber-verilerini-python-ve-postgresql-ile-yakalamak-bir-etl-yolculugu\/","title":{"rendered":"Ger\u00e7ek Zamanl\u0131 Haber Verilerini Python ve PostgreSQL ile Yakalamak: Bir ETL Yolculu\u011fu"},"content":{"rendered":"<h2>Ger\u00e7ek Zamanl\u0131 Haber Verilerini Python ve PostgreSQL ile Yakalamak: Bir ETL Yolculu\u011fu<\/h2>\n<p>G\u00fcn\u00fcm\u00fcz d\u00fcnyas\u0131nda bilgiye an\u0131nda eri\u015fim kritik \u00f6neme sahip. S\u00fcrekli akan haber verilerini otomatik olarak toplay\u0131p i\u015flemek, bir\u00e7ok sekt\u00f6r i\u00e7in rekabet avantaj\u0131 sa\u011flayabilir. Bu makale, Python ve PostgreSQL kullanarak ger\u00e7ek zamanl\u0131 haber verilerini \u00e7ekmek, temizlemek, d\u00f6n\u00fc\u015ft\u00fcrmek ve depolamak i\u00e7in sa\u011flam bir ETL (Extract, Transform, Load) hatt\u0131 olu\u015fturman\u0131n ad\u0131m ad\u0131m rehberini sunuyor. Bu s\u00fcre\u00e7te, veri m\u00fchendisli\u011finin temel prensiplerini uygulayarak, g\u00fcvenilir ve \u00f6l\u00e7eklenebilir bir sistem in\u015fa etmeyi hedefliyoruz.<\/p>\n<h3>Neden Ger\u00e7ek Zamanl\u0131 Haber Verisi ve ETL Kritik?<\/h3>\n<p>G\u00fcn\u00fcm\u00fcz\u00fcn dijital \u00e7a\u011f\u0131nda, bilgi ak\u0131\u015f\u0131 hi\u00e7 olmad\u0131\u011f\u0131 kadar h\u0131zl\u0131 ve yo\u011fun. \u00d6zellikle haberler, k\u00fcresel olaylar\u0131n nabz\u0131n\u0131 tutmak, piyasa hareketlerini anlamak ve toplumsal e\u011filimleri analiz etmek i\u00e7in paha bi\u00e7ilmez bir kaynakt\u0131r. Finans sekt\u00f6r\u00fcnde, \u015firket haberleri hisse senedi fiyatlar\u0131n\u0131 an\u0131nda etkileyebilirken, pazarlama uzmanlar\u0131 \u00fcr\u00fcn lansmanlar\u0131 veya marka itibar\u0131n\u0131 etkileyen haberleri takip ederek stratejilerini h\u0131zla g\u00fcncelleyebilirler. Ara\u015ft\u0131rmac\u0131lar i\u00e7inse, belirli bir konu hakk\u0131ndaki en son geli\u015fmeleri izlemek, \u00e7al\u0131\u015fmalar\u0131n\u0131n g\u00fcncelli\u011fini korumak ad\u0131na hayati \u00f6neme sahiptir. \u0130\u015fte bu noktada, ger\u00e7ek zamanl\u0131 haber verilerinin toplanmas\u0131, i\u015flenmesi ve analiz edilmesi, karar alma s\u00fcre\u00e7lerinde b\u00fcy\u00fck bir fark yarat\u0131r.<\/p>\n<p>Ancak, ham haber verisi genellikle da\u011f\u0131n\u0131k, yap\u0131land\u0131r\u0131lmam\u0131\u015f ve farkl\u0131 kaynaklardan geldi\u011fi i\u00e7in do\u011frudan kullan\u0131ma uygun de\u011fildir. Bu t\u00fcr veriyi anlaml\u0131 bilgilere d\u00f6n\u00fc\u015ft\u00fcrmek i\u00e7in sistematik bir yakla\u015f\u0131ma ihtiya\u00e7 duyar\u0131z. \u0130\u015fte burada ETL (Extract, Transform, Load &#8211; \u00c7ek, D\u00f6n\u00fc\u015ft\u00fcr, Y\u00fckle) kavram\u0131 devreye girer. ETL, farkl\u0131 kaynaklardan gelen veriyi al\u0131p (Extract), belirli kurallar ve mant\u0131k \u00e7er\u00e7evesinde temizleyip, yap\u0131land\u0131r\u0131p, zenginle\u015ftirip (Transform) ve son olarak analiz veya raporlama i\u00e7in uygun bir depolama alan\u0131na (genellikle bir veritaban\u0131 veya veri ambar\u0131) y\u00fckleme (Load) s\u00fcrecini ifade eder. Bu \u00fc\u00e7 a\u015famal\u0131 s\u00fcre\u00e7, verinin kalitesini, tutarl\u0131l\u0131\u011f\u0131n\u0131 ve kullan\u0131labilirli\u011fini art\u0131rarak, ham verinin stratejik bir varl\u0131\u011fa d\u00f6n\u00fc\u015fmesini sa\u011flar.<\/p>\n<p>Peki, neden \u00f6zellikle Python ve PostgreSQL ikilisini se\u00e7iyoruz? Python, geni\u015f k\u00fct\u00fcphane ekosistemi (<code>requests<\/code>, <code>pandas<\/code>, <code>beautifulsoup<\/code> vb.) ve basit s\u00f6zdizimi sayesinde veri \u00e7ekme ve d\u00f6n\u00fc\u015ft\u00fcrme i\u015flemleri i\u00e7in ideal bir dildir. H\u0131zl\u0131 prototipleme imkan\u0131 sunmas\u0131 ve b\u00fcy\u00fck veri k\u00fcmeleriyle ba\u015fa \u00e7\u0131kabilme yetene\u011fi, onu veri m\u00fchendisli\u011fi projelerinin vazge\u00e7ilmezi yapar. PostgreSQL ise, a\u00e7\u0131k kaynakl\u0131, g\u00fc\u00e7l\u00fc, \u00f6l\u00e7eklenebilir ve g\u00fcvenilir bir ili\u015fkisel veritaban\u0131 y\u00f6netim sistemidir. Karma\u015f\u0131k sorgular\u0131 desteklemesi, JSON verisi gibi yap\u0131land\u0131r\u0131lmam\u0131\u015f verileri depolayabilmesi ve ACID (Atomicity, Consistency, Isolation, Durability) \u00f6zelliklerini sa\u011flamas\u0131, onu ger\u00e7ek zamanl\u0131 veri depolama ve analiz ihtiya\u00e7lar\u0131 i\u00e7in m\u00fckemmel bir se\u00e7im haline getirir. Bu iki teknolojinin birle\u015fimi, esnek, g\u00fc\u00e7l\u00fc ve bak\u0131m\u0131 kolay bir ETL hatt\u0131 olu\u015fturmak i\u00e7in sa\u011flam bir temel sunar. Bu makale boyunca, bu ara\u00e7lar\u0131 kullanarak nas\u0131l ad\u0131m ad\u0131m bir haber ETL hatt\u0131 kuraca\u011f\u0131m\u0131z\u0131 detayl\u0131ca inceleyece\u011fiz.<\/p>\n<h3>ETL Hatt\u0131n\u0131n Temel Bile\u015fenleri: Ad\u0131m Ad\u0131m \u0130n\u015fa<\/h3>\n<p>Bir ETL hatt\u0131 olu\u015fturmak, bir binan\u0131n temelini atmaya benzer; her katman bir \u00f6ncekinin \u00fczerine in\u015fa edilir ve sa\u011flam bir yap\u0131 i\u00e7in her bir bile\u015fenin do\u011fru tasarlanmas\u0131 kritik \u00f6neme sahiptir. Ger\u00e7ek zamanl\u0131 haber verilerini i\u015fleyecek bir ETL hatt\u0131 kurarken, ana bile\u015fenleri ve bu bile\u015fenlerin birbirleriyle nas\u0131l etkile\u015fime girdi\u011fini anlamak, ba\u015far\u0131l\u0131 bir sistemin anahtar\u0131d\u0131r. Bu s\u00fcre\u00e7, temelde \u00fc\u00e7 ana a\u015famadan olu\u015fur: Veri \u00c7ekme (Extract), Veri D\u00f6n\u00fc\u015ft\u00fcrme (Transform) ve Veri Y\u00fckleme (Load).<\/p>\n<p>\u0130lk olarak, <strong>Veri Kayna\u011f\u0131 (Haber API&#8217;leri)<\/strong> se\u00e7imi gelir. Haber verilerine ula\u015fman\u0131n en yayg\u0131n ve verimli yolu, \u00e7e\u015fitli haber ajanslar\u0131n\u0131n veya veri sa\u011flay\u0131c\u0131lar\u0131n\u0131n sundu\u011fu Uygulama Programlama Aray\u00fczleri (API &#8211; Application Programming Interface) kullanmakt\u0131r. Bu API&#8217;ler, genellikle belirli bir formatta (JSON veya XML gibi) yap\u0131land\u0131r\u0131lm\u0131\u015f veriler sunar. API se\u00e7imi yaparken, veri kapsam\u0131 (hangi konular\u0131, dilleri, b\u00f6lgeleri kaps\u0131yor), veri g\u00fcncelli\u011fi (ne s\u0131kl\u0131kla g\u00fcncelleniyor), kullan\u0131m limitleri (dakikada\/ayda ka\u00e7 istek yapabilirim), maliyeti ve kimlik do\u011frulama (API anahtar\u0131, OAuth vb.) y\u00f6ntemleri gibi fakt\u00f6rleri g\u00f6z \u00f6n\u00fcnde bulundurmak \u00f6nemlidir. \u00d6rne\u011fin, News API, GNews API veya MediaStack gibi servisler pop\u00fcler se\u00e7eneklerdir. Kimlik do\u011frulama, genellikle bir API anahtar\u0131 ile yap\u0131l\u0131r ve bu anahtar, API isteklerinizin ge\u00e7erlili\u011fini ve yetkilili\u011fini sa\u011flar. Bu anahtarlar\u0131n g\u00fcvenli bir \u015fekilde saklanmas\u0131 ve kullan\u0131lmas\u0131, sistem g\u00fcvenli\u011fi a\u00e7\u0131s\u0131ndan elzemdir.<\/p>\n<p>\u0130kinci a\u015fama, <strong>Veri \u00c7ekme (Extract)<\/strong>&#8216;dir. Bu a\u015famada, Python programlama dilini kullanarak se\u00e7ti\u011fimiz haber API&#8217;sinden ham veriyi alaca\u011f\u0131z. Python&#8217;\u0131n <code>requests<\/code> k\u00fct\u00fcphanesi, HTTP istekleri g\u00f6ndererek API&#8217;lerle ileti\u015fim kurmak i\u00e7in son derece kullan\u0131\u015fl\u0131d\u0131r. \u00c7ekme i\u015flemi s\u0131ras\u0131nda, API&#8217;nin belirledi\u011fi parametreleri (anahtar kelime, tarih aral\u0131\u011f\u0131, dil vb.) do\u011fru bir \u015fekilde ayarlamak, istedi\u011fimiz veriye ula\u015fmak i\u00e7in \u00f6nemlidir. Ayr\u0131ca, a\u011f hatalar\u0131, API limitlerine tak\u0131lma veya ge\u00e7ersiz yan\u0131tlar gibi durumlar i\u00e7in hata y\u00f6netimi ve yeniden deneme (retry) mekanizmalar\u0131 uygulamak, ETL hatt\u0131n\u0131n dayan\u0131kl\u0131l\u0131\u011f\u0131n\u0131 art\u0131r\u0131r. Bu a\u015faman\u0131n \u00e7\u0131kt\u0131s\u0131, genellikle bir JSON format\u0131nda gelen, hen\u00fcz i\u015flenmemi\u015f ham haber makaleleri listesidir.<\/p>\n<p>\u00dc\u00e7\u00fcnc\u00fc ve en karma\u015f\u0131k a\u015fama, <strong>Veri D\u00f6n\u00fc\u015ft\u00fcrme (Transform)<\/strong>&#8216;dir. \u00c7ekilen ham veri, genellikle farkl\u0131 alan adland\u0131rmalar\u0131na, eksik de\u011ferlere, gereksiz karakterlere veya tutars\u0131z formatlara sahip olabilir. D\u00f6n\u00fc\u015ft\u00fcrme a\u015famas\u0131nda, bu ham veriyi temizleyerek, standartla\u015ft\u0131rarak ve analiz i\u00e7in uygun bir yap\u0131ya getirerek i\u015fleriz. Bu s\u00fcre\u00e7 \u015funlar\u0131 i\u00e7erebilir: eksik de\u011ferleri doldurma veya atma, metin alanlar\u0131ndan \u00f6zel karakterleri veya HTML etiketlerini kald\u0131rma, tarih formatlar\u0131n\u0131 standartla\u015ft\u0131rma, kategori etiketlerini birle\u015ftirme veya yeni t\u00fcretilmi\u015f \u00f6zellikler (\u00f6rne\u011fin, haber metninin uzunlu\u011fu, ba\u015fl\u0131kta ge\u00e7en anahtar kelime say\u0131s\u0131) olu\u015fturma. Python&#8217;\u0131n <code>pandas<\/code> k\u00fct\u00fcphanesi, bu t\u00fcr veri manip\u00fclasyonlar\u0131 i\u00e7in g\u00fc\u00e7l\u00fc ara\u00e7lar sunar, ancak daha basit senaryolar i\u00e7in \u00f6zel Python fonksiyonlar\u0131 da yeterli olabilir. D\u00f6n\u00fc\u015ft\u00fcrme a\u015famas\u0131n\u0131n amac\u0131, veriyi &#8220;temiz&#8221; ve &#8220;tutarl\u0131&#8221; hale getirerek bir sonraki y\u00fckleme a\u015famas\u0131na haz\u0131rlamakt\u0131r.<\/p>\n<p>Son olarak, <strong>Veri Y\u00fckleme (Load)<\/strong> a\u015famas\u0131 gelir. D\u00f6n\u00fc\u015ft\u00fcr\u00fclm\u00fc\u015f ve temizlenmi\u015f veriyi kal\u0131c\u0131 olarak depolamak i\u00e7in bir veritaban\u0131na ihtiyac\u0131m\u0131z var. PostgreSQL, bu t\u00fcr yap\u0131land\u0131r\u0131lm\u0131\u015f veriyi depolamak i\u00e7in m\u00fckemmel bir se\u00e7enektir. Y\u00fckleme a\u015famas\u0131nda, veritaban\u0131nda haber makaleleri i\u00e7in uygun bir tablo \u015femas\u0131 (schema) olu\u015fturulur. Bu \u015fema, haberin ba\u015fl\u0131\u011f\u0131, i\u00e7eri\u011fi, yazar\u0131, yay\u0131n tarihi, URL&#8217;si gibi alanlar\u0131 ve bunlar\u0131n veri tiplerini tan\u0131mlar. Python&#8217;dan PostgreSQL&#8217;e veri y\u00fcklemek i\u00e7in <code>psycopg2<\/code> gibi veritaban\u0131 adapt\u00f6rleri veya <code>SQLAlchemy<\/code> gibi ORM (Object-Relational Mapping) ara\u00e7lar\u0131 kullan\u0131labilir. Y\u00fckleme i\u015flemi s\u0131ras\u0131nda, ayn\u0131 haberin birden fazla kez kaydedilmesini \u00f6nlemek i\u00e7in benzersiz anahtarlar (\u00f6rne\u011fin, haber URL&#8217;si) \u00fczerinden &#8220;upsert&#8221; (ekle veya g\u00fcncelle) i\u015flemleri uygulamak, veri tekrar\u0131n\u0131 (duplication) engellemek i\u00e7in \u00f6nemlidir. Bu a\u015faman\u0131n sonunda, t\u00fcm i\u015flenmi\u015f haber verileri, sorgulanabilir ve analiz edilebilir bir formatta PostgreSQL veritaban\u0131m\u0131zda saklanm\u0131\u015f olur.<\/p>\n<h3>Python ile Veri \u00c7ekme (Extract) Mekanizmas\u0131 Nas\u0131l Kurulur?<\/h3>\n<p>ETL hatt\u0131m\u0131z\u0131n ilk ve en temel ad\u0131m\u0131, ham haber verisini kaynak sistemden, yani genellikle bir haber API&#8217;sinden \u00e7ekmektir. Bu &#8220;Extract&#8221; (\u00c7ekme) a\u015famas\u0131, verinin kalitesi ve g\u00fcncelli\u011fi i\u00e7in kritik bir rol oynar. Python, bu t\u00fcr g\u00f6revler i\u00e7in sundu\u011fu g\u00fc\u00e7l\u00fc ve esnek k\u00fct\u00fcphaneler sayesinde ideal bir ara\u00e7t\u0131r. Bu b\u00f6l\u00fcmde, Python&#8217;\u0131n <code>requests<\/code> k\u00fct\u00fcphanesini kullanarak bir haber API&#8217;sinden nas\u0131l veri \u00e7ekece\u011fimizi, kimlik do\u011frulama stratejilerini ve hata y\u00f6netimi mekanizmalar\u0131n\u0131 nas\u0131l uygulayaca\u011f\u0131m\u0131z\u0131 ad\u0131m ad\u0131m inceleyece\u011fiz.<\/p>\n<p>\u0130lk olarak, bir haber API&#8217;si se\u00e7memiz gerekiyor. Piyasadaki pop\u00fcler se\u00e7eneklerden biri olan News API&#8217;yi veya GNews API&#8217;yi \u00f6rnek alabiliriz. Bu API&#8217;ler genellikle bir API anahtar\u0131 gerektirir. Bu anahtar, API&#8217;ye eri\u015fim yetkinizi do\u011frular ve istek limitlerinizi y\u00f6netir. API anahtar\u0131n\u0131z\u0131 do\u011frudan kod i\u00e7ine yazmak yerine, ortam de\u011fi\u015fkenleri (environment variables) arac\u0131l\u0131\u011f\u0131yla veya bir yap\u0131land\u0131rma dosyas\u0131 kullanarak g\u00fcvenli bir \u015fekilde saklamak en iyi uygulamad\u0131r. B\u00f6ylece, anahtar\u0131n\u0131z\u0131n yanl\u0131\u015fl\u0131kla a\u00e7\u0131k kaynak kod depolar\u0131na s\u0131zmas\u0131n\u0131 \u00f6nlemi\u015f olursunuz.<\/p>\n<p>Veri \u00e7ekme i\u015flemi i\u00e7in Python&#8217;\u0131n <code>requests<\/code> k\u00fct\u00fcphanesini kullanaca\u011f\u0131z. E\u011fer y\u00fckl\u00fc de\u011filse, <code>pip install requests<\/code> komutuyla kolayca y\u00fckleyebilirsiniz. Bu k\u00fct\u00fcphane, HTTP istekleri (GET, POST vb.) g\u00f6ndermeyi ve API yan\u0131tlar\u0131n\u0131 i\u015flemeyi son derece basitle\u015ftirir. Bir haber API&#8217;sinden veri \u00e7ekerken, genellikle belirli parametreler (anahtar kelime, dil, tarih aral\u0131\u011f\u0131, sayfa numaras\u0131 vb.) ile birlikte bir GET iste\u011fi g\u00f6ndeririz. Bu parametreler, API&#8217;nin belgelerinde (documentation) detayl\u0131ca a\u00e7\u0131klan\u0131r.<\/p>\n<p>A\u015fa\u011f\u0131daki \u00f6rnek kod blo\u011fu, bir haber API&#8217;sinden belirli bir anahtar kelimeye g\u00f6re haberleri nas\u0131l \u00e7ekece\u011finizi g\u00f6stermektedir. Burada, <code>NEWS_API_KEY<\/code> ve <code>NEWS_API_URL<\/code> de\u011ferlerinin ortam de\u011fi\u015fkenlerinden al\u0131nd\u0131\u011f\u0131n\u0131 varsay\u0131yoruz:<\/p>\n<div class=\"code-container\">\n<pre><code>\nimport requests\nimport os\nimport time\n\ndef fetch_news_data(query, page_size=100, language='tr'):\n    api_key = os.getenv('NEWS_API_KEY')\n    api_url = os.getenv('NEWS_API_URL', 'https:\/\/newsapi.org\/v2\/everything') # Varsay\u0131lan URL\n    \n    if not api_key:\n        print(\"Hata: NEWS_API_KEY ortam de\u011fi\u015fkeni tan\u0131ml\u0131 de\u011fil.\")\n        return []\n\n    params = {\n        'q': query,\n        'pageSize': page_size,\n        'language': language,\n        'apiKey': api_key\n    }\n    \n    all_articles = []\n    page = 1\n    total_results = 0\n    \n    while True:\n        params['page'] = page\n        print(f\"Haberler \u00e7ekiliyor... Sayfa: {page}\")\n        try:\n            response = requests.get(api_url, params=params, timeout=10)\n            response.raise_for_status() # HTTP hatalar\u0131n\u0131 yakalar (4xx veya 5xx)\n            data = response.json()\n            \n            if not data['articles']:\n                break # Daha fazla makale yoksa d\u00f6ng\u00fcy\u00fc sonland\u0131r\n            \n            all_articles.extend(data['articles'])\n            total_results = data.get('totalResults', 0)\n            \n            # API'nin sayfa limitini veya toplam sonu\u00e7lar\u0131 kontrol et\n            if len(all_articles) >= total_results or page * page_size >= 1000: # News API max 1000 sonu\u00e7\n                break\n            \n            page += 1\n            time.sleep(1) # API limitlerine tak\u0131lmamak i\u00e7in bekletme\n            \n        except requests.exceptions.HTTPError as e:\n            print(f\"HTTP Hatas\u0131: {e}\")\n            if e.response.status_code == 429: # Too Many Requests\n                print(\"API limitine ula\u015f\u0131ld\u0131, biraz bekleyip tekrar denenecek...\")\n                time.sleep(60) # 1 dakika bekle\n                continue\n            break # Di\u011fer HTTP hatalar\u0131nda d\u00f6ng\u00fcy\u00fc sonland\u0131r\n        except requests.exceptions.ConnectionError as e:\n            print(f\"Ba\u011flant\u0131 Hatas\u0131: {e}. A\u011f ba\u011flant\u0131n\u0131z\u0131 kontrol edin.\")\n            break\n        except requests.exceptions.Timeout as e:\n            print(f\"Zaman A\u015f\u0131m\u0131 Hatas\u0131: {e}. \u0130stek zaman\u0131nda tamamlanamad\u0131.\")\n            break\n        except requests.exceptions.RequestException as e:\n            print(f\"Genel \u0130stek Hatas\u0131: {e}\")\n            break\n        except ValueError as e:\n            print(f\"JSON \u00c7\u00f6z\u00fcmleme Hatas\u0131: {e}. API'den beklenen formatta yan\u0131t al\u0131namad\u0131.\")\n            print(f\"Yan\u0131t metni: {response.text[:500]}...\") # Hata durumunda yan\u0131t\u0131n bir k\u0131sm\u0131n\u0131 yazd\u0131r\n            break\n            \n    print(f\"Toplam {len(all_articles)} makale \u00e7ekildi.\")\n    return all_articles\n\nif __name__ == '__main__':\n    # \u00d6rnek kullan\u0131m:\n    # NEWS_API_KEY ve NEWS_API_URL ortam de\u011fi\u015fkenlerini ayarlad\u0131\u011f\u0131n\u0131zdan emin olun.\n    # export NEWS_API_KEY=\"YOUR_API_KEY\"\n    # export NEWS_API_URL=\"https:\/\/newsapi.org\/v2\/everything\"\n    \n    # Yerel olarak test etmek i\u00e7in:\n    # os.environ['NEWS_API_KEY'] = 'YOUR_API_KEY' # Kendi anahtar\u0131n\u0131z\u0131 buraya yaz\u0131n\n    # os.environ['NEWS_API_URL'] = 'https:\/\/newsapi.org\/v2\/everything'\n    \n    news_articles = fetch_news_data('teknoloji')\n    if news_articles:\n        print(f\"\u0130lk makale ba\u015fl\u0131\u011f\u0131: {news_articles[0].get('title')}\")\n    <\/code><\/pre>\n<\/div>\n<p>Yukar\u0131daki kodda, <code>fetch_news_data<\/code> fonksiyonu, belirli bir sorgu (<code>query<\/code>) i\u00e7in haberleri \u00e7eker. <code>os.getenv()<\/code> kullanarak API anahtar\u0131n\u0131 ortam de\u011fi\u015fkeninden al\u0131r. Bu, g\u00fcvenlik a\u00e7\u0131s\u0131ndan \u00f6nemlidir. Ayr\u0131ca, API limitlerine tak\u0131lmamak ve daha fazla veri \u00e7ekebilmek i\u00e7in sayfalama (pagination) mant\u0131\u011f\u0131 ve <code>time.sleep(1)<\/code> ile k\u0131sa bir bekleme s\u00fcresi eklenmi\u015ftir. \u00c7ekilen verinin JSON format\u0131nda oldu\u011funu varsayarak <code>response.json()<\/code> ile Python s\u00f6zl\u00fc\u011f\u00fcne d\u00f6n\u00fc\u015ft\u00fcr\u00fcl\u00fcr.<\/p>\n<p><strong>Hata Y\u00f6netimi ve Yeniden Deneme Mekanizmalar\u0131:<\/strong> Ger\u00e7ek zamanl\u0131 sistemlerde, a\u011f kesintileri, API sunucusunun ge\u00e7ici olarak ula\u015f\u0131lamamas\u0131 veya API limitlerine tak\u0131lma gibi durumlar ka\u00e7\u0131n\u0131lmazd\u0131r. Bu nedenle, sa\u011flam bir hata y\u00f6netimi stratejisi uygulamak hayati \u00f6nem ta\u015f\u0131r. Yukar\u0131daki \u00f6rnekte <code>try-except<\/code> bloklar\u0131 kullan\u0131larak \u00e7e\u015fitli <code>requests.exceptions<\/code> t\u00fcrleri yakalanm\u0131\u015ft\u0131r. \u00d6zellikle <code>requests.exceptions.HTTPError<\/code>, sunucudan gelen 4xx veya 5xx durum kodlar\u0131n\u0131 (\u00f6rne\u011fin, 401 Unauthorized, 404 Not Found, 429 Too Many Requests, 500 Internal Server Error) yakalamak i\u00e7in kritik \u00f6neme sahiptir. E\u011fer bir &#8220;429 Too Many Requests&#8221; hatas\u0131 al\u0131n\u0131rsa, belirli bir s\u00fcre (\u00f6rne\u011fin 60 saniye) bekleyip iste\u011fi yeniden denemek, API limitlerini a\u015fmadan veri \u00e7ekmeye devam etmenin yayg\u0131n bir yoludur. Ba\u011flant\u0131 hatalar\u0131 veya zaman a\u015f\u0131m\u0131 durumlar\u0131 i\u00e7in de uygun mesajlar ve \u00e7\u0131k\u0131\u015f stratejileri belirlenmelidir. Bu t\u00fcr hata y\u00f6netimi, ETL hatt\u0131n\u0131z\u0131n daha dayan\u0131kl\u0131 ve kesintisiz \u00e7al\u0131\u015fmas\u0131n\u0131 sa\u011flar, b\u00f6ylece veri ak\u0131\u015f\u0131n\u0131z\u0131n s\u00fcreklili\u011fi garanti alt\u0131na al\u0131n\u0131r.<\/p>\n<h3>\u00c7ekilen Ham Veriyi PostgreSQL&#8217;e Uygun Hale Getirme (Transform)<\/h3>\n<p>Veri \u00e7ekme (Extract) a\u015famas\u0131ndan sonra elimizde genellikle JSON format\u0131nda, farkl\u0131 yap\u0131 ve kalitede ham haber verileri bulunur. Bu veriyi do\u011frudan bir veritaban\u0131na kaydetmek, gelecekteki analizleri zorla\u015ft\u0131rabilir ve veri kalitesi sorunlar\u0131na yol a\u00e7abilir. \u0130\u015fte bu noktada, &#8220;Transform&#8221; (D\u00f6n\u00fc\u015ft\u00fcrme) a\u015famas\u0131 devreye girer. D\u00f6n\u00fc\u015ft\u00fcrme, ham veriyi temizleme, standartla\u015ft\u0131rma, zenginle\u015ftirme ve PostgreSQL veritaban\u0131m\u0131z\u0131n \u015femas\u0131na uygun hale getirme s\u00fcrecidir. Bu a\u015fama, ETL hatt\u0131n\u0131n en karma\u015f\u0131k ve kritik par\u00e7alar\u0131ndan biridir, \u00e7\u00fcnk\u00fc verinin kalitesi burada belirlenir.<\/p>\n<p>\u00c7ekti\u011fimiz haber verisi genellikle bir liste i\u00e7inde Python s\u00f6zl\u00fckleri (dictionary) \u015feklinde gelir. Her s\u00f6zl\u00fck bir haber makalesini temsil eder ve ba\u015fl\u0131k, yazar, a\u00e7\u0131klama, URL, yay\u0131n tarihi gibi alanlar\u0131 i\u00e7erebilir. Ancak, bu alanlar her zaman bekledi\u011fimiz formatta veya eksiksiz olmayabilir. \u00d6rne\u011fin:<\/p>\n<ul>\n<li><strong>Eksik De\u011ferler:<\/strong> Baz\u0131 haber makalelerinde yazar veya a\u00e7\u0131klama alan\u0131 bo\u015f olabilir. Bu durumlar i\u00e7in ya varsay\u0131lan bir de\u011fer atamam\u0131z ya da bu alanlar\u0131 bo\u015f (NULL) b\u0131rakmam\u0131z gerekebilir.<\/li>\n<li><strong>Veri Tipleri ve Tutarl\u0131l\u0131k:<\/strong> Yay\u0131n tarihi alan\u0131, API&#8217;den farkl\u0131 formatlarda gelebilir (\u00f6rne\u011fin, ISO 8601 format\u0131, farkl\u0131 saat dilimleri). Veritaban\u0131na kaydetmeden \u00f6nce bu tarihleri standart bir formata (\u00f6rne\u011fin, UTC ve belirli bir tarih-saat string format\u0131) d\u00f6n\u00fc\u015ft\u00fcrmemiz gerekir.<\/li>\n<li><strong>Metin Temizli\u011fi:<\/strong> Haber ba\u015fl\u0131klar\u0131 veya i\u00e7erikleri HTML etiketleri, \u00f6zel karakterler veya gereksiz bo\u015fluklar i\u00e7erebilir. Bu t\u00fcr metinleri temizlemek, hem okunabilirli\u011fi art\u0131r\u0131r hem de veritaban\u0131nda depolama ve indeksleme performans\u0131n\u0131 iyile\u015ftirir. Stop words (ve, ile, bir gibi s\u0131k kullan\u0131lan kelimeler) kald\u0131rmak veya k\u00f6k bulma (stemming) i\u015flemleri uygulamak, metin analizleri i\u00e7in veriyi daha kullan\u0131\u015fl\u0131 hale getirebilir.<\/li>\n<li><strong>Veri Zenginle\u015ftirme:<\/strong> Baz\u0131 durumlarda, ham veriye ek bilgiler eklemek isteyebiliriz. \u00d6rne\u011fin, haber metninin duygu analizini yaparak bir &#8220;duygu puan\u0131&#8221; ekleyebiliriz. Ya da haberin dilini otomatik olarak alg\u0131lay\u0131p bir &#8220;dil&#8221; alan\u0131 ekleyebiliriz.<\/li>\n<li><strong>Alan Adland\u0131rmas\u0131:<\/strong> API&#8217;den gelen alan adlar\u0131, veritaban\u0131 \u015femam\u0131zdaki s\u00fctun adlar\u0131yla \u00f6rt\u00fc\u015fmeyebilir. Bu durumda, alan adlar\u0131n\u0131 yeniden e\u015fle\u015ftirmemiz (mapping) gerekir.<\/li>\n<\/ul>\n<p>Python&#8217;da bu d\u00f6n\u00fc\u015f\u00fcm i\u015flemlerini ger\u00e7ekle\u015ftirmek i\u00e7in \u00f6zel fonksiyonlar yazabiliriz. E\u011fer veri hacmi \u00e7ok b\u00fcy\u00fckse veya daha karma\u015f\u0131k d\u00f6n\u00fc\u015f\u00fcmlere ihtiyac\u0131m\u0131z varsa, <code>pandas<\/code> k\u00fct\u00fcphanesi veri \u00e7er\u00e7eveleri (DataFrame) ile g\u00fc\u00e7l\u00fc ve esnek \u00e7\u00f6z\u00fcmler sunar. Ancak, bu \u00f6rnek i\u00e7in daha basit, ad\u0131m ad\u0131m bir yakla\u015f\u0131m izleyece\u011fiz.<\/p>\n<p>A\u015fa\u011f\u0131daki \u00f6rnek kod blo\u011fu, \u00e7ekilen haber makalelerini temizleme ve standartla\u015ft\u0131rma i\u00e7in bir fonksiyonu g\u00f6stermektedir:<\/p>\n<div class=\"code-container\">\n<pre><code>\nimport re\nfrom datetime import datetime\n\ndef clean_and_transform_news(articles):\n    transformed_articles = []\n    for article in articles:\n        # Gerekli alanlar\u0131n varl\u0131\u011f\u0131n\u0131 kontrol et ve varsay\u0131lan de\u011ferler ata\n        title = article.get('title')\n        description = article.get('description')\n        content = article.get('content')\n        url = article.get('url')\n        author = article.get('author')\n        published_at = article.get('publishedAt')\n        source_name = article.get('source', {}).get('name')\n\n        # Ba\u015fl\u0131k veya URL yoksa bu makaleyi atla (kritik alanlar)\n        if not title or not url:\n            continue\n\n        # Metin temizli\u011fi: HTML etiketlerini ve gereksiz bo\u015fluklar\u0131 kald\u0131r\n        def clean_text(text):\n            if text is None:\n                return None\n            # HTML etiketlerini kald\u0131r\n            clean = re.compile('<.*?>')\n            text = re.sub(clean, '', text)\n            # Birden fazla bo\u015flu\u011fu tek bo\u015flu\u011fa indir\n            text = re.sub(r'\\s+', ' ', text).strip()\n            return text\n\n        cleaned_title = clean_text(title)\n        cleaned_description = clean_text(description)\n        cleaned_content = clean_text(content)\n\n        # Tarih format\u0131n\u0131 standartla\u015ft\u0131r\n        standardized_published_at = None\n        if published_at:\n            try:\n                # ISO 8601 format\u0131ndan datetime objesine d\u00f6n\u00fc\u015ft\u00fcr\n                dt_object = datetime.fromisoformat(published_at.replace('Z', '+00:00'))\n                # \u0130stenen string format\u0131na d\u00f6n\u00fc\u015ft\u00fcr (\u00f6rn: YYYY-MM-DD HH:MM:SS)\n                standardized_published_at = dt_object.strftime('%Y-%m-%d %H:%M:%S')\n            except ValueError:\n                print(f\"Uyar\u0131: Ge\u00e7ersiz tarih format\u0131 '{published_at}' i\u00e7in makale: {title}\")\n                # Hata durumunda NULL b\u0131rak veya ba\u015fka bir varsay\u0131lan de\u011fer ata\n                standardized_published_at = None\n\n        # D\u00f6n\u00fc\u015ft\u00fcr\u00fclm\u00fc\u015f makale verilerini bir s\u00f6zl\u00fck olarak topla\n        transformed_article = {\n            'title': cleaned_title,\n            'description': cleaned_description,\n            'content': cleaned_content,\n            'url': url,\n            'author': author if author else 'Bilinmiyor', # Yazar yoksa 'Bilinmiyor' ata\n            'published_at': standardized_published_at,\n            'source_name': source_name,\n            'processed_at': datetime.now().strftime('%Y-%m-%d %H:%M:%S') # \u0130\u015flem zaman\u0131n\u0131 ekle\n        }\n        transformed_articles.append(transformed_article)\n        \n    return transformed_articles\n\nif __name__ == '__main__':\n    # \u00d6rnek ham veri (fetch_news_data fonksiyonundan geldi\u011fini varsayal\u0131m)\n    sample_raw_articles = [\n        {\n            'source': {'id': 'google-news', 'name': 'Google News'},\n            'author': 'John Doe',\n            'title': 'Teknoloji D\u00fcnyas\u0131nda Yeni Bir Geli\u015fme <b>\u00d6nemli<\/b>',\n            'description': 'Bu bir test a\u00e7\u0131klamas\u0131d\u0131r. <a href=\"#\">Daha fazla bilgi<\/a>',\n            'url': 'http:\/\/example.com\/news1',\n            'urlToImage': 'http:\/\/example.com\/image1.jpg',\n            'publishedAt': '2023-10-27T10:30:00Z',\n            'content': 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'\n        },\n        {\n            'source': {'id': None, 'name': 'Bilinmeyen Kaynak'},\n            'author': None,\n            'title': 'Ekonomi Haberleri',\n            'description': 'Piyasalar hareketli.',\n            'url': 'http:\/\/example.com\/news2',\n            'urlToImage': 'http:\/\/example.com\/image2.jpg',\n            'publishedAt': '2023-10-27T11:45:00.000Z', # Farkl\u0131 tarih format\u0131\n            'content': 'Dolar ve Euro y\u00fckseli\u015fte.'\n        },\n        {\n            'source': {'id': None, 'name': 'Lokal Gazete'},\n            'author': 'Jane Smith',\n            'title': None, # Ba\u015fl\u0131k yok\n            'description': 'Bu makale ba\u015fl\u0131\u011f\u0131 eksik.',\n            'url': 'http:\/\/example.com\/news3',\n            'urlToImage': 'http:\/\/example.com\/image3.jpg',\n            'publishedAt': '2023-10-27T12:00:00Z',\n            'content': '\u00d6nemli yerel olaylar.'\n        }\n    ]\n\n    transformed_data = clean_and_transform_news(sample_raw_articles)\n    for article in transformed_data:\n        print(f\"Ba\u015fl\u0131k: {article['title']}, Yazar: {article['author']}, Yay\u0131n Tarihi: {article['published_at']}\")\n    <\/code><\/pre>\n<\/div>\n<p>Bu <code>clean_and_transform_news<\/code> fonksiyonu, her bir haber makalesi \u00fczerinde a\u015fa\u011f\u0131daki d\u00f6n\u00fc\u015f\u00fcmleri ger\u00e7ekle\u015ftirir:<\/p>\n<ul>\n<li>Gerekli alanlar\u0131n (<code>title<\/code>, <code>url<\/code>) varl\u0131\u011f\u0131n\u0131 kontrol eder ve eksikse makaleyi atlar.<\/li>\n<li><code>clean_text<\/code> yard\u0131mc\u0131 fonksiyonu ile metin alanlar\u0131ndaki (ba\u015fl\u0131k, a\u00e7\u0131klama, i\u00e7erik) HTML etiketlerini regex (d\u00fczenli ifadeler) kullanarak kald\u0131r\u0131r ve fazla bo\u015fluklar\u0131 temizler.<\/li>\n<li><code>publishedAt<\/code> alan\u0131n\u0131 ISO 8601 format\u0131ndan Python <code>datetime<\/code> objesine, ard\u0131ndan standart <code>'YYYY-MM-DD HH:MM:SS'<\/code> string format\u0131na d\u00f6n\u00fc\u015ft\u00fcr\u00fcr. Ge\u00e7ersiz tarih formatlar\u0131 i\u00e7in hata y\u00f6netimi i\u00e7erir.<\/li>\n<li>Eksik <code>author<\/code> alanlar\u0131 i\u00e7in &#8216;Bilinmiyor&#8217; gibi varsay\u0131lan bir de\u011fer atar.<\/li>\n<li>Her makale i\u00e7in bir <code>processed_at<\/code> (i\u015flem zaman\u0131) alan\u0131 ekleyerek, verinin ne zaman i\u015flendi\u011fini kaydeder.<\/li>\n<\/ul>\n<p>Bu d\u00f6n\u00fc\u015f\u00fcm a\u015famas\u0131, verinin tutarl\u0131l\u0131\u011f\u0131n\u0131 ve kalitesini art\u0131rarak, bir sonraki ad\u0131m olan veritaban\u0131na y\u00fckleme i\u00e7in ideal bir zemin haz\u0131rlar. Veriyi bu \u015fekilde yap\u0131land\u0131rmak, hem depolama alan\u0131n\u0131 optimize eder hem de gelecekteki sorgular\u0131n ve analizlerin \u00e7ok daha verimli olmas\u0131n\u0131 sa\u011flar. \u00d6zellikle b\u00fcy\u00fck veri hacimleriyle \u00e7al\u0131\u015f\u0131rken, bu t\u00fcr \u00f6n i\u015fleme ad\u0131mlar\u0131, sistem performans\u0131n\u0131 do\u011frudan etkiler.<\/p>\n<h3>PostgreSQL ile Veri Y\u00fckleme (Load) ve Depolama Stratejileri<\/h3>\n<p>ETL hatt\u0131m\u0131z\u0131n son a\u015famas\u0131, &#8220;Load&#8221; (Y\u00fckleme), yani temizlenmi\u015f ve d\u00f6n\u00fc\u015ft\u00fcr\u00fclm\u00fc\u015f haber verilerini kal\u0131c\u0131 olarak bir veritaban\u0131na kaydetmektir. Bu b\u00f6l\u00fcmde, PostgreSQL&#8217;i kullanarak veri y\u00fckleme i\u015flemlerini nas\u0131l ger\u00e7ekle\u015ftirece\u011fimizi, veritaban\u0131 ve tablo \u015femas\u0131 tasar\u0131m\u0131n\u0131, Python&#8217;dan PostgreSQL&#8217;e ba\u011flanmak i\u00e7in <code>psycopg2<\/code> k\u00fct\u00fcphanesini ve veri tekrar\u0131n\u0131 \u00f6nlemek i\u00e7in &#8220;upsert&#8221; (ekle veya g\u00fcncelle) stratejilerini inceleyece\u011fiz.<\/p>\n<p>\u00d6ncelikle, PostgreSQL veritaban\u0131m\u0131zda haber makalelerini depolamak i\u00e7in uygun bir tablo \u015femas\u0131 tasarlamam\u0131z gerekiyor. Bu \u015fema, d\u00f6n\u00fc\u015ft\u00fcrme a\u015famas\u0131nda haz\u0131rlad\u0131\u011f\u0131m\u0131z veri yap\u0131s\u0131yla uyumlu olmal\u0131d\u0131r. A\u015fa\u011f\u0131da, \u00f6rnek bir <code>news_articles<\/code> tablosu i\u00e7in SQL komutu bulunmaktad\u0131r:<\/p>\n<div class=\"code-container\">\n<pre><code>\nCREATE TABLE IF NOT EXISTS news_articles (\n    id SERIAL PRIMARY KEY,\n    title VARCHAR(500) NOT NULL,\n    description TEXT,\n    content TEXT,\n    url VARCHAR(2048) UNIQUE NOT NULL, -- URL'nin benzersiz olmas\u0131n\u0131 sa\u011flar\n    author VARCHAR(255),\n    published_at TIMESTAMP WITH TIME ZONE,\n    source_name VARCHAR(255),\n    processed_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP\n);\n\n-- H\u0131zl\u0131 sorgular i\u00e7in URL ve yay\u0131n tarihi \u00fczerinde indeks olu\u015fturma\nCREATE INDEX IF NOT EXISTS idx_news_articles_url ON news_articles (url);\nCREATE INDEX IF NOT EXISTS idx_news_articles_published_at ON news_articles (published_at);\n  <\/code><\/pre>\n<\/div>\n<p>Bu tablo \u015femas\u0131nda:<\/p>\n<ul>\n<li><code>id<\/code>: Her haber makalesi i\u00e7in otomatik artan benzersiz bir kimlik sa\u011flar.<\/li>\n<li><code>title<\/code>, <code>description<\/code>, <code>content<\/code>, <code>author<\/code>, <code>source_name<\/code>: Metin tabanl\u0131 veriler i\u00e7in uygun VARCHAR veya TEXT tipleri.<\/li>\n<li><code>url<\/code>: Haber makalesinin URL&#8217;si. <code>UNIQUE NOT NULL<\/code> k\u0131s\u0131tlamas\u0131, her URL&#8217;nin benzersiz olmas\u0131n\u0131 garanti eder ve ayn\u0131 haberin birden fazla kez eklenmesini engellemek i\u00e7in kritik \u00f6neme sahiptir.<\/li>\n<li><code>published_at<\/code>, <code>processed_at<\/code>: Tarih ve saat bilgileri i\u00e7in <code>TIMESTAMP WITH TIME ZONE<\/code>. Bu, farkl\u0131 saat dilimlerini do\u011fru bir \u015fekilde y\u00f6netmek i\u00e7in \u00f6nemlidir.<\/li>\n<\/ul>\n<p>Bu tabloyu veritaban\u0131n\u0131zda olu\u015fturduktan sonra, Python&#8217;dan bu tabloya veri y\u00fckleyebiliriz. Python&#8217;dan PostgreSQL&#8217;e ba\u011flanmak i\u00e7in genellikle <code>psycopg2<\/code> k\u00fct\u00fcphanesi kullan\u0131l\u0131r. E\u011fer y\u00fckl\u00fc de\u011filse, <code>pip install psycopg2-binary<\/code> komutuyla y\u00fckleyebilirsiniz. Bu k\u00fct\u00fcphane, veritaban\u0131 ba\u011flant\u0131lar\u0131 kurmay\u0131, SQL sorgular\u0131 y\u00fcr\u00fctmeyi ve i\u015flem y\u00f6netimini sa\u011flar.<\/p>\n<p><strong>Veri Tekrar\u0131n\u0131 \u00d6nleme (Upsert):<\/strong> Ger\u00e7ek zamanl\u0131 haber verileriyle \u00e7al\u0131\u015f\u0131rken, ayn\u0131 haber makalesinin farkl\u0131 zamanlarda tekrar \u00e7ekilmesi olas\u0131d\u0131r. Bunu \u00f6nlemek ve veritaban\u0131m\u0131zda veri tekrar\u0131n\u0131 engellemek i\u00e7in &#8220;upsert&#8221; (INSERT ON CONFLICT) stratejisini kullan\u0131r\u0131z. Bu, bir kay\u0131t zaten mevcutsa (\u00f6rne\u011fin, <code>url<\/code> alan\u0131 benzersiz oldu\u011fu i\u00e7in), kayd\u0131 g\u00fcncelle, aksi takdirde yeni bir kay\u0131t ekle anlam\u0131na gelir. PostgreSQL&#8217;in <code>INSERT ... ON CONFLICT (constraint) DO UPDATE SET ...<\/code> yap\u0131s\u0131 bu i\u015f i\u00e7in idealdir.<\/p>\n<p>A\u015fa\u011f\u0131daki Python kodu, d\u00f6n\u00fc\u015ft\u00fcr\u00fclm\u00fc\u015f haber verilerini PostgreSQL&#8217;e nas\u0131l y\u00fckleyece\u011finizi g\u00f6stermektedir:<\/p>\n<div class=\"code-container\">\n<pre><code>\nimport psycopg2\nimport os\nfrom datetime import datetime\n\ndef load_news_to_postgres(articles):\n    db_name = os.getenv('DB_NAME')\n    db_user = os.getenv('DB_USER')\n    db_password = os.getenv('DB_PASSWORD')\n    db_host = os.getenv('DB_HOST', 'localhost')\n    db_port = os.getenv('DB_PORT', '5432')\n\n    conn = None\n    try:\n        conn = psycopg2.connect(\n            dbname=db_name,\n            user=db_user,\n            password=db_password,\n            host=db_host,\n            port=db_port\n        )\n        cur = conn.cursor()\n\n        # Tablo yoksa olu\u015ftur\n        create_table_sql = \"\"\"\n        CREATE TABLE IF NOT EXISTS news_articles (\n            id SERIAL PRIMARY KEY,\n            title VARCHAR(500) NOT NULL,\n            description TEXT,\n            content TEXT,\n            url VARCHAR(2048) UNIQUE NOT NULL,\n            author VARCHAR(255),\n            published_at TIMESTAMP WITH TIME ZONE,\n            source_name VARCHAR(255),\n            processed_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP\n        );\n        CREATE INDEX IF NOT EXISTS idx_news_articles_url ON news_articles (url);\n        CREATE INDEX IF NOT EXISTS idx_news_articles_published_at ON news_articles (published_at);\n        \"\"\"\n        cur.execute(create_table_sql)\n        conn.commit()\n        print(\"news_articles tablosu kontrol edildi\/olu\u015fturuldu.\")\n\n        insert_count = 0\n        update_count = 0\n\n        for article in articles:\n            # Upsert SQL sorgusu\n            upsert_sql = \"\"\"\n            INSERT INTO news_articles (title, description, content, url, author, published_at, source_name, processed_at)\n            VALUES (%s, %s, %s, %s, %s, %s, %s, %s)\n            ON CONFLICT (url) DO UPDATE SET\n                title = EXCLUDED.title,\n                description = EXCLUDED.description,\n                content = EXCLUDED.content,\n                author = EXCLUDED.author,\n                published_at = EXCLUDED.published_at,\n                source_name = EXCLUDED.source_name,\n                processed_at = EXCLUDED.processed_at;\n            \"\"\"\n            try:\n                cur.execute(upsert_sql, (\n                    article.get('title'),\n                    article.get('description'),\n                    article.get('content'),\n                    article.get('url'),\n                    article.get('author'),\n                    article.get('published_at'),\n                    article.get('source_name'),\n                    article.get('processed_at', datetime.now().strftime('%Y-%m-%d %H:%M:%S'))\n                ))\n                if cur.rowcount == 1: # rowcount 1 ise insert, 0 ise update (PostgreSQL'de bu davran\u0131\u015f farkl\u0131l\u0131k g\u00f6sterebilir)\n                    # Daha kesin bir say\u0131m i\u00e7in ayr\u0131 bir SELECT sorgusu yap\u0131labilir\n                    # veya ON CONFLICT'in d\u00f6nd\u00fcrd\u00fc\u011f\u00fc durumu kontrol etmek gerekir.\n                    # Basit\u00e7e, buradaki her execute bir i\u015flem anlam\u0131na gelir.\n                    pass\n                else:\n                    pass\n            except psycopg2.Error as e:\n                conn.rollback() # Hata durumunda i\u015flemi geri al\n                print(f\"Veri y\u00fckleme hatas\u0131 i\u00e7in URL: {article.get('url')} - {e}\")\n                continue # Bir sonraki makaleye ge\u00e7\n\n        conn.commit() # T\u00fcm ba\u015far\u0131l\u0131 i\u015flemleri onayla\n        print(f\"Toplam {len(articles)} makale i\u015flendi.\")\n\n    except psycopg2.Error as e:\n        print(f\"Veritaban\u0131 ba\u011flant\u0131 veya i\u015flem hatas\u0131: {e}\")\n    finally:\n        if conn:\n            conn.close()\n\nif __name__ == '__main__':\n    # \u00d6rnek kullan\u0131m:\n    # DB_NAME, DB_USER, DB_PASSWORD, DB_HOST ortam de\u011fi\u015fkenlerini ayarlad\u0131\u011f\u0131n\u0131zdan emin olun.\n    # export DB_NAME=\"your_db\"\n    # export DB_USER=\"your_user\"\n    # export DB_PASSWORD=\"your_password\"\n    # export DB_HOST=\"localhost\"\n    \n    # Yerel olarak test etmek i\u00e7in:\n    # os.environ['DB_NAME'] = 'news_db'\n    # os.environ['DB_USER'] = 'postgres'\n    # os.environ['DB_PASSWORD'] = 'password'\n    # os.environ['DB_HOST'] = 'localhost'\n    \n    # \u00d6rnek d\u00f6n\u00fc\u015ft\u00fcr\u00fclm\u00fc\u015f veri (clean_and_transform_news fonksiyonundan geldi\u011fini varsayal\u0131m)\n    sample_transformed_articles = [\n        {\n            'title': 'Teknoloji D\u00fcnyas\u0131nda Yeni Bir Geli\u015fme',\n            'description': 'Bu bir test a\u00e7\u0131klamas\u0131d\u0131r.',\n            'content': 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.',\n            'url': 'http:\/\/example.com\/news1',\n            'author': 'John Doe',\n            'published_at': '2023-10-27 10:30:00',\n            'source_name': 'Google News',\n            'processed_at': '2023-10-27 15:00:00'\n        },\n        {\n            'title': 'Ekonomi Haberleri',\n            'description': 'Piyasalar hareketli.',\n            'content': 'Dolar ve Euro y\u00fckseli\u015fte.',\n            'url': 'http:\/\/example.com\/news2',\n            'author': 'Bilinmiyor',\n            'published_at': '2023-10-27 11:45:00',\n            'source_name': 'Bilinmeyen Kaynak',\n            'processed_at': '2023-10-27 15:01:00'\n        },\n        {\n            'title': 'G\u00fcncel Politika Geli\u015fmeleri',\n            'description': '\u00dclke g\u00fcndemi hareketli.',\n            'content': 'Se\u00e7im s\u00fcreci devam ediyor.',\n            'url': 'http:\/\/example.com\/news4', # Yeni bir haber\n            'author': 'Ay\u015fe Y\u0131lmaz',\n            'published_at': '2023-10-27 13:00:00',\n            'source_name': 'Haber Ajans\u0131',\n            'processed_at': '2023-10-27 15:02:00'\n        }\n    ]\n\n    load_news_to_postgres(sample_transformed_articles)\n    <\/code><\/pre>\n<\/div>\n<p><code>load_news_to_postgres<\/code> fonksiyonu, veritaban\u0131 ba\u011flant\u0131 bilgilerini ortam de\u011fi\u015fkenlerinden al\u0131r. Bu yine g\u00fcvenlik i\u00e7in \u00f6nemli bir yakla\u015f\u0131md\u0131r. Veritaban\u0131na ba\u011fland\u0131ktan sonra, imle\u00e7 (cursor) arac\u0131l\u0131\u011f\u0131yla SQL sorgular\u0131 y\u00fcr\u00fct\u00fcl\u00fcr. \u0130lk olarak, <code>news_articles<\/code> tablosunun varl\u0131\u011f\u0131n\u0131 kontrol eder ve yoksa olu\u015fturur. Ard\u0131ndan, her bir haber makalesi i\u00e7in <code>INSERT ... ON CONFLICT (url) DO UPDATE SET ...<\/code> sorgusunu \u00e7al\u0131\u015ft\u0131r\u0131r. Bu sorgu, <code>url<\/code> de\u011feri zaten mevcutsa kayd\u0131 g\u00fcnceller, aksi takdirde yeni bir kay\u0131t ekler. Bu sayede, ayn\u0131 haberin birden fazla kez kaydedilmesi engellenir. Her bir i\u015flemden sonra <code>conn.commit()<\/code> ile de\u011fi\u015fiklikler veritaban\u0131na kal\u0131c\u0131 olarak kaydedilir. Hata durumlar\u0131nda ise <code>conn.rollback()<\/code> ile i\u015flemler geri al\u0131n\u0131r ve hatan\u0131n veritaban\u0131 b\u00fct\u00fcnl\u00fc\u011f\u00fcn\u00fc bozmas\u0131 engellenir.<\/p>\n<p>Bu y\u00fckleme a\u015famas\u0131, ETL hatt\u0131m\u0131z\u0131n son ad\u0131m\u0131 olup, t\u00fcm verinin g\u00fcvenli, yap\u0131land\u0131r\u0131lm\u0131\u015f ve sorgulanabilir bir \u015fekilde depolanmas\u0131n\u0131 sa\u011flar. Art\u0131k veritaban\u0131m\u0131zdaki haber verilerini analiz, raporlama veya di\u011fer uygulamalar i\u00e7in kullanabiliriz.<\/p>\n<h3>ETL Hatt\u0131n\u0131 Otomatikle\u015ftirme ve \u0130zleme<\/h3>\n<p>Bir ETL hatt\u0131n\u0131n ger\u00e7ek potansiyeli, manuel m\u00fcdahale olmadan d\u00fczenli aral\u0131klarla \u00e7al\u0131\u015fabilmesinde yatar. Ger\u00e7ek zamanl\u0131 haber verilerini s\u00fcrekli olarak \u00e7ekmek, i\u015flemek ve depolamak i\u00e7in bu hatt\u0131 otomatikle\u015ftirmemiz ve olas\u0131 sorunlar\u0131 h\u0131zl\u0131ca tespit edebilmek i\u00e7in izlememiz gerekir. Otomasyon, insan hatas\u0131n\u0131 azalt\u0131r, verimlili\u011fi art\u0131r\u0131r ve verinin s\u00fcrekli g\u00fcncel kalmas\u0131n\u0131 sa\u011flar.<\/p>\n<p><strong>Zamanlama (Scheduling):<\/strong> ETL hatt\u0131n\u0131 belirli aral\u0131klarla \u00e7al\u0131\u015ft\u0131rman\u0131n birka\u00e7 yolu vard\u0131r:<\/p>\n<ul>\n<li><strong>Cron (Linux\/Unix sistemleri i\u00e7in):<\/strong> Basit ve yayg\u0131n bir zamanlama arac\u0131d\u0131r. Belirli bir Python beti\u011fini dakikal\u0131k, saatlik, g\u00fcnl\u00fck veya haftal\u0131k olarak \u00e7al\u0131\u015ft\u0131rmak i\u00e7in kullan\u0131labilir. \u00d6rne\u011fin, her 15 dakikada bir haber \u00e7ekme beti\u011fini \u00e7al\u0131\u015ft\u0131rmak i\u00e7in cron tab&#8217;a bir giri\u015f ekleyebilirsiniz.\n<div class=\"code-container\">\n<pre><code>\n*\/15 * * * * \/usr\/bin\/python3 \/path\/to\/your\/etl_script.py\n          <\/code><\/pre>\n<\/p><\/div>\n<p>        Bu komut, her 15 dakikada bir <code>etl_script.py<\/code> dosyas\u0131n\u0131 \u00e7al\u0131\u015ft\u0131r\u0131r. Ancak, cron&#8217;un hata y\u00f6netimi ve i\u015f ak\u0131\u015f\u0131 ba\u011f\u0131ml\u0131l\u0131klar\u0131 konusunda s\u0131n\u0131rlamalar\u0131 vard\u0131r.<\/li>\n<li><strong>Apache Airflow:<\/strong> Daha karma\u015f\u0131k ETL i\u015f ak\u0131\u015flar\u0131 i\u00e7in end\u00fcstri standard\u0131 bir \u00e7\u00f6z\u00fcmd\u00fcr. Airflow, i\u015f ak\u0131\u015flar\u0131n\u0131 (DAG &#8211; Directed Acyclic Graph) kod olarak tan\u0131mlaman\u0131za, ba\u011f\u0131ml\u0131l\u0131klar\u0131 y\u00f6netmenize, yeniden denemeleri yap\u0131land\u0131rman\u0131za ve i\u015flerin durumunu g\u00f6rsel olarak izlemenize olanak tan\u0131r. Farkl\u0131 g\u00f6revler (API&#8217;den \u00e7ekme, veriyi temizleme, veritaban\u0131na y\u00fckleme) aras\u0131nda ba\u011f\u0131ml\u0131l\u0131klar kurarak, bir g\u00f6revin ba\u015far\u0131l\u0131 tamamlanmas\u0131n\u0131n di\u011ferini tetiklemesini sa\u011flayabilirsiniz. Bu, \u00f6zellikle b\u00fcy\u00fck ve \u00e7ok ad\u0131ml\u0131 ETL s\u00fcre\u00e7leri i\u00e7in \u00e7ok daha sa\u011flam bir \u00e7\u00f6z\u00fcmd\u00fcr.<\/li>\n<li><strong>Celery (Python i\u00e7in):<\/strong> E\u011fer daha \u00e7ok mikroservis mimarisi veya arka plan g\u00f6revleri \u00fczerinde \u00e7al\u0131\u015f\u0131yorsan\u0131z, Celery gibi bir da\u011f\u0131t\u0131k g\u00f6rev kuyru\u011fu kullanabilirsiniz. Celery, asenkron g\u00f6revleri zamanlaman\u0131za ve y\u00fcr\u00fctmenize olanak tan\u0131r, bu da onu yo\u011fun I\/O i\u015flemleri gerektiren veri \u00e7ekme g\u00f6revleri i\u00e7in uygun hale getirir.<\/li>\n<\/ul>\n<p>K\u00fc\u00e7\u00fck \u00f6l\u00e7ekli projeler i\u00e7in cron yeterli olabilirken, daha b\u00fcy\u00fck, kurumsal d\u00fczeyde ETL hatlar\u0131 i\u00e7in Airflow gibi \u00e7\u00f6z\u00fcmler, i\u015f ak\u0131\u015f\u0131 y\u00f6netimini ve \u00f6l\u00e7eklenebilirli\u011fi art\u0131r\u0131r.<\/p>\n<p><strong>Hata G\u00fcnl\u00fc\u011f\u00fc (Logging) ve Uyar\u0131 Sistemleri:<\/strong> Bir ETL hatt\u0131 otomatik olarak \u00e7al\u0131\u015f\u0131rken, sorunlar ortaya \u00e7\u0131kt\u0131\u011f\u0131nda bundan haberdar olmak hayati \u00f6nem ta\u015f\u0131r. Python&#8217;\u0131n yerle\u015fik <code>logging<\/code> mod\u00fcl\u00fc, beti\u011finizdeki olaylar\u0131 (bilgi mesajlar\u0131, uyar\u0131lar, hatalar) kaydetmek i\u00e7in g\u00fc\u00e7l\u00fc bir ara\u00e7t\u0131r. Loglar\u0131 bir dosyaya yazmak veya merkezi bir log y\u00f6netim sistemine (ELK Stack, Grafana Loki vb.) g\u00f6ndermek, sorun giderme ve sistemin genel sa\u011fl\u0131\u011f\u0131n\u0131 izlemek i\u00e7in \u00f6nemlidir.<\/p>\n<div class=\"code-container\">\n<pre><code>\nimport logging\n\n# Loglama yap\u0131land\u0131rmas\u0131\nlogging.basicConfig(\n    level=logging.INFO,\n    format='%(asctime)s - %(levelname)s - %(message)s',\n    handlers=[\n        logging.FileHandler(\"etl_pipeline.log\"),\n        logging.StreamHandler()\n    ]\n)\n\n# \u00d6rnek kullan\u0131m\nlogging.info(\"ETL hatt\u0131 \u00e7al\u0131\u015fmaya ba\u015flad\u0131.\")\ntry:\n    # Veri \u00e7ekme i\u015flemi\n    # ...\n    logging.info(\"Veri \u00e7ekme i\u015flemi tamamland\u0131.\")\nexcept Exception as e:\n    logging.error(f\"Veri \u00e7ekme s\u0131ras\u0131nda hata olu\u015ftu: {e}\", exc_info=True)\n    # Hata durumunda bildirim g\u00f6nder (e-posta, Slack vb.)\n    \nlogging.info(\"ETL hatt\u0131 tamamland\u0131.\")\n  <\/code><\/pre>\n<\/div>\n<p>Sadece loglamak yeterli de\u011fildir; kritik hatalar veya anormal durumlar olu\u015ftu\u011funda uyar\u0131 alman\u0131z gerekir. Bu, e-posta, Slack, Telegram veya PagerDuty gibi ara\u00e7lar arac\u0131l\u0131\u011f\u0131yla otomatik bildirimler g\u00f6nderilerek yap\u0131labilir. \u00d6rne\u011fin, bir API iste\u011fi art arda belirli say\u0131da hata d\u00f6nd\u00fcrd\u00fc\u011f\u00fcnde veya veritaban\u0131na y\u00fcklenen kay\u0131t say\u0131s\u0131 beklenenin alt\u0131na d\u00fc\u015ft\u00fc\u011f\u00fcnde bir uyar\u0131 tetikleyebilirsiniz. Bu t\u00fcr uyar\u0131 sistemleri, sorunlara proaktif bir \u015fekilde m\u00fcdahale etmenizi sa\u011flar ve veri ak\u0131\u015f\u0131n\u0131z\u0131n kesintiye u\u011framamas\u0131n\u0131 garanti eder.<\/p>\n<p><strong>Performans Optimizasyonu \u0130pu\u00e7lar\u0131:<\/strong> \u00d6l\u00e7eklenebilirlik, ger\u00e7ek zamanl\u0131 veri i\u015fleme sistemleri i\u00e7in \u00f6nemli bir konudur. Performans\u0131 art\u0131rmak i\u00e7in baz\u0131 ipu\u00e7lar\u0131:<\/p>\n<ul>\n<li><strong>Toplu \u0130\u015flemler (Batch Processing):<\/strong> Her bir haber makalesini tek tek veritaban\u0131na eklemek yerine, belirli bir say\u0131da makaleyi (\u00f6rne\u011fin 100 veya 1000) bir araya getirip tek bir i\u015flemde (transaction) y\u00fcklemek, veritaban\u0131 I\/O y\u00fck\u00fcn\u00fc \u00f6nemli \u00f6l\u00e7\u00fcde azalt\u0131r ve performans\u0131 art\u0131r\u0131r. <code>psycopg2<\/code> ile <code>executemany<\/code> fonksiyonu bu i\u015f i\u00e7in kullan\u0131labilir.<\/li>\n<li><strong>Asenkron \u0130\u015flemler:<\/strong> \u00d6zellikle veri \u00e7ekme a\u015famas\u0131nda, birden fazla API iste\u011fini ayn\u0131 anda asenkron olarak yapmak, toplam \u00e7ekme s\u00fcresini k\u0131saltabilir. Python&#8217;\u0131n <code>asyncio<\/code> ve <code>aiohttp<\/code> k\u00fct\u00fcphaneleri bu konuda yard\u0131mc\u0131 olabilir.<\/li>\n<li><strong>Veritaban\u0131 \u0130ndeksleri:<\/strong> Do\u011fru indekslerin (\u00f6zellikle <code>url<\/code> ve <code>published_at<\/code> gibi s\u0131k\u00e7a sorgulanan alanlarda) olu\u015fturulmas\u0131, veri okuma ve &#8220;upsert&#8221; i\u015flemlerinin h\u0131z\u0131n\u0131 art\u0131r\u0131r.<\/li>\n<li><strong>Kaynak Y\u00f6netimi:<\/strong> Veritaban\u0131 ba\u011flant\u0131lar\u0131n\u0131 do\u011fru \u015fekilde a\u00e7\u0131p kapatmak veya ba\u011flant\u0131 havuzu (connection pool) kullanmak, ba\u011flant\u0131 kurma maliyetini azalt\u0131r.<\/li>\n<li><strong>Veri S\u0131k\u0131\u015ft\u0131rma:<\/strong> B\u00fcy\u00fck metin alanlar\u0131 (<code>content<\/code>) depolarken, e\u011fer veritaban\u0131 destekliyorsa veya uygulama seviyesinde s\u0131k\u0131\u015ft\u0131rma uygulamak, depolama alan\u0131n\u0131 ve I\/O performans\u0131n\u0131 iyile\u015ftirebilir.<\/li>\n<\/ul>\n<p>Bu otomasyon ve izleme stratejileri, ETL hatt\u0131n\u0131z\u0131n sadece \u00e7al\u0131\u015fmas\u0131n\u0131 de\u011fil, ayn\u0131 zamanda g\u00fcvenilir, verimli ve y\u00f6netilebilir olmas\u0131n\u0131 sa\u011flar. Bu sayede, s\u00fcrekli akan haber verilerinden maksimum fayday\u0131 elde edebilirsiniz.<\/p>\n<h3>Ger\u00e7ek D\u00fcnya Senaryolar\u0131 ve \u0130leri D\u00fczey Uygulamalar<\/h3>\n<p>\u015eimdiye kadar olu\u015fturdu\u011fumuz ETL hatt\u0131, ger\u00e7ek zamanl\u0131 haber verilerini \u00e7ekmek, d\u00f6n\u00fc\u015ft\u00fcrmek ve PostgreSQL veritaban\u0131na y\u00fcklemek i\u00e7in sa\u011flam bir temel sunuyor. Ancak bu hatt\u0131n ger\u00e7ek de\u011feri, toplanan verilerin farkl\u0131 i\u015f senaryolar\u0131nda nas\u0131l kullan\u0131labilece\u011fi ve ileri d\u00fczey analizlerle nas\u0131l zenginle\u015ftirilebilece\u011fidir. \u0130\u015fte baz\u0131 ger\u00e7ek d\u00fcnya senaryolar\u0131 ve bu ETL hatt\u0131n\u0131 daha da g\u00fc\u00e7lendirecek ileri d\u00fczey uygulamalar:<\/p>\n<p><strong>Duygu Analizi Entegrasyonu:<\/strong> Haberler sadece olaylar\u0131 bildirmekle kalmaz, ayn\u0131 zamanda belirli konular veya markalar hakk\u0131ndaki kamuoyunun duygu durumunu da yans\u0131t\u0131r. Toplad\u0131\u011f\u0131m\u0131z haber makalelerinin ba\u015fl\u0131klar\u0131 ve i\u00e7erikleri \u00fczerinde duygu analizi (sentiment analysis) yaparak, bir markan\u0131n itibar\u0131n\u0131, bir \u00fcr\u00fcn\u00fcn alg\u0131s\u0131n\u0131 veya belirli bir olay\u0131n toplumsal tepkisini \u00f6l\u00e7ebiliriz. Python&#8217;da NLTK, TextBlob veya spaCy gibi k\u00fct\u00fcphaneler, temel duygu analizi i\u00e7in kullan\u0131labilir. Daha geli\u015fmi\u015f modeller i\u00e7in, \u00f6nceden e\u011fitilmi\u015f makine \u00f6\u011frenimi modelleri (\u00f6rne\u011fin, BERT tabanl\u0131 modeller) veya bulut tabanl\u0131 NLP (Do\u011fal Dil \u0130\u015fleme) servisleri (Google Cloud NLP, AWS Comprehend) entegre edilebilir. Duygu analizi sonu\u00e7lar\u0131n\u0131 (pozitif, negatif, n\u00f6tr skorlar\u0131) veritaban\u0131m\u0131zdaki <code>news_articles<\/code> tablosuna yeni s\u00fctunlar olarak ekleyebiliriz. \u00d6rne\u011fin, bir \u015firket, yeni \u00fcr\u00fcn lansman\u0131 sonras\u0131 haberlerdeki duygu skorlar\u0131n\u0131 takip ederek pazarlama stratejilerini an\u0131nda ayarlayabilir.<\/p>\n<div class=\"code-container\">\n<pre><code>\nfrom textblob import TextBlob\n\ndef analyze_sentiment(text):\n    if text is None:\n        return 0.0, 0.0 # Polarity, Subjectivity\n    analysis = TextBlob(text)\n    # Polarity: -1.0 (negatif) ile +1.0 (pozitif) aras\u0131\n    # Subjectivity: 0.0 (nesnel) ile +1.0 (\u00f6znel) aras\u0131\n    return analysis.sentiment.polarity, analysis.sentiment.subjectivity\n\n# D\u00f6n\u00fc\u015ft\u00fcrme a\u015famas\u0131nda bu fonksiyonu \u00e7a\u011f\u0131rabiliriz:\n# transformed_article['sentiment_polarity'], transformed_article['sentiment_subjectivity'] = analyze_sentiment(cleaned_content)\n  <\/code><\/pre>\n<\/div>\n<p><strong>Makine \u00d6\u011frenimi i\u00e7in Veri Haz\u0131rl\u0131\u011f\u0131:<\/strong> Toplad\u0131\u011f\u0131m\u0131z ve i\u015fledi\u011fimiz haber verileri, \u00e7e\u015fitli makine \u00f6\u011frenimi modelleri i\u00e7in m\u00fckemmel bir e\u011fitim seti olu\u015fturabilir. \u00d6rne\u011fin:<\/p>\n<ul>\n<li><strong>Haber Kategorizasyonu:<\/strong> Haberleri otomatik olarak \u00f6nceden tan\u0131mlanm\u0131\u015f kategorilere (spor, politika, teknoloji vb.) ay\u0131rmak i\u00e7in bir s\u0131n\u0131fland\u0131rma modeli e\u011fitebiliriz. Bu, b\u00fcy\u00fck hacimli haberleri y\u00f6netmeyi ve ilgili haberleri h\u0131zl\u0131ca bulmay\u0131 kolayla\u015ft\u0131r\u0131r.<\/li>\n<li><strong>Konu Modelleme (Topic Modeling):<\/strong> Haber metinlerinden gizli konular\u0131 ke\u015ffetmek i\u00e7in LDA (Latent Dirichlet Allocation) gibi algoritmalar kullan\u0131labilir. Bu, trendleri veya belirli bir zaman dilimindeki ana tart\u0131\u015fma konular\u0131n\u0131 belirlemeye yard\u0131mc\u0131 olur.<\/li>\n<li><strong>\u00d6zetleme:<\/strong> Uzun haber makalelerini otomatik olarak \u00f6zetleyen modeller geli\u015ftirmek, kullan\u0131c\u0131lar\u0131n h\u0131zl\u0131ca bilgi edinmesini sa\u011flayabilir.<\/li>\n<\/ul>\n<p>Bu t\u00fcr modelleri e\u011fitmek i\u00e7in, ETL hatt\u0131m\u0131zdan gelen temizlenmi\u015f ve yap\u0131land\u0131r\u0131lm\u0131\u015f metin verileri (ba\u015fl\u0131k, a\u00e7\u0131klama, i\u00e7erik) kullan\u0131l\u0131r. Veritaban\u0131m\u0131z, bu modeller i\u00e7in g\u00fcvenilir bir veri kayna\u011f\u0131 g\u00f6revi g\u00f6r\u00fcr.<\/p>\n<p><strong>B\u00fcy\u00fck Veri Hacimleri i\u00e7in \u00d6l\u00e7eklendirme:<\/strong> E\u011fer g\u00fcnl\u00fck \u00e7ekilen haber makalesi say\u0131s\u0131 milyonlara ula\u015f\u0131yorsa, tek bir PostgreSQL \u00f6rne\u011fi ve Python beti\u011fi yeterli olmayabilir. Bu durumda, ETL hatt\u0131m\u0131z\u0131 \u00f6l\u00e7eklendirmek i\u00e7in farkl\u0131 stratejiler d\u00fc\u015f\u00fcnmemiz gerekir:<\/p>\n<ul>\n<li><strong>Da\u011f\u0131t\u0131k Veritabanlar\u0131:<\/strong> PostgreSQL&#8217;in yatay \u00f6l\u00e7eklenmesini sa\u011flamak i\u00e7in CitusData gibi eklentiler veya Greenplum gibi da\u011f\u0131t\u0131k veritaban\u0131 \u00e7\u00f6z\u00fcmleri kullan\u0131labilir.<\/li>\n<li><strong>Veri Ambarlar\u0131:<\/strong> Analitik sorgular i\u00e7in optimize edilmi\u015f, s\u00fctun tabanl\u0131 (columnar) veri ambarlar\u0131 (\u00f6rne\u011fin, Apache Druid, ClickHouse, Snowflake) kullan\u0131labilir. Bu, \u00f6zellikle b\u00fcy\u00fck veri k\u00fcmeleri \u00fczerinde karma\u015f\u0131k analitik sorgular\u0131n performans\u0131n\u0131 art\u0131r\u0131r.<\/li>\n<li><strong>Ak\u0131\u015f \u0130\u015fleme (Stream Processing):<\/strong> Ger\u00e7ek zamanl\u0131l\u0131\u011f\u0131n kritik oldu\u011fu durumlarda, Apache Kafka gibi mesaj kuyruklar\u0131 ile veri ak\u0131\u015f\u0131n\u0131 y\u00f6netebilir ve Apache Flink veya Apache Spark Streaming gibi ara\u00e7larla veriyi anl\u0131k olarak i\u015fleyebiliriz. Bu, haberler gelir gelmez an\u0131nda i\u015flenmesini ve analiz edilmesini sa\u011flar.<\/li>\n<li><strong>Bulut Hizmetleri:<\/strong> AWS Glue, Google Cloud Dataflow veya Azure Data Factory gibi bulut tabanl\u0131 ETL servisleri, altyap\u0131 y\u00f6netimi y\u00fck\u00fcn\u00fc azaltarak \u00f6l\u00e7eklenebilir ve y\u00f6netilebilir ETL \u00e7\u00f6z\u00fcmleri sunar.<\/li>\n<\/ul>\n<p>Bu ileri d\u00fczey uygulamalar ve \u00f6l\u00e7eklendirme stratejileri, temel ETL hatt\u0131m\u0131z\u0131 daha g\u00fc\u00e7l\u00fc, esnek ve farkl\u0131 i\u015f ihtiya\u00e7lar\u0131na cevap verebilen bir veri platformuna d\u00f6n\u00fc\u015ft\u00fcr\u00fcr. Haber verisi, sadece bir bilgi ak\u0131\u015f\u0131 olmaktan \u00e7\u0131k\u0131p, stratejik karar alma s\u00fcre\u00e7lerini destekleyen de\u011ferli bir varl\u0131k haline gelir.<\/p>\n<h3>Sonu\u00e7 ve Gelecek Perspektifleri<\/h3>\n<p>Bu makalede, ger\u00e7ek zamanl\u0131 haber verilerini Python ve PostgreSQL kullanarak \u00e7ekmek, d\u00f6n\u00fc\u015ft\u00fcrmek ve depolamak i\u00e7in sa\u011flam bir ETL hatt\u0131 olu\u015fturman\u0131n t\u00fcm ad\u0131mlar\u0131n\u0131 detayl\u0131ca inceledik. &#8220;Extract&#8221; a\u015famas\u0131nda Python&#8217;\u0131n <code>requests<\/code> k\u00fct\u00fcphanesi ile haber API&#8217;lerinden nas\u0131l veri \u00e7ekilece\u011fini, kimlik do\u011frulama ve hata y\u00f6netimi stratejilerini \u00f6\u011frendik. &#8220;Transform&#8221; a\u015famas\u0131nda, \u00e7ekilen ham veriyi temizleme, standartla\u015ft\u0131rma ve zenginle\u015ftirme tekniklerini, \u00f6zellikle metin temizli\u011fi ve tarih format\u0131 d\u00f6n\u00fc\u015f\u00fcmlerini ele ald\u0131k. Son olarak, &#8220;Load&#8221; a\u015famas\u0131nda PostgreSQL&#8217;de uygun bir tablo \u015femas\u0131 tasarlayarak ve <code>psycopg2<\/code> ile &#8220;upsert&#8221; mekanizmas\u0131n\u0131 kullanarak veriyi g\u00fcvenli ve tekrar etmeyecek \u015fekilde nas\u0131l depolayaca\u011f\u0131m\u0131z\u0131 g\u00f6sterdik. Ayr\u0131ca, bu hatt\u0131 otomatikle\u015ftirme ve izleme y\u00f6ntemlerini ve duygu analizi, makine \u00f6\u011frenimi i\u00e7in veri haz\u0131rl\u0131\u011f\u0131 gibi ileri d\u00fczey uygulamalar\u0131 da tart\u0131\u015ft\u0131k.<\/p>\n<p>Olu\u015fturdu\u011fumuz bu ETL hatt\u0131, kurumlar\u0131n ve bireylerin s\u00fcrekli akan bilgi okyanusundan anlaml\u0131 veriler \u00e7\u0131karmas\u0131na olanak tan\u0131r. Finansal piyasalar\u0131 takip etmekten, marka itibar\u0131n\u0131 y\u00f6netmeye, akademik ara\u015ft\u0131rmalardan, rekabet analizi yapmaya kadar bir\u00e7ok alanda de\u011ferli i\u00e7g\u00f6r\u00fcler sunar. Bilgiye an\u0131nda eri\u015fim ve bu bilgiyi i\u015fleme yetene\u011fi, g\u00fcn\u00fcm\u00fcz\u00fcn h\u0131zla de\u011fi\u015fen d\u00fcnyas\u0131nda bir rekabet avantaj\u0131 sa\u011flamaktad\u0131r.<\/p>\n<p>Gelecekte, bu ETL hatt\u0131n\u0131 daha da geli\u015ftirmek i\u00e7in bir\u00e7ok yol bulunmaktad\u0131r. \u00d6rne\u011fin, farkl\u0131 veri kaynaklar\u0131n\u0131 (sosyal medya, bloglar) entegre ederek veri kapsam\u0131n\u0131 geni\u015fletebilir, daha geli\u015fmi\u015f do\u011fal dil i\u015fleme (NLP) teknikleri kullanarak (varl\u0131k tan\u0131ma, metin \u00f6zetleme) veriyi daha da zenginle\u015ftirebiliriz. B\u00fcy\u00fck veri teknolojileriyle (Kafka, Spark) entegrasyon, hatt\u0131n daha y\u00fcksek hacimli ve daha h\u0131zl\u0131 veri ak\u0131\u015flar\u0131n\u0131 y\u00f6netmesini sa\u011flayabilir. Ayr\u0131ca, toplanan verileri interaktif panolar (\u00f6rne\u011fin, Grafana, Metabase) arac\u0131l\u0131\u011f\u0131yla g\u00f6rselle\u015ftirmek, karar vericilerin i\u00e7g\u00f6r\u00fclere daha kolay ula\u015fmas\u0131n\u0131 sa\u011flayacakt\u0131r. Veri m\u00fchendisli\u011fi, s\u00fcrekli \u00f6\u011frenmeyi ve yeni teknolojilere adapte olmay\u0131 gerektiren dinamik bir aland\u0131r ve bu ETL hatt\u0131, bu yolculukta sa\u011flam bir ba\u015flang\u0131\u00e7 noktas\u0131 sunmaktad\u0131r.<\/p>\n<h3>S\u0131k\u00e7a Sorulan Sorular<\/h3>\n<ul>\n<li>\n        <strong>ETL hatt\u0131 kurmak neden bu kadar \u00f6nemli?<\/strong><\/p>\n<p>ETL hatt\u0131, farkl\u0131 ve da\u011f\u0131n\u0131k kaynaklardan gelen ham veriyi, analiz ve karar verme s\u00fcre\u00e7leri i\u00e7in kullan\u0131labilir, temiz ve yap\u0131land\u0131r\u0131lm\u0131\u015f bir formata d\u00f6n\u00fc\u015ft\u00fcrerek veri kalitesini ve tutarl\u0131l\u0131\u011f\u0131n\u0131 sa\u011flar. Bu, do\u011fru ve zaman\u0131nda al\u0131nan kararlar i\u00e7in temel olu\u015fturur.<\/p>\n<\/li>\n<li>\n        <strong>Python ve PostgreSQL yerine ba\u015fka teknolojiler kullan\u0131labilir mi?<\/strong><\/p>\n<p>Kesinlikle. Python ve PostgreSQL pop\u00fcler ve g\u00fc\u00e7l\u00fc se\u00e7enekler olsa da, veri \u00e7ekme i\u00e7in Node.js veya Java, veritaban\u0131 olarak MySQL, MongoDB veya bulut tabanl\u0131 veri ambarlar\u0131 (Snowflake, BigQuery) kullan\u0131labilir. Se\u00e7im, projenin \u00f6zel gereksinimlerine, mevcut altyap\u0131ya ve ekibin yetkinliklerine ba\u011fl\u0131d\u0131r.<\/p>\n<\/li>\n<li>\n        <strong>Ger\u00e7ek zamanl\u0131 veri ne kadar &#8220;ger\u00e7ek zamanl\u0131&#8221; olmal\u0131?<\/strong><\/p>\n<p>&#8220;Ger\u00e7ek zamanl\u0131&#8221; terimi, projenin ihtiya\u00e7lar\u0131na g\u00f6re de\u011fi\u015fir. Baz\u0131 senaryolarda dakikalar i\u00e7indeki gecikme kabul edilebilirken, finansal ticaret gibi alanlarda milisaniyeler bile kritik olabilir. Haber verisi i\u00e7in genellikle birka\u00e7 dakikal\u0131k gecikme &#8220;ger\u00e7ek zamanl\u0131&#8221; kabul edilebilir, ancak bu, kullan\u0131lan API&#8217;nin h\u0131z\u0131na ve ETL hatt\u0131n\u0131n i\u015fleme kapasitesine ba\u011fl\u0131d\u0131r.<\/p>\n<\/li>\n<li>\n        <strong>API limitleriyle nas\u0131l ba\u015fa \u00e7\u0131kabilirim?<\/strong><\/p>\n<p>API limitleri, veri \u00e7ekme s\u00fcrecinde s\u0131k\u00e7a kar\u015f\u0131la\u015f\u0131lan bir sorundur. \u00c7\u00f6z\u00fcmler aras\u0131nda API sa\u011flay\u0131c\u0131s\u0131yla ileti\u015fime ge\u00e7erek limitleri art\u0131rmak, birden fazla API anahtar\u0131 kullanmak (e\u011fer izin veriliyorsa), istekler aras\u0131na gecikmeler (<code>time.sleep()<\/code>) eklemek, ba\u015far\u0131s\u0131z istekler i\u00e7in yeniden deneme mant\u0131\u011f\u0131 uygulamak ve veriyi daha az s\u0131kl\u0131kta \u00e7ekmek yer al\u0131r.<\/p>\n<\/li>\n<li>\n        <strong>Veritaban\u0131nda veri tekrar\u0131n\u0131 \u00f6nlemek i\u00e7in ba\u015fka y\u00f6ntemler var m\u0131?<\/strong><\/p>\n<p>Evet, &#8220;upsert&#8221; (INSERT ON CONFLICT) d\u0131\u015f\u0131nda, Python taraf\u0131nda \u00e7ekilen veriyi veritaban\u0131na y\u00fcklemeden \u00f6nce mevcut kay\u0131tlarla kar\u015f\u0131la\u015ft\u0131r\u0131p sadece yeni veya g\u00fcncellenmi\u015f kay\u0131tlar\u0131 eklemek de bir y\u00f6ntemdir. Ancak, b\u00fcy\u00fck veri k\u00fcmelerinde bu yakla\u015f\u0131m daha fazla a\u011f trafi\u011fi ve i\u015fleme y\u00fck\u00fc yaratabilir. Veritaban\u0131 seviyesindeki &#8220;upsert&#8221; genellikle daha performansl\u0131d\u0131r.<\/p>\n<\/li>\n<\/ul>\n<p>#ETLPipeline #Python #PostgreSQL #VeriM\u00fchendisli\u011fi #Ger\u00e7ekZamanl\u0131Veri #HaberVerisi #APIEntegrasyonu<\/p>\n<div class=\"github-example-link\"><strong>\u00d6rnek kod:<\/strong> <a href=\"https:\/\/github.com\/fatihsoysalcom\/python-news-etl-simulation\" target=\"_blank\" rel=\"noopener noreferrer\">github.com\/fatihsoysalcom\/python-news-etl-simulation<\/a><\/div>\n","protected":false},"excerpt":{"rendered":"G\u00fcn\u00fcm\u00fcz d\u00fcnyas\u0131nda bilgiye an\u0131nda eri\u015fim kritik \u00f6neme sahip. S\u00fcrekli akan haber verilerini otomatik olarak toplay\u0131p i\u015flemek, bir\u00e7ok sekt\u00f6r i\u00e7in rekabet avantaj\u0131 sa\u011flayabilir.","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"csco_page_header_type":"","csco_page_load_nextpost":"","csco_page_subscribe_form":"","csco_page_contact_form":"","footnotes":""},"categories":[644],"tags":[],"class_list":{"0":"post-42363","1":"post","2":"type-post","3":"status-publish","4":"format-standard","6":"category-postgresql","7":"cs-entry","8":"cs-video-wrap"},"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v20.5 (Yoast SEO v25.3.1) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Ger\u00e7ek Zamanl\u0131 Haber Verilerini Python ve PostgreSQL ile Yakalamak: Bir ETL Yolculu\u011fu - Kodlar\u0131n Gizemli D\u00fcnyas\u0131<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/fatihsoysal.com\/blog\/gercek-zamanli-haber-verilerini-python-ve-postgresql-ile-yakalamak-bir-etl-yolculugu\/\" \/>\n<meta property=\"og:locale\" content=\"tr_TR\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Ger\u00e7ek Zamanl\u0131 Haber Verilerini Python ve PostgreSQL ile Yakalamak: Bir ETL Yolculu\u011fu\" \/>\n<meta property=\"og:description\" content=\"G\u00fcn\u00fcm\u00fcz d\u00fcnyas\u0131nda bilgiye an\u0131nda eri\u015fim kritik \u00f6neme sahip. S\u00fcrekli akan haber verilerini otomatik olarak toplay\u0131p i\u015flemek, bir\u00e7ok sekt\u00f6r i\u00e7in rekabet avantaj\u0131 sa\u011flayabilir.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/fatihsoysal.com\/blog\/gercek-zamanli-haber-verilerini-python-ve-postgresql-ile-yakalamak-bir-etl-yolculugu\/\" \/>\n<meta property=\"og:site_name\" content=\"Kodlar\u0131n Gizemli D\u00fcnyas\u0131\" \/>\n<meta property=\"article:published_time\" content=\"2026-06-07T18:04:45+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2026-06-07T18:05:13+00:00\" \/>\n<meta name=\"author\" content=\"Fatih Soysal\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Yazan:\" \/>\n\t<meta name=\"twitter:data1\" content=\"Fatih Soysal\" \/>\n\t<meta name=\"twitter:label2\" content=\"Tahmini okuma s\u00fcresi\" \/>\n\t<meta name=\"twitter:data2\" content=\"36 dakika\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/gercek-zamanli-haber-verilerini-python-ve-postgresql-ile-yakalamak-bir-etl-yolculugu\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/gercek-zamanli-haber-verilerini-python-ve-postgresql-ile-yakalamak-bir-etl-yolculugu\/\"},\"author\":{\"name\":\"Fatih Soysal\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\"},\"headline\":\"Ger\u00e7ek Zamanl\u0131 Haber Verilerini Python ve PostgreSQL ile Yakalamak: Bir ETL Yolculu\u011fu\",\"datePublished\":\"2026-06-07T18:04:45+00:00\",\"dateModified\":\"2026-06-07T18:05:13+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/gercek-zamanli-haber-verilerini-python-ve-postgresql-ile-yakalamak-bir-etl-yolculugu\/\"},\"wordCount\":5294,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\"},\"articleSection\":[\"PostgreSQL\"],\"inLanguage\":\"tr\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/fatihsoysal.com\/blog\/gercek-zamanli-haber-verilerini-python-ve-postgresql-ile-yakalamak-bir-etl-yolculugu\/#respond\"]}],\"copyrightYear\":\"2026\",\"copyrightHolder\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/gercek-zamanli-haber-verilerini-python-ve-postgresql-ile-yakalamak-bir-etl-yolculugu\/\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/gercek-zamanli-haber-verilerini-python-ve-postgresql-ile-yakalamak-bir-etl-yolculugu\/\",\"name\":\"Ger\u00e7ek Zamanl\u0131 Haber Verilerini Python ve PostgreSQL ile Yakalamak: Bir ETL Yolculu\u011fu - Kodlar\u0131n Gizemli D\u00fcnyas\u0131\",\"isPartOf\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#website\"},\"datePublished\":\"2026-06-07T18:04:45+00:00\",\"dateModified\":\"2026-06-07T18:05:13+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/gercek-zamanli-haber-verilerini-python-ve-postgresql-ile-yakalamak-bir-etl-yolculugu\/#breadcrumb\"},\"inLanguage\":\"tr\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/fatihsoysal.com\/blog\/gercek-zamanli-haber-verilerini-python-ve-postgresql-ile-yakalamak-bir-etl-yolculugu\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/gercek-zamanli-haber-verilerini-python-ve-postgresql-ile-yakalamak-bir-etl-yolculugu\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Anasayfa\",\"item\":\"https:\/\/fatihsoysal.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Ger\u00e7ek Zamanl\u0131 Haber Verilerini Python ve PostgreSQL ile Yakalamak: Bir ETL Yolculu\u011fu\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#website\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/\",\"name\":\"Fatihsoysal.com\",\"description\":\"Blog - Yaz\u0131l\u0131m D\u00fcnyas\u0131 Tecr\u00fcbelerim\",\"publisher\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/fatihsoysal.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"tr\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\",\"name\":\"Fatih Soysal\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"tr\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png\",\"contentUrl\":\"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png\",\"width\":512,\"height\":512,\"caption\":\"Fatih Soysal\"},\"logo\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/\"},\"description\":\"Kullan\u0131m ve kodlama m\u00fckemmeliyetini odak alan uygulamalar olu\u015fturma deneyimine sahip, profesyonel olarak 15+ y\u0131l \u00fczeri deneyime sahip bir yaz\u0131l\u0131m m\u00fchendisi.\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/author\/fatihsoysal\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Ger\u00e7ek Zamanl\u0131 Haber Verilerini Python ve PostgreSQL ile Yakalamak: Bir ETL Yolculu\u011fu - Kodlar\u0131n Gizemli D\u00fcnyas\u0131","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/fatihsoysal.com\/blog\/gercek-zamanli-haber-verilerini-python-ve-postgresql-ile-yakalamak-bir-etl-yolculugu\/","og_locale":"tr_TR","og_type":"article","og_title":"Ger\u00e7ek Zamanl\u0131 Haber Verilerini Python ve PostgreSQL ile Yakalamak: Bir ETL Yolculu\u011fu","og_description":"G\u00fcn\u00fcm\u00fcz d\u00fcnyas\u0131nda bilgiye an\u0131nda eri\u015fim kritik \u00f6neme sahip. S\u00fcrekli akan haber verilerini otomatik olarak toplay\u0131p i\u015flemek, bir\u00e7ok sekt\u00f6r i\u00e7in rekabet avantaj\u0131 sa\u011flayabilir.","og_url":"https:\/\/fatihsoysal.com\/blog\/gercek-zamanli-haber-verilerini-python-ve-postgresql-ile-yakalamak-bir-etl-yolculugu\/","og_site_name":"Kodlar\u0131n Gizemli D\u00fcnyas\u0131","article_published_time":"2026-06-07T18:04:45+00:00","article_modified_time":"2026-06-07T18:05:13+00:00","author":"Fatih Soysal","twitter_card":"summary_large_image","twitter_misc":{"Yazan:":"Fatih Soysal","Tahmini okuma s\u00fcresi":"36 dakika"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/fatihsoysal.com\/blog\/gercek-zamanli-haber-verilerini-python-ve-postgresql-ile-yakalamak-bir-etl-yolculugu\/#article","isPartOf":{"@id":"https:\/\/fatihsoysal.com\/blog\/gercek-zamanli-haber-verilerini-python-ve-postgresql-ile-yakalamak-bir-etl-yolculugu\/"},"author":{"name":"Fatih Soysal","@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1"},"headline":"Ger\u00e7ek Zamanl\u0131 Haber Verilerini Python ve PostgreSQL ile Yakalamak: Bir ETL Yolculu\u011fu","datePublished":"2026-06-07T18:04:45+00:00","dateModified":"2026-06-07T18:05:13+00:00","mainEntityOfPage":{"@id":"https:\/\/fatihsoysal.com\/blog\/gercek-zamanli-haber-verilerini-python-ve-postgresql-ile-yakalamak-bir-etl-yolculugu\/"},"wordCount":5294,"commentCount":0,"publisher":{"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1"},"articleSection":["PostgreSQL"],"inLanguage":"tr","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/fatihsoysal.com\/blog\/gercek-zamanli-haber-verilerini-python-ve-postgresql-ile-yakalamak-bir-etl-yolculugu\/#respond"]}],"copyrightYear":"2026","copyrightHolder":{"@id":"https:\/\/fatihsoysal.com\/blog\/#organization"}},{"@type":"WebPage","@id":"https:\/\/fatihsoysal.com\/blog\/gercek-zamanli-haber-verilerini-python-ve-postgresql-ile-yakalamak-bir-etl-yolculugu\/","url":"https:\/\/fatihsoysal.com\/blog\/gercek-zamanli-haber-verilerini-python-ve-postgresql-ile-yakalamak-bir-etl-yolculugu\/","name":"Ger\u00e7ek Zamanl\u0131 Haber Verilerini Python ve PostgreSQL ile Yakalamak: Bir ETL Yolculu\u011fu - Kodlar\u0131n Gizemli D\u00fcnyas\u0131","isPartOf":{"@id":"https:\/\/fatihsoysal.com\/blog\/#website"},"datePublished":"2026-06-07T18:04:45+00:00","dateModified":"2026-06-07T18:05:13+00:00","breadcrumb":{"@id":"https:\/\/fatihsoysal.com\/blog\/gercek-zamanli-haber-verilerini-python-ve-postgresql-ile-yakalamak-bir-etl-yolculugu\/#breadcrumb"},"inLanguage":"tr","potentialAction":[{"@type":"ReadAction","target":["https:\/\/fatihsoysal.com\/blog\/gercek-zamanli-haber-verilerini-python-ve-postgresql-ile-yakalamak-bir-etl-yolculugu\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/fatihsoysal.com\/blog\/gercek-zamanli-haber-verilerini-python-ve-postgresql-ile-yakalamak-bir-etl-yolculugu\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Anasayfa","item":"https:\/\/fatihsoysal.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Ger\u00e7ek Zamanl\u0131 Haber Verilerini Python ve PostgreSQL ile Yakalamak: Bir ETL Yolculu\u011fu"}]},{"@type":"WebSite","@id":"https:\/\/fatihsoysal.com\/blog\/#website","url":"https:\/\/fatihsoysal.com\/blog\/","name":"Fatihsoysal.com","description":"Blog - Yaz\u0131l\u0131m D\u00fcnyas\u0131 Tecr\u00fcbelerim","publisher":{"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/fatihsoysal.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"tr"},{"@type":["Person","Organization"],"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1","name":"Fatih Soysal","image":{"@type":"ImageObject","inLanguage":"tr","@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/","url":"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png","contentUrl":"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png","width":512,"height":512,"caption":"Fatih Soysal"},"logo":{"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/"},"description":"Kullan\u0131m ve kodlama m\u00fckemmeliyetini odak alan uygulamalar olu\u015fturma deneyimine sahip, profesyonel olarak 15+ y\u0131l \u00fczeri deneyime sahip bir yaz\u0131l\u0131m m\u00fchendisi.","url":"https:\/\/fatihsoysal.com\/blog\/author\/fatihsoysal\/"}]}},"yoast_meta":{"yoast_wpseo_title":"","yoast_wpseo_metadesc":"","yoast_wpseo_canonical":""},"amp_enabled":true,"_links":{"self":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/posts\/42363","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/comments?post=42363"}],"version-history":[{"count":1,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/posts\/42363\/revisions"}],"predecessor-version":[{"id":42364,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/posts\/42363\/revisions\/42364"}],"wp:attachment":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/media?parent=42363"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/categories?post=42363"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/tags?post=42363"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}