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.
- 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")
- 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()