R ile Veri Kazıma Alıştırmaları

Sadettin Demirel

3/22/2019

Veri çağında yaşıyoruz. Önümüz arkamız sağımız solumuz veri. Hükümetler, uluslararası kuruluşlar, haber merkezleri verilerini kullanıma açıyor, bu veriler, araştırma, geliştirme, gazetecilik vb amaçları için kullanılıyor ve yeniden dağıtıma sokuluyor. Ama üretilen ve paylaşılan her veri açık veri statüsünde değil. Web ortamında paylaşılan her veri indirilemiyor, indirilse dahi uygun formatta olmadığı için kullanılamıyor. Twitter, Google, Facebook gibi büyük oluşumlar bu verileri bir API (Uygulama Programlama Arayüzü) hizmetiyle ticarileştirerek kullanıma sunuyor. Önceki yazımda “R ile tweet verisi nasıl çekilir” yazımda bunu detaylı olarak ele almıştım. Peki API hizmeti sunmayan web sitelerinin verileri nerede? Bu websitelerindeki verileri nasıl kazıyabiliriz? bu yazıda R kullanarak uygulamalı olarak anlatacağım.

Anlatacağım yöntemle web sitelerindeki metin verileri (cümleler, paragrafları) de kazınabilir. Fakat bu pratikte web sayfalarına hapsedilmiş veri tablolarını kazıyacağız. Veri kazıma pratiği için iki ayrı websitede adresinden yararlanacağız. İlki Yök Tez Merkezi İstatistikleri, diğeri Maçkolik Süper Lig Gol istatistikleri Her iki adresteki veriler de tablo formatında. O halde her biri için ayrı bir yöntem kullanarak, bu verileri kazıyalım.

Kullanıcılacak paketler ve ön hazırlık

Veri kazıma pratiğinde rvest paketini kullanacağız. Bunun yanısıra tidyverse ve janitor paketleri de kazınan verinin düzenlenmesi ve görselleştirilmesi için işimize yarayacak.

#paketleri yüklemeyi unutmayın!
#install.packages("rvest")...
library("rvest")
library("tidyverse")
library("janitor")

Paketleri çağırdıktan sonra yapmamız gereken kazıyacağımız web sayfalarının adresilerini R’a aktarmak. read_html fonksiyonu ile adresleri tanımlayarak bunu yapabiliriz. Bundan sonraki adımda tanımladığımız yok_link ve mackolik öğeleriyle işlemler yapacağız.

yok_link <- read_html("https://tez.yok.gov.tr/UlusalTezMerkezi/IstatistikiBilgiler?islem=3")
mackolik<- read_html("https://www.mackolik.com/puan-durumu/t%C3%BCrkiye-spor-toto-s%C3%BCper-lig/istatistik/482ofyysbdbeoxauk19yg7tdt")

Pratik 1: Yök Tez Merkezi Verileri

Veri tablosu içeren html tabanlı tüm web sayfalarını rvest paketinin html_table() fonksiyonuyla kazıyabiliriz. Aşağıdaki işlemde yök tez merkezi verilerinin bulunduğu adresi html_table ile kazıdık. fill = TRUE argümanı sayesinde R veri tablosunda eksik verileri NA, yani eksik veri olarak okuyor. Ayrıca, kazıdığımız verileri yok_tez isimli yeni bir öğeye kaydettik, çünkü kazıdığımız veri henüz istediğimiz tablo formatında değil. View(yok_tez) kodu ile verinin ne kadar dağınık olduğuna göz atabiliriz.

yok_tez <- yok_link %>% html_table(fill = TRUE)

Kazıdığımız veri yok_tez şuan R’ın veri formatlarından biri olan liste formatında. Listedeki [[1]] ve [[2]] numaraları iki ayrı veri tablosunndan oluştuğunu ifade ediyor. O halde her iki veri tablosunu göz atalım. Bakalım hangisi yök tez verileri.

Birinci veri tablosu işimize yaraymayacak (junk) veriler içeriyor. İkinc tablo de ise konulara ve derecelere göre tez sayılarını görebiliryoruz. Tek veri tablosu ismi ve sütun isimleri değer olarak yer alıyor.

head(yok_tez[[2]])
##                X1            X2            X3            X4            X5
## 1   Konulara göre Konulara göre Konulara göre Konulara göre Konulara göre
## 2            Konu       Bakınız   Ayrıca Bkz. Yüksek Lisans       Doktora
## 3        Adli Tıp                                       734           248
## 4     Ağaç İşleri                                       551            91
## 5  Aile Hekimliği                                        53            11
## 6 Aile Planlaması                                        71            17
##               X6               X7                     X8
## 1  Konulara göre    Konulara göre          Konulara göre
## 2 Tıpta Uzmanlık Sanatta Yeterlik Diş Hekimliği Uzmanlık
## 3            374                0                      1
## 4              0                1                      0
## 5           1254                0                      0
## 6             18                0                      0
##                       X9           X10
## 1          Konulara göre Konulara göre
## 2 Tıpta Yan Dal Uzmanlık        Toplam
## 3                      0          1357
## 4                      0           643
## 5                      0          1318
## 6                      0           106

