dersblog

GDELT Dünya Olayları Veri Tabanı (Event Database)

Bu proje yapay öğrenim (machine learning) teknikleri kullanarak İnternet'teki haber makalelerini kategorize etmeye uğraşır. Günlük, yıllık verileri basit CSV dosyaları içinde her satır bir haber olacak şekilde paylaşıyorlar. Gösterilen [1] bağlantısına gidince her gün için bir zip dosyası görüyoruz, her gün için dosya ismini hazırlayıp onu otomatik indiren bir Python script altadır. Örnek olarak 10 Eylül 2022 günü indirildi,

import pandas as pd, datetime
from zipfile import ZipFile
from io import BytesIO
import urllib.request as urllib2

base_conflict_url = "http://data.gdeltproject.org/events"

conf_cols = ['GlobalEventID', 'Day', 'MonthYear', 'Year', 'FractionDate',\
       'Actor1Code', 'Actor1Name', 'Actor1CountryCode', 'Actor1KnownGroupCode',\
       'Actor1EthnicCode', 'Actor1Religion1Code', 'Actor1Religion2Code',\
       'Actor1Type1Code', 'Actor1Type2Code', 'Actor1Type3Code', \
       'Actor2Code', 'Actor2Name', 'Actor2CountryCode', 'Actor2KnownGroupCode',
       'Actor2EthnicCode', 'Actor2Religion1Code', 'Actor2Religion2Code',
       'Actor2Type1Code', 'Actor2Type2Code', 'Actor2Type3Code', \
       'IsRootEvent','EventCode', 'EventBaseCode','EventRootCode',\
       'QuadClass', 'GoldsteinScale','NumMentions','NumSources', \
       'NumArticles', 'AvgTone','Actor1Geo_Type', 'Actor1Geo_FullName',\
       'Actor1Geo_CountryCode', 'Actor1Geo_ADM1Code','Actor1Geo_Lat', \
       'Actor1Geo_Long', 'Actor1Geo_FeatureID','Actor2Geo_Type', \
       'Actor2Geo_FullName','Actor2Geo_CountryCode', 'Actor2Geo_ADM1Code',\
       'Actor2Geo_Lat', 'Actor2Geo_Long']

sd = "%d%02d%02d" % (2022, 9, 10)
url = base_conflict_url + "/%s.export.CSV.zip" % sd
r = urllib2.urlopen(url).read()
file = ZipFile(BytesIO(r))
csv = file.open("%s.export.CSV" % sd)
df = pd.read_csv(csv,sep='\t',header=None)    
url_col = df[57]        
df = df[range(len(conf_cols))]
df.columns = conf_cols

Bu noktada veri Pandas DataFrame objesi halindedir. Daha da filtreleyebiliriz, mesela olay kodu 190 ve 194 içeren olaylara bakalım. GDELT belgelerine [2] göre bu kodlar saldırı anlamına geliyor, ya askeri konvansiyonel şekilde genel saldırı. Olaylar ayrıca 1'inci aktör ve 2'inci aktör olarak ayrılmaya uğraşılmış, bir aktör bir diğerine bir etkide bulunuyorsa birinci ve ikinci aktör bunlar oluyor. Birinci Rusya ikinci aktör Ukrayna olarak filtreleme yapalım,

df2 = df[(df.EventCode==190)|(df.EventCode==195)|(df.EventCode==194)]
df3 = df2[(df2.Actor1Name=='RUSSIA') & (df2.Actor2Name=='UKRAINE')]
cols = ['Actor1Name','Actor2Name','Actor2Geo_Lat','Actor2Geo_Long']
df3 = df3[cols]
print (len(df3))
print (df3.tail(4))
22
      Actor1Name Actor2Name  Actor2Geo_Lat  Actor2Geo_Long
51112     RUSSIA    UKRAINE        60.0000        100.0000
54643     RUSSIA    UKRAINE        46.6558         32.6178
55912     RUSSIA    UKRAINE        60.0000        100.0000
55914     RUSSIA    UKRAINE        49.9808         36.2527

Bazı sonuçlar geldi. Sondan dört tane gösterdik, olay sırasında ikinci aktörün nerede olduğunu göstermiş. Hangi haber baz alınarak mesela son bilgi toplanmış?

