Data Science Programming
Web scraping in R
1) Menyalin Data Tabel dari Website ke R
## 1) datapasta ----
install.packages("datapasta")
library(datapasta)
#https://www.topendsports.com/events/summer/medal-tally/all-time-all.htm
olympic_medals <- data.frame(
stringsAsFactors = FALSE,
check.names = FALSE,
Rank = c(1L,2L,3L,4L,5L,6L,7L,8L,9L,
10L,11L,12L,13L,14L,15L,16L,
17L,18L,19L,20L,21L,22L,23L,24L,
25L,26L,27L,28L,29L,30L,31L,32L,
33L,34L,35L,36L,37L,38L,39L,40L,
41L,42L,43L,44L,45L,46L,47L,48L,
49L,50L,51L,52L,53L,54L,55L,
56L,57L,58L,59L,60L,61L,62L,63L,
64L,65L,66L,67L,68L,69L,70L,71L,
72L,73L,74L,75L,76L,77L,78L,79L,
80L,81L,82L,83L,84L,85L,86L,87L,
88L,89L,90L,91L,92L,93L,94L,
95L,96L,97L,98L,99L,100L,101L,102L,
103L,104L,105L,106L,107L,108L,
109L,110L,111L,112L,113L,114L,115L,
116L,117L,118L,119L,120L,121L,
122L,123L,124L,125L,126L,127L,128L,
129L,130L,131L,132L,133L,134L,
135L,136L,137L,138L,139L,140L,141L,
142L,143L,144L,145L,146L,147L),
`Nation.(NOC)` = c("United States","Soviet Union",
"Germany","Great Britain","China",
"France","Italy","Hungary","Russia",
"Japan","Australia","East Germany",
"Sweden","Finland","South Korea",
"Netherlands","Romania","Cuba","Poland",
"Canada","Norway","Bulgaria",
"Switzerland","New Zealand","Czechoslovakia",
"Denmark","Spain","Belgium",
"Türkiye","Brazil","Ukraine","Greece",
"Kenya","Yugoslavia","South Africa",
"Jamaica","Iran","Ethiopia","Argentina",
"Austria","Czechia","North Korea",
"Kazakhstan","Croatia","Belarus",
"Mexico","Ireland","Georgia",
"Uzbekistan","Estonia","Thailand","India",
"Slovakia","Egypt","Indonesia",
"Slovenia","Mixed team","Bahamas",
"Azerbaijan","Chinese Taipei","Morocco",
"Lithuania","Serbia","Colombia","Portugal",
"Algeria","Tunisia","Latvia",
"Uganda","Nigeria","Venezuela",
"Trinidad and Tobago","Israel",
"Dominican Republic","Pakistan","Zimbabwe","Cameroon",
"Ecuador","Kosovo","Mongolia",
"Armenia","Chile","Puerto Rico",
"Uruguay","Hong Kong","Qatar","Fiji",
"Bahrain","Philippines",
"Independent Olympic Athletes/Participants","Singapore",
"Vietnam","Costa Rica","Peru",
"Ivory Coast","Tajikistan","Syria",
"Grenada","Panama","Jordan","Suriname",
"Bermuda","Mozambique","Burundi",
"Luxembourg","United Arab Emirates",
"Malaysia","Kyrgyzstan","Moldova","Ghana",
"Namibia","Bohemia","Iceland",
"Saudi Arabia","Lebanon","San Marino",
"Kuwait","Sri Lanka",
"Serbia and Montenegro","Haiti","North Macedonia",
"Niger","Zambia","British West Indies",
"Botswana","Tanzania","Afghanistan",
"Iraq","Sudan","Cyprus","Senegal",
"Samoa","Guyana","Guatemala","Paraguay",
"Netherlands Antilles","Gabon",
"Barbados","Montenegro","Mauritius",
"Eritrea","Burkina Faso","Virgin Islands",
"Djibouti","Turkmenistan","Tonga",
"Togo"),
No..of.Games = c(28L,10L,25L,29L,11L,29L,28L,
27L,10L,23L,29L,5L,28L,26L,18L,
27L,22L,21L,22L,27L,26L,21L,29L,
24L,16L,28L,24L,27L,23L,23L,7L,
29L,15L,18L,20L,18L,17L,14L,
25L,28L,7L,10L,7L,8L,7L,24L,22L,
7L,7L,13L,17L,25L,7L,23L,16L,8L,
3L,17L,7L,15L,15L,10L,5L,20L,
25L,14L,15L,12L,16L,17L,19L,18L,
17L,15L,18L,14L,15L,15L,2L,14L,
7L,24L,19L,22L,17L,10L,15L,10L,
22L,4L,17L,16L,16L,19L,14L,7L,
14L,10L,18L,11L,13L,19L,11L,7L,
24L,10L,14L,7L,7L,15L,8L,3L,21L,
12L,18L,15L,13L,18L,1L,16L,7L,
13L,14L,1L,11L,14L,15L,15L,13L,
11L,15L,10L,18L,15L,13L,13L,11L,
13L,4L,10L,6L,10L,13L,9L,7L,
10L,11L),
Gold = c(1061L,440L,285L,285L,262L,
226L,217L,181L,170L,169L,167L,153L,
148L,101L,96L,95L,90L,85L,72L,
71L,60L,54L,53L,53L,49L,48L,48L,
43L,41L,37L,35L,35L,35L,28L,27L,
26L,24L,23L,21L,19L,19L,16L,15L,
14L,13L,13L,11L,10L,10L,10L,10L,
10L,10L,8L,8L,8L,8L,8L,7L,7L,
7L,6L,6L,5L,5L,5L,5L,4L,4L,3L,
3L,3L,3L,3L,3L,3L,3L,3L,3L,
2L,2L,2L,2L,2L,2L,2L,2L,2L,1L,
1L,1L,1L,1L,1L,1L,1L,1L,1L,1L,
1L,1L,1L,1L,1L,1L,1L,0L,0L,0L,
0L,0L,0L,0L,0L,0L,0L,0L,0L,
0L,0L,0L,0L,0L,0L,0L,0L,0L,0L,
0L,0L,0L,0L,0L,0L,0L,0L,0L,0L,
0L,0L,0L,0L,0L,0L,0L,0L,0L),
Silver = c(836L,357L,326L,315L,199L,258L,
188L,154L,157L,150L,177L,129L,
176L,85L,91L,104L,97L,71L,89L,
108L,51L,88L,79L,33L,49L,78L,72L,
54L,26L,42L,36L,45L,42L,31L,33L,
36L,23L,12L,26L,34L,21L,16L,21L,
13L,30L,24L,10L,12L,6L,9L,8L,
9L,14L,11L,14L,9L,4L,2L,14L,11L,
5L,7L,7L,13L,9L,4L,3L,11L,4L,
11L,7L,5L,1L,5L,3L,4L,1L,2L,0L,
11L,8L,7L,2L,2L,3L,1L,0L,1L,
5L,1L,2L,3L,1L,3L,1L,1L,1L,1L,
0L,1L,0L,0L,0L,1L,1L,0L,8L,3L,
2L,1L,5L,1L,2L,2L,2L,1L,0L,
2L,2L,1L,1L,1L,1L,0L,1L,2L,0L,
0L,1L,1L,1L,1L,0L,1L,1L,1L,1L,
0L,1L,0L,0L,0L,1L,0L,1L,1L,0L),
Bronze = c(739L,325L,363L,315L,173L,280L,
213L,176L,178L,178L,213L,127L,
179L,119L,100L,122L,121L,85L,137L,
147L,49L,82L,73L,53L,45L,79L,
47L,58L,37L,71L,68L,41L,36L,31L,
29L,25L,29L,23L,30L,41L,27L,22L,
36L,14L,42L,36L,14L,18L,20L,17L,
17L,14L,8L,19L,15L,11L,4L,6L,
28L,18L,12L,13L,11L,15L,14L,8L,
7L,6L,3L,13L,9L,11L,9L,4L,4L,1L,
2L,0L,0L,17L,8L,4L,6L,6L,4L,
5L,1L,0L,8L,3L,2L,1L,2L,0L,2L,
2L,2L,1L,2L,1L,1L,1L,1L,0L,0L,
1L,5L,4L,4L,4L,0L,3L,2L,2L,
2L,2L,3L,0L,0L,1L,1L,1L,1L,2L,
1L,0L,2L,1L,0L,0L,0L,0L,1L,0L,
0L,0L,0L,1L,0L,1L,1L,1L,0L,1L,
0L,0L,1L),
Total = c(2636L,1122L,974L,915L,634L,
764L,618L,511L,505L,497L,557L,409L,
503L,305L,287L,321L,308L,241L,
298L,326L,160L,224L,205L,139L,143L,
205L,167L,155L,104L,150L,139L,
121L,113L,90L,89L,87L,76L,58L,77L,
94L,67L,54L,72L,41L,85L,73L,35L,
40L,36L,36L,35L,35L,32L,38L,
37L,28L,16L,14L,49L,36L,24L,26L,
24L,33L,28L,17L,15L,21L,11L,27L,
19L,19L,13L,12L,10L,8L,6L,5L,3L,
30L,18L,13L,10L,10L,9L,8L,3L,
3L,14L,5L,5L,5L,4L,4L,4L,4L,4L,
3L,3L,3L,2L,2L,2L,2L,2L,2L,
13L,7L,6L,5L,5L,4L,4L,4L,4L,3L,
3L,2L,2L,2L,2L,2L,2L,2L,2L,2L,
2L,1L,1L,1L,1L,1L,1L,1L,1L,
1L,1L,1L,1L,1L,1L,1L,1L,1L,1L,
1L,1L)
)
Contoh pertama ini sebenarnya bukan web scraping, melainkan jalan pintas. Jika Anda menemukan sebuah tabel di sebuah situs web dan ingin mengambil data dari tabel tersebut langsung ke dalam R, salah satu cara termudah adalah dengan:
- Menyorot seluruh isi tabel, termasuk judul kolom.
- Menekan tombol Ctrl + C (atau klik kanan lalu pilih “Copy”).
- Menggunakan paket datapasta di R untuk menempelkan data dari clipboard sebagai data frame langsung ke R.
Misalnya, saya memiliki tabel medali Olimpiade. Setelah menyalin dan menempelkannya menggunakan datapasta, kita akan mendapatkan data frame dengan kolom-kolom yang berisi:
- Peringkat negara,
- Jumlah partisipasi di Olimpiade,
- Jumlah medali emas, perak, dan perunggu,
- Total semua medali.
Pendekatan ini lebih cepat dibandingkan menyalin data ke Excel lalu mengimpornya ke dalam R.
2) Web Scraping dengan Paket rvest
Untuk melakukan web scraping yang sesungguhnya, kita membutuhkan paket rvest. Paket ini digunakan untuk “memanen” (harvest) data dari situs web.
1. Menginstal dan Memuat Paket
Sebelum menggunakan rvest, kita perlu menginstalnya terlebih dahulu:
2. Membaca Halaman HTML
Langkah pertama adalah menggunakan fungsi read_html()
yang membutuhkan URL sebagai parameter. Misalnya, kita ingin mengambil
daftar semua paket di situs web R.
url <- "https://cran.r-project.org/web/packages/available_packages_by_name.html"
web_page <- read_html(url)
Jika kita mencetak objek web_page
, kita akan melihat
bahwa ini adalah dokumen HTML yang memiliki head dan
body (struktur standar HTML).
3. Mengakses Elemen HTML
Untuk mengakses data yang kita butuhkan, kita dapat menggunakan alat pengembang di browser dengan menekan F12. Dengan Element Inspector, kita bisa mengidentifikasi bahwa data yang kita cari berada dalam sebuah tabel di dalam elemen body.
Fungsi html_node()
digunakan untuk mengambil elemen HTML
tertentu, dan html_table()
mengubah elemen tabel menjadi
data frame.
4. Membersihkan Data
Tabel yang kita peroleh mungkin memiliki beberapa baris kosong atau tidak relevan. Kita bisa membersihkannya dengan menghapus baris yang berisi NA dan memberi nama pada kolom-kolom tabel:
Hasilnya adalah tabel yang rapi berisi nama paket R dan deskripsinya.
Berikut adalah teks yang telah digabungkan dengan kode yang sesuai:
3) Scraping Data dari Beberapa Halaman Web
Dalam contoh ini, kita ingin mengambil data dari empat situs web berbeda yang menampilkan skuad pemain di Kejuaraan Eropa.
1. Mengidentifikasi Elemen dengan ID
Pada halaman yang ingin kita scrape, kita menekan
F12 dan menggunakan Element Inspector untuk
menemukan bahwa tabel pemain memiliki ID spesifik (misalnya
yw1
).
2. Membuat Data Frame Referensi
Langkah pertama adalah membuat data frame referensi yang berisi daftar URL dan informasi negara yang ingin kita scrape:
reference_df <- data.frame(
id = 1:4,
code = c("GER", "ESP", "ITA", "FRA"),
country = c("Germany", "Spain", "Italy", "France"),
url = c("https://www.transfermarkt.com/germany/kader/verein/3262/saison_id/2023/plus/1",
"https://www.transfermarkt.com/spain/kader/verein/3375/saison_id/2023/plus/1",
"https://www.transfermarkt.com/italy/kader/verein/3376/saison_id/2023/plus/1",
"https://www.transfermarkt.com/france/kader/verein/3377/saison_id/2023/plus/1")
)
3. Melakukan Scraping dengan Perulangan (Loop)
Setelah kita memiliki referensi URL, kita dapat menggunakan loop untuk mengambil data dari setiap situs web:
library(tidyverse)
library(rvest)
euro24 <- data.frame() # Data frame kosong untuk menyimpan hasil scraping
for (i in 1:nrow(reference_df)) {
temp_url <- reference_df$url[i] # Ambil URL dari daftar referensi
# Membaca halaman HTML
temp_page <- read_html(temp_url)
# Ekstraksi tabel skuad pemain
temp_table <- temp_page %>%
html_node(xpath = '//*[@id="yw1"]/table') %>%
html_table()
# Pembersihan dan pemrosesan data
names(temp_table) <- c("Number", "delete", "delete2", "Name", "Position", "Age", "delete3", "Height",
"Foot", "International_matches", "Goals", "Debut", "Market_value")
temp_df <- temp_table %>%
select(-contains("delete")) %>%
filter(!is.na(Name)) %>%
mutate(code = reference_df$code[i],
country = reference_df$country[i],
International_matches = as.numeric(International_matches))
# Menggabungkan hasil scraping ke dalam satu data frame
euro24 <- bind_rows(euro24, temp_df)
}
# Menampilkan hasil
View(euro24)
Dengan cara ini, kita dapat menggabungkan data dari beberapa halaman web sekaligus ke dalam satu data frame.
4) Scraping Data yang Tidak Berada dalam Tabel
Kadang, data yang kita butuhkan tidak ada dalam tabel, tetapi tersebar di berbagai elemen HTML.
1. Menggunakan ChatGPT untuk Membantu Scraping
Dalam contoh ini, kita ingin mengekstrak judul komunitas, deskripsi, jumlah anggota, dan harga berlangganan dari sebuah halaman komunitas online.
Tekan F12, gunakan Element Inspector untuk
menemukan bahwa setiap komunitas berada dalam elemen
<div>
dengan kelas tertentu.
- Klik kanan elemen tersebut → Copy → Copy
element.
- Tempel elemen tersebut ke dalam ChatGPT, lalu tanyakan:
“Bagaimana cara mengambil elemen-elemen ini menggunakan rvest di R?”
- ChatGPT akan memberi kita skrip yang mengekstrak elemen-elemen seperti ini:
community_names <- web_page %>% html_nodes(".community-title") %>% html_text()
descriptions <- web_page %>% html_nodes(".description") %>% html_text()
members <- web_page %>% html_nodes(".members-count") %>% html_text()
prices <- web_page %>% html_nodes(".price") %>% html_text()
data <- data.frame(Community = community_names, Description = descriptions, Members = members, Price = prices)
2. Scraping Data dari Banyak Halaman
Jika situs memiliki banyak halaman, kita dapat menggunakan loop dengan parameter halaman dalam URL:
library(dplyr)
library(rvest)
# Definisi URL dasar
base_url <- "https://www.skool.com/discovery?p="
# Inisialisasi list kosong untuk menyimpan data
rankings <- list()
community_names <- list()
descriptions <- list()
meta_info <- list()
# Loop untuk mengambil data dari beberapa halaman (misalnya, 5 halaman)
for (page_num in 1:5) {
# Membangun URL untuk halaman saat ini
url <- paste0(base_url, page_num)
# Membaca HTML dari halaman
temp_page <- read_html(url)
# Ekstraksi data komunitas
community_names[[page_num]] <- temp_page %>%
html_nodes('.styled_TypographyWrapper-sc-m28jfn-8.eolHmvk') %>%
html_text()
# Ekstraksi ranking
rankings[[page_num]] <- temp_page %>%
html_nodes('.styled_DiscoveryCardRanking-sc-13ysp3k-6.ege3Zg') %>%
html_text()
# Ekstraksi deskripsi
descriptions[[page_num]] <- temp_page %>%
html_nodes('.styled_DiscoveryCardDescription-sc-13ysp3k-5.dCJqt6') %>%
html_text()
# Ekstraksi meta informasi (Private/Public, Members, Paid/Free)
meta_info[[page_num]] <- temp_page %>%
html_nodes('.styled_DiscoveryCardMeta-sc-13ysp3k-7.jjNZwic') %>%
html_text()
}
# Menggabungkan list menjadi satu data frame
data <- data.frame(
Ranking = unlist(rankings),
Community = unlist(community_names),
Description = unlist(descriptions),
Meta = unlist(meta_info),
stringsAsFactors = FALSE
)
# Menampilkan hasil
print(data)
- Beberapa situs membatasi scraping karena dapat membebani
server.
- Gunakan scraping secara bertanggung jawab dan hindari mengambil terlalu banyak data dalam satu waktu agar tidak diblokir.
Dengan teknik ini, kita dapat mengekstrak informasi dari berbagai halaman dan menggabungkannya menjadi satu dataset yang rapi.