Sütun isimlerini düzenlenmeden önce hala yok_tez listesinde bulunan 2. veri setini, veri tablosu olarak kaydedelim. Bu hem işimizi kolaylaştıracak hem de gereksiz veri setinden kurtulmuş olacağız. Bunu as.data.freame() fonksiyonu içerisine yok_tez[[2]] ekleyerek yapabiliriz.

yok_tablo <- as.data.frame(yok_tez[[2]])
head(yok_tablo)
##                X1            X2            X3            X4            X5
## 1   Konulara göre Konulara göre Konulara göre Konulara göre Konulara göre
## 2            Konu       Bakınız   Ayrıca Bkz. Yüksek Lisans       Doktora
## 3        Adli Tıp                                       734           248
## 4     Ağaç İşleri                                       551            91
## 5  Aile Hekimliği                                        53            11
## 6 Aile Planlaması                                        71            17
##               X6               X7                     X8
## 1  Konulara göre    Konulara göre          Konulara göre
## 2 Tıpta Uzmanlık Sanatta Yeterlik Diş Hekimliği Uzmanlık
## 3            374                0                      1
## 4              0                1                      0
## 5           1254                0                      0
## 6             18                0                      0
##                       X9           X10
## 1          Konulara göre Konulara göre
## 2 Tıpta Yan Dal Uzmanlık        Toplam
## 3                      0          1357
## 4                      0           643
## 5                      0          1318
## 6                      0           106

Yukarıdaki işlemle veri tablosunu yok_tablo olarak kaydettik. Bu aşamadan sonra eğer isterseniz bu veriyi dışarı aktarıp Excelde veya istediğiniz veri aracında temizleyerek kullanabilirsiniz. Dışarı aktarmak için aşağıdaki kodu kullanabilirsiniz.

write_csv(yok_tablo, "~/desktop/yok_tablo1.csv")

Bir diğer yol “R ekosisteminde dağınık veriler nasıl temizlenir” yazımda ele aldığım gibi bu veri tablosunu temizleyebilir, derli hale getirebiliriz. Fakat bu aşamada sütun isimlerini düzenlememiz yeterli olacaktır. Bunun için dplyr ve janitor paketlerini kullanacağız.

İlk olarak select komutuyla 1,,4,5,10.’cu sütunları seçiyoruz. Sonrasında row_to_names fonksiyonu ile hangi satırın sütun ismi olarak seçeceksek row_number argumanına belirtiyoruz. Bu veri setinde istediğimiz isimler 2. satırda. Diğer tanımladığımız argümanlar ise sütun isimleri olarak belirlediğimiz satırdaki verileri (remove_row) ve üst satırlardaki değerleri (remove_rows_above) temizlememizi sağlıyor.

yok_derli <- yok_tablo %>% select(1,4,5,10) %>% row_to_names(row_number = 2, remove_row = TRUE, remove_rows_above = TRUE)
head(yok_derli)
##                    Konu Yüksek Lisans Doktora Toplam
## 3              Adli Tıp           734     248   1357
## 4           Ağaç İşleri           551      91    643
## 5        Aile Hekimliği            53      11   1318
## 6       Aile Planlaması            71      17    106
## 7    Aktüerya Bilimleri           103      17    120
## 8 Allerji ve İmmünoloji           170     117    645

Kazıma işlemini tamamladık hatta kazınan veriyi biraz temizledik. Bundan sonraki adımda metin verisi olarak algılanan Yüksek Lisans, Doktora ve Toplam değişkenleri sayı verisine dönüştürülerek analiz devam ettirilebilir. Şimde geçelim ikinci veri kazıma pratiğine.

Pratik2: Maçkolik Verileri

İkinci pratikte Maçkolik Süperlig gol istatistiklerini yine html_table ile çekebiliriz. Ama işimizi kolaylaştırmayalım. Gol istatistiklerini metin verisi olarak çekip R’da birleştirelim. Bazı durumlarda html_table() fonksiyonu işe düzgün çalışmayabiliyor.

ikinci adım ilkine göre biraz meşakatli. Bu adımda tablolardaki veriyi çekmek için sırasıyla html_node ve html_text komutlarını kullanacağız. Çünkü kazıyacağımız verileri htmel ve css node’ları ile web sitede görüntüleniyor. Veri tablosuna karşılıl gelen node ları bulabilmek için bir tarayıcı eklentisi kullanacağız: sellector gadget. Bu eklenti tarayıcılarda sağa tılayıp inpect seçeneğiyle aynı görevi görüyor. Farkı tabloya karşılık gelen Node’u zaman kaybetmeden elde ediyoruz.

Maçkolik süper lig gol istatistiklerine açıyoruz ve eklenti ile oyuncu ismi üzerine tıklıyoruz. Sağ altta eklenti bize ilgili node’u verdi. Sonrasında yapmamız gereken node’u aşağıdaki olduğu gibi html_nodes() komutu içerisine ekleyebiliriz. Ve son olarak html_text() node’daki verileri metin verisine dönüştürdük. Veriyi oyuncu öğesine kaydettik. View(oyuncu) komutu ile neyi kazıdığımızı görebiliriz.