print (df3.loc[55914])
print (url_col.loc[55914])
Actor1Name         RUSSIA
Actor2Name        UKRAINE
Actor2Geo_Lat     49.9808
Actor2Geo_Long    36.2527
Name: 55914, dtype: object
https://katcountry989.com/2022/09/10/russian-rockets-hit-ukraines-kharkiv-killing-one-governor/

Bağlantıyı ziyaret edince hakikaten bir saldırı haberi olduğunu görüyoruz.

Fakat dikkat: her haber bu şekilde kategorize edilmeyebiliyor. Kullanıcıların GDELT verisini başlangıç noktası kabul ederek üstüne ek filtreleme yapmaları gerekebilir.

Yanlış bir örnek olarak alttaki makaleye bakalım,

print (df2.loc[67736][cols])
print (url_col.loc[67736])
Actor1Name            NEVADA
Actor2Name        JOURNALIST
Actor2Geo_Lat        38.4199
Actor2Geo_Long      -117.122
Name: 67736, dtype: object
https://twitchy.com/brettt-3136/2022/09/10/reporter-nevada-gubernatorial-candidate-refuses-to-denounce-donald-trumps-normalization-of-attacks-on-reporters/

Bu makaleye bakınca evet içinde saldırı kelimesi geçtiğini görüyoruz fakat bu askeri değil, politika bağlamında sözel bir çekişme var. Demek ki GDELT her zaman işlemiyor, ek filtreleme yapmak gerekebilir.

Ekler

En son versiyon üzerinde işleyen kod alttadır, 20240602 tarihi için bir zıp dosyasının indirilmiş olduğunu kabul edelim,

import zipfile, pandas as pd
with zipfile.ZipFile('20240602.export.CSV.zip', 'r') as z:
     df = pd.read_csv(z.open('20240602.export.CSV'),sep='\t',header=None)

cols = ["GLOBALEVENTID", "SQLDATE", "MonthYear", "Year",
"FractionDate", "Actor1Code", "Actor1Name", "Actor1CountryCode",
"Actor1KnownGroupCode", "Actor1EthnicCode", "Actor1Religion1Code",
"Actor1Religion2Code", "Actor1Type1Code", "Actor1Type2Code",
"Actor1Type3Code", "Actor2Code", "Actor2Name", "Actor2CountryCode",
"Actor2KnownGroupCode", "Actor2EthnicCode", "Actor2Religion1Code",
"Actor2Religion2Code", "Actor2Type1Code", "Actor2Type2Code",
"Actor2Type3Code", "IsRootEvent", "EventCode", "EventBaseCode",
"EventRootCode", "QuadClass", "GoldsteinScale", "NumMentions",
"NumSources", "NumArticles", "AvgTone", "Actor1Geo_Type",
"Actor1Geo_FullName", "Actor1Geo_CountryCode", "Actor1Geo_ADM1Code",
"Actor1Geo_Lat", "Actor1Geo_Long", "Actor1Geo_FeatureID",
"Actor2Geo_Type", "Actor2Geo_FullName", "Actor2Geo_CountryCode",
"Actor2Geo_ADM1Code", "Actor2Geo_Lat", "Actor2Geo_Long",
"Actor2Geo_FeatureID", "ActionGeo_Type", "ActionGeo_FullName",
"ActionGeo_CountryCode", "ActionGeo_ADM1Code", "ActionGeo_Lat",
"ActionGeo_Long", "ActionGeo_FeatureID", "DATEADDED","SOURCEURL"];

df.columns = cols

df = df[(df['Actor1Type1Code'] == 'MIL') | (df.EventCode==154)]
df = df[['Actor1Geo_Lat','Actor1Geo_Long','SOURCEURL']]
df = df.drop_duplicates(subset=['SOURCEURL'],keep='last')
df = df[pd.isnull(df2.Actor1Geo_Lat)==False]

Artık df içinde filtrelenmiş ve enlem, boylam ve haber kaynağının URL bağlantısını içeren bir veri sonucu vardır.

Kaynaklar

[1] [GDELT](http://data.gdeltproject.org/events/index.html)

[2] [GDELT Olay Kodlari - PDF](http://data.gdeltproject.org/documentation/CAMEO.Manual.1.1b3.pdf)


Yukarı