oyuncu <- mackolik %>% html_nodes(".p0c-competition-player-ranking__player-name") %>% html_text(trim = TRUE)
head(oyuncu)
## [1] "M. Diagne"    "H. Rodallega" "P. Cissé"     "Burak Yılmaz"
## [5] "H. Onyekuru"  "V. Muriqi"

Bundan sonraki adımlarda takım ve gol_sayısı içinde gerekli node’ları seçtikten aynı işlemi tekrarlayabiliriz. Bu arada trim = TRUE metin verisindeki gereksiz boş alanları kaldırıyor.

takım <- mackolik %>% html_nodes(".p0c-competition-player-ranking__cell--team") %>% html_text(trim = TRUE)
gol_sayisi <- mackolik %>% html_nodes(".p0c-competition-player-ranking__cell--stat") %>% html_text(trim = TRUE)

Her üç sütundeki değerleri kazıdık. Şimdi elimizdeki parçaları birleştirerek bir veri tablosu oluşturalım. Bu aşamada metin verisinden oluşan üç öğeyi tibble komutuyla tablo formatına dönüştürelim. tibble, as.data.frame komutunun modern hali diyebiliriz. Ayrıca Yeni Zelanda İngilizcesinde table anlamına geliyor.

#verileri birleştirelim
mackolik_derli <- tibble(oyuncu, takım, gol_sayisi)
head(mackolik_derli)
## # A tibble: 6 x 3
##   oyuncu       takım           gol_sayisi
##   <chr>        <chr>           <chr>     
## 1 M. Diagne    Galatasaray     23        
## 2 H. Rodallega Trabzonspor     12        
## 3 P. Cissé     Alanyaspor      12        
## 4 Burak Yılmaz Beşiktaş        11        
## 5 H. Onyekuru  Galatasaray     11        
## 6 V. Muriqi    Çaykur Rizespor 11

Veri tablosunu oluşturduk ama gol_sayisi metin verisi olarak algılanmış. as.numeric komutu ile gol_sayısı değişkenini sayı formatına dönüştürelim.

mackolik_derli$gol_sayisi <- as.numeric(mackolik_derli$gol_sayisi)
head(mackolik_derli)
## # A tibble: 6 x 3
##   oyuncu       takım           gol_sayisi
##   <chr>        <chr>                <dbl>
## 1 M. Diagne    Galatasaray             23
## 2 H. Rodallega Trabzonspor             12
## 3 P. Cissé     Alanyaspor              12
## 4 Burak Yılmaz Beşiktaş                11
## 5 H. Onyekuru  Galatasaray             11
## 6 V. Muriqi    Çaykur Rizespor         11

Evet yukarıdaki tabloda da görüldüğü üzere veri kazıma ve temizleme işlemini hallettik. Temizlenen veriye şuradan ulaşabilirsiniz:

write.csv(mackolik_derli, "~/desktop/mackolik_derli.csv")

Veri görselleştirmenin detaylı adımları

Son olarak kazıdığımız ve temizlediğimiz veriyi görselleştirelim.

  1. Renkleri oluşturalım
palette <- c(
  "Galatasaray" = "#c40b13",
  "Beşiktaş" = "#33313b",
  "İstanbul Başakşehir" = "#f69314",
  "Trabzonspor" = "#4592af",
  "Alanyaspor" ="#dadddf",
  "Çaykur Rizespor"= "#dadddf",
  "Sivasspor"= "#dadddf",
  "Yeni Malatyaspor"= "#dadddf",
  "Antalyaspor"= "#dadddf",
  "Kasımpaşa"= "#dadddf",
  "Göztepe"= "#dadddf",
  "BB Erzurumspor"= "#dadddf",
  "Kayserispor"= "#dadddf",
  "Konyaspor"= "#dadddf",
  "MKE Ankaragücü" = "#dadddf")
  1. Temayı özelleştirelim
theme_custom1 <- function() {
  theme_minimal() +
    theme(
      text = element_text(family = "Proxima Nova", color = "gray25"),
      plot.title = element_text(face = "bold",size = 14),
      plot.subtitle = element_text(size = 13),
      axis.text.x= element_text(size=11),
      axis.text.y = element_text(size=11),
      plot.caption = element_text(size = 11, color = "gray30"),
      plot.background = element_rect(fill = "#f6f5f5"),
      legend.position = "none")
}

3.Atılan golleri takımlara göre görselleştirelim

ggplot(mackolik_derli, aes(fct_reorder(oyuncu, gol_sayisi),gol_sayisi, fill = takım, label = gol_sayisi))+
  geom_col(show.legend = FALSE)+ 
  geom_text(check_overlap = TRUE, hjust = -0.2)+
  scale_fill_manual(values = palette)+
  labs(x="",y="",title = "Süper Ligin Golcüleri 2018/2019", subtitle ="Sadece 4 takımın oyuncuları için renk kullanılmıştır" ,caption = "@demirelsadettin / kaynak: maçkolik")+
  coord_flip()+theme_custom1()