Apabila kita ingin menganalisis sesuatu, kita pasti membutuhkan data. Data biasanya tersedia dalam format seperti teks, CSV, atau file Excel, sehingga mudah dimuat ke dalam R dan menjalankan skrip untuk mendapatkan hasil dan jawaban yang dibutuhkan. Namun, jika data tersebut tidak disusun dengan rapi, melainkan tersebar di berbagai lokasi di satu atau lebih situs web, maka kita akan menggunakan Web Scraping. Web scraping adalah teknik untuk mengambil data dari situs web dan mengolahnya dalam bentuk yang lebih terstruktur. Dalam laporan ini, kita akan membahas cara melakukan web scraping di R menggunakan paket rvest. Beberapa contoh yang dibahas mencakup:
Copy-paste tabel sebagai alternatif scraping
Scraping data dari tabel dalam situs web
Scraping dari beberapa situs web sekaligus
Scraping data non-tabel dengan bantuan ChatGPT
Penjelasan dari web scraping, yaitu:
1 Copy-Paste Tabel Menggunakan datapasta
Contoh pertama sebenarnya bukan web scraping, melainkan jalan pintas. Jika Anda menemukan tabel di sebuah situs web dan ingin mengambil informasi dari tabel tersebut ke dalam R, salah satu cara tercepat adalah:
Sorot seluruh sel tabel.
Tahan tombol mouse hingga mencapai header tabel.
Tekan Ctrl + C atau klik kanan dan pilih Copy.
Di R, setelah menginstal paket datapasta, Anda akan memiliki fitur tambahan yang memungkinkan Anda langsung menempelkan data dari clipboard sebagai data frame ke dalam R. Misalnya, saya ingin menyimpan informasi dalam sebuah objek bernama Olympic_medals dan menempelkannya sebagai data frame. Formatnya akan terlihat seperti ini:
Kolom pertama berisi peringkat (rank).
Kolom Nations berisi nama negara.
Kolom lainnya menunjukkan jumlah medali emas, perak, dan perunggu yang dimenangkan, serta totalnya.
Tipe data akan dikenali secara otomatis, dengan nama negara sebagai karakter dan jumlah medali sebagai integer.
## 1) datapasta
library(datapasta)
## Warning: package 'datapasta' was built under R version 4.4.3
#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)
)
print(olympic_medals)
## Rank Nation.(NOC) No..of.Games Gold Silver
## 1 1 United States 28 1061 836
## 2 2 Soviet Union 10 440 357
## 3 3 Germany 25 285 326
## 4 4 Great Britain 29 285 315
## 5 5 China 11 262 199
## 6 6 France 29 226 258
## 7 7 Italy 28 217 188
## 8 8 Hungary 27 181 154
## 9 9 Russia 10 170 157
## 10 10 Japan 23 169 150
## 11 11 Australia 29 167 177
## 12 12 East Germany 5 153 129
## 13 13 Sweden 28 148 176
## 14 14 Finland 26 101 85
## 15 15 South Korea 18 96 91
## 16 16 Netherlands 27 95 104
## 17 17 Romania 22 90 97
## 18 18 Cuba 21 85 71
## 19 19 Poland 22 72 89
## 20 20 Canada 27 71 108
## 21 21 Norway 26 60 51
## 22 22 Bulgaria 21 54 88
## 23 23 Switzerland 29 53 79
## 24 24 New Zealand 24 53 33
## 25 25 Czechoslovakia 16 49 49
## 26 26 Denmark 28 48 78
## 27 27 Spain 24 48 72
## 28 28 Belgium 27 43 54
## 29 29 Türkiye 23 41 26
## 30 30 Brazil 23 37 42
## 31 31 Ukraine 7 35 36
## 32 32 Greece 29 35 45
## 33 33 Kenya 15 35 42
## 34 34 Yugoslavia 18 28 31
## 35 35 South Africa 20 27 33
## 36 36 Jamaica 18 26 36
## 37 37 Iran 17 24 23
## 38 38 Ethiopia 14 23 12
## 39 39 Argentina 25 21 26
## 40 40 Austria 28 19 34
## 41 41 Czechia 7 19 21
## 42 42 North Korea 10 16 16
## 43 43 Kazakhstan 7 15 21
## 44 44 Croatia 8 14 13
## 45 45 Belarus 7 13 30
## 46 46 Mexico 24 13 24
## 47 47 Ireland 22 11 10
## 48 48 Georgia 7 10 12
## 49 49 Uzbekistan 7 10 6
## 50 50 Estonia 13 10 9
## 51 51 Thailand 17 10 8
## 52 52 India 25 10 9
## 53 53 Slovakia 7 10 14
## 54 54 Egypt 23 8 11
## 55 55 Indonesia 16 8 14
## 56 56 Slovenia 8 8 9
## 57 57 Mixed team 3 8 4
## 58 58 Bahamas 17 8 2
## 59 59 Azerbaijan 7 7 14
## 60 60 Chinese Taipei 15 7 11
## 61 61 Morocco 15 7 5
## 62 62 Lithuania 10 6 7
## 63 63 Serbia 5 6 7
## 64 64 Colombia 20 5 13
## 65 65 Portugal 25 5 9
## 66 66 Algeria 14 5 4
## 67 67 Tunisia 15 5 3
## 68 68 Latvia 12 4 11
## 69 69 Uganda 16 4 4
## 70 70 Nigeria 17 3 11
## 71 71 Venezuela 19 3 7
## 72 72 Trinidad and Tobago 18 3 5
## 73 73 Israel 17 3 1
## 74 74 Dominican Republic 15 3 5
## 75 75 Pakistan 18 3 3
## 76 76 Zimbabwe 14 3 4
## 77 77 Cameroon 15 3 1
## 78 78 Ecuador 15 3 2
## 79 79 Kosovo 2 3 0
## 80 80 Mongolia 14 2 11
## 81 81 Armenia 7 2 8
## 82 82 Chile 24 2 7
## 83 83 Puerto Rico 19 2 2
## 84 84 Uruguay 22 2 2
## 85 85 Hong Kong 17 2 3
## 86 86 Qatar 10 2 1
## 87 87 Fiji 15 2 0
## 88 88 Bahrain 10 2 1
## 89 89 Philippines 22 1 5
## 90 90 Independent Olympic Athletes/Participants 4 1 1
## 91 91 Singapore 17 1 2
## 92 92 Vietnam 16 1 3
## 93 93 Costa Rica 16 1 1
## 94 94 Peru 19 1 3
## 95 95 Ivory Coast 14 1 1
## 96 96 Tajikistan 7 1 1
## 97 97 Syria 14 1 1
## 98 98 Grenada 10 1 1
## 99 99 Panama 18 1 0
## 100 100 Jordan 11 1 1
## 101 101 Suriname 13 1 0
## 102 102 Bermuda 19 1 0
## 103 103 Mozambique 11 1 0
## 104 104 Burundi 7 1 1
## 105 105 Luxembourg 24 1 1
## 106 106 United Arab Emirates 10 1 0
## 107 107 Malaysia 14 0 8
## 108 108 Kyrgyzstan 7 0 3
## 109 109 Moldova 7 0 2
## 110 110 Ghana 15 0 1
## 111 111 Namibia 8 0 5
## 112 112 Bohemia 3 0 1
## 113 113 Iceland 21 0 2
## 114 114 Saudi Arabia 12 0 2
## 115 115 Lebanon 18 0 2
## 116 116 San Marino 15 0 1
## 117 117 Kuwait 13 0 0
## 118 118 Sri Lanka 18 0 2
## 119 119 Serbia and Montenegro 1 0 2
## 120 120 Haiti 16 0 1
## 121 121 North Macedonia 7 0 1
## 122 122 Niger 13 0 1
## 123 123 Zambia 14 0 1
## 124 124 British West Indies 1 0 0
## 125 125 Botswana 11 0 1
## 126 126 Tanzania 14 0 2
## 127 127 Afghanistan 15 0 0
## 128 128 Iraq 15 0 0
## 129 129 Sudan 13 0 1
## 130 130 Cyprus 11 0 1
## 131 131 Senegal 15 0 1
## 132 132 Samoa 10 0 1
## 133 133 Guyana 18 0 0
## 134 134 Guatemala 15 0 1
## 135 135 Paraguay 13 0 1
## 136 136 Netherlands Antilles 13 0 1
## 137 137 Gabon 11 0 1
## 138 138 Barbados 13 0 0
## 139 139 Montenegro 4 0 1
## 140 140 Mauritius 10 0 0
## 141 141 Eritrea 6 0 0
## 142 142 Burkina Faso 10 0 0
## 143 143 Virgin Islands 13 0 1
## 144 144 Djibouti 9 0 0
## 145 145 Turkmenistan 7 0 1
## 146 146 Tonga 10 0 1
## 147 147 Togo 11 0 0
## Bronze Total
## 1 739 2636
## 2 325 1122
## 3 363 974
## 4 315 915
## 5 173 634
## 6 280 764
## 7 213 618
## 8 176 511
## 9 178 505
## 10 178 497
## 11 213 557
## 12 127 409
## 13 179 503
## 14 119 305
## 15 100 287
## 16 122 321
## 17 121 308
## 18 85 241
## 19 137 298
## 20 147 326
## 21 49 160
## 22 82 224
## 23 73 205
## 24 53 139
## 25 45 143
## 26 79 205
## 27 47 167
## 28 58 155
## 29 37 104
## 30 71 150
## 31 68 139
## 32 41 121
## 33 36 113
## 34 31 90
## 35 29 89
## 36 25 87
## 37 29 76
## 38 23 58
## 39 30 77
## 40 41 94
## 41 27 67
## 42 22 54
## 43 36 72
## 44 14 41
## 45 42 85
## 46 36 73
## 47 14 35
## 48 18 40
## 49 20 36
## 50 17 36
## 51 17 35
## 52 14 35
## 53 8 32
## 54 19 38
## 55 15 37
## 56 11 28
## 57 4 16
## 58 6 14
## 59 28 49
## 60 18 36
## 61 12 24
## 62 13 26
## 63 11 24
## 64 15 33
## 65 14 28
## 66 8 17
## 67 7 15
## 68 6 21
## 69 3 11
## 70 13 27
## 71 9 19
## 72 11 19
## 73 9 13
## 74 4 12
## 75 4 10
## 76 1 8
## 77 2 6
## 78 0 5
## 79 0 3
## 80 17 30
## 81 8 18
## 82 4 13
## 83 6 10
## 84 6 10
## 85 4 9
## 86 5 8
## 87 1 3
## 88 0 3
## 89 8 14
## 90 3 5
## 91 2 5
## 92 1 5
## 93 2 4
## 94 0 4
## 95 2 4
## 96 2 4
## 97 2 4
## 98 1 3
## 99 2 3
## 100 1 3
## 101 1 2
## 102 1 2
## 103 1 2
## 104 0 2
## 105 0 2
## 106 1 2
## 107 5 13
## 108 4 7
## 109 4 6
## 110 4 5
## 111 0 5
## 112 3 4
## 113 2 4
## 114 2 4
## 115 2 4
## 116 2 3
## 117 3 3
## 118 0 2
## 119 0 2
## 120 1 2
## 121 1 2
## 122 1 2
## 123 1 2
## 124 2 2
## 125 1 2
## 126 0 2
## 127 2 2
## 128 1 1
## 129 0 1
## 130 0 1
## 131 0 1
## 132 0 1
## 133 1 1
## 134 0 1
## 135 0 1
## 136 0 1
## 137 0 1
## 138 1 1
## 139 0 1
## 140 1 1
## 141 1 1
## 142 1 1
## 143 0 1
## 144 1 1
## 145 0 1
## 146 0 1
## 147 1 1
2 Scraping Data dari Tabel dalam Situs Web
Jika tabel tidak bisa disalin secara manual, kita memerlukan paket rvest. Paket ini diucapkan seperti “Harvest”, karena kita ingin memanen data dari situs web. Fungsi pertama yang kita perlukan adalah read_html(), yang memerlukan URL sebagai input. Misalnya, kita ingin mengambil daftar paket R dalam urutan alfabet dari sebuah situs web. Jika kita menjalankan kode untuk membaca HTML dari situs tersebut, kita akan melihat bahwa objek yang dihasilkan adalah dokumen HTML dengan struktur head dan body.
Saat kita melihat isi halaman web tersebut, kita melihat bahwa informasi yang kita butuhkan tersembunyi di dalam node HTML. Dengan menekan F12, kita bisa membuka alat pengembang dan menggunakan element inspector untuk menemukan elemen yang memuat data yang kita butuhkan. Misalnya, kita ingin mengambil tabel berisi daftar paket R. Dengan menggunakan HTML node inspector, kita bisa menemukan elemen yang menyimpan data tersebut. Kemudian, kita bisa menggunakan html_node() untuk mengambil elemen tersebut dan html_table() untuk mengubahnya menjadi data frame. Setelah dibersihkan (menghapus NA dan placeholder di antara huruf alfabet), kita mendapatkan tabel yang rapi berisi nama dan deskripsi paket R.
## 2) basic webscraping
library(rvest)
## Warning: package 'rvest' was built under R version 4.4.3
url <- "https://cran.r-project.org/web/packages/available_packages_by_name.html"
# Membaca HTML dari situs
webpage <- read_html(url)
# Mengambil tabel dari halaman
paket_table <- webpage %>% html_node("table") %>% html_table(fill = TRUE)
# Menampilkan data yang telah diambil
print(paket_table)
## # A tibble: 22,222 × 2
## X1 X2
## <chr> <chr>
## 1 "" <NA>
## 2 "A3" "Accurate, Adaptable, and Accessible Error Metrics for Predi…
## 3 "AalenJohansen" "Conditional Aalen-Johansen Estimation"
## 4 "AATtools" "Reliability and Scoring Routines for the Approach-Avoidance…
## 5 "ABACUS" "Apps Based Activities for Communicating and Understanding\n…
## 6 "abasequence" "Coding 'ABA' Patterns for Sequence Data"
## 7 "abbreviate" "Readable String Abbreviation"
## 8 "abc" "Tools for Approximate Bayesian Computation (ABC)"
## 9 "abc.data" "Data Only: Tools for Approximate Bayesian Computation (ABC)"
## 10 "ABC.RAP" "Array Based CpG Region Analysis Pipeline"
## # ℹ 22,212 more rows
3 Scraping Data dari Beberapa Situs Web Sekaligus
Untuk mengambil data dari beberapa sumber sekaligus, kita bisa membuat daftar URL dan melakukan scraping secara otomatis. Dalam contoh berikutnya, saya ingin mengambil data dari empat situs web berbeda yang memuat daftar pemain untuk Kejuaraan Eropa (EURO). Ketika kita menggunakan F12, kita melihat bahwa tabel yang kita butuhkan tersembunyi dalam elemen dengan ID tertentu. Dalam hal ini, ID yang diperlukan adalah “yw1”.
Langkah-langkahnya:
Buat data frame referensi yang menyimpan daftar URL dan ID tabel.
Gunakan loop untuk membaca setiap halaman web dan mengambil tabel yang kita butuhkan.
Bersihkan data (hapus kolom yang tidak diperlukan, hilangkan duplikasi, dll.).
Gabungkan hasil scraping dari empat situs web menjadi satu tabel.
Setelah loop selesai, kita mendapatkan data dari empat negara sekaligus (Jerman, Spanyol, Italia, dan Prancis) dengan hanya beberapa baris kode.
# Memuat pustaka yang diperlukan
library(rvest)
library(dplyr)
##
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
##
## filter, lag
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
# Daftar URL dan ID tabel yang akan di-scrape
data_sources <- data.frame(
country = c("Jerman", "Spanyol", "Italia", "Prancis"),
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"
),
table_id = '//*[@id="yw1"]' # XPath untuk elemen tabel
)
# List untuk menyimpan data dari tiap halaman
all_data <- list()
# Loop untuk mengambil data dari setiap situs
for (i in 1:nrow(data_sources)) {
tryCatch({
# Baca halaman web
page <- read_html(data_sources$url[i])
# Ambil tabel menggunakan XPath
table <- page %>% html_node(xpath = data_sources$table_id) %>% html_table(fill = TRUE)
# Pastikan tabel ada sebelum diproses
if (!is.null(table)) {
table$Country <- data_sources$country[i] # Tambahkan kolom negara
all_data[[i]] <- table
} else {
message("Tabel tidak ditemukan untuk ", data_sources$country[i])
}
}, error = function(e) {
message("Gagal mengambil data untuk ", data_sources$country[i], ": ", e$message)
})
}
## Gagal mengambil data untuk Jerman: `xpath` must be a single string, not a character vector.
## Gagal mengambil data untuk Spanyol: `xpath` must be a single string, not a character vector.
## Gagal mengambil data untuk Italia: `xpath` must be a single string, not a character vector.
## Gagal mengambil data untuk Prancis: `xpath` must be a single string, not a character vector.
# Gabungkan semua hasil jika ada data yang berhasil diambil
if (length(all_data) > 0) {
final_data <- bind_rows(all_data)
print(final_data)
} else {
message("Tidak ada data yang berhasil diambil.")
}
## Tidak ada data yang berhasil diambil.
4 Scraping Data Non-Tabel dengan ChatGPT
Misalnya, kita ingin mengekstrak informasi dari 1000 komunitas teratas yang terdaftar di halaman Discovery School. Informasi yang dibutuhkan:
Nama komunitas
Deskripsi
Status (private/public)
Jumlah anggota
Biaya berlangganan
Ketika kita menekan F12, kita bisa melihat bahwa informasi ini tidak ada dalam tabel, melainkan tersebar di berbagai nodes HTML.
Trik praktis:
Klik kanan pada elemen yang berisi data yang kita butuhkan.
Pilih Copy Element.
Tempelkan kode HTML ke dalam ChatGPT dan tanyakan di mana lokasi informasi yang kita butuhkan.
ChatGPT akan menganalisis kode HTML dan memberikan skrip R yang bisa digunakan untuk mengambil data tersebut.
Jika kita ingin mengambil data dari beberapa halaman, kita bisa membuat URL dinamis dengan mengganti nomor halaman di dalam loop. Jika data tersebar di elemen non-tabel, kita bisa menggunakan html_nodes() untuk mengekstrak informasi yang relevan.
# Memuat pustaka yang diperlukan
library(rvest)
library(dplyr)
# Daftar URL komunitas virtual
urls <- c(
"https://www.reddit.com/r/programming/",
"https://www.deviantart.com/",
"https://www.flickr.com/groups/central/",
"https://www.goodreads.com/group/show/1-goodreads-authors"
)
# Inisialisasi data frame untuk menyimpan data komunitas
community_data <- data.frame(
Name = character(),
Description = character(),
Members = character(),
Status = character(),
stringsAsFactors = FALSE
)
# Fungsi untuk membersihkan teks
clean_text <- function(text) {
gsub("[\r\n\t]", "", text) %>% trimws()
}
# Loop melalui setiap URL
for (url in urls) {
# Coba untuk membaca halaman web
try({
webpage <- read_html(url)
# Mengambil elemen spesifik berdasarkan struktur halaman
if (grepl("reddit", url)) {
name <- webpage %>% html_node("h1") %>% html_text() %>% clean_text()
description <- webpage %>% html_node("p") %>% html_text() %>% clean_text()
members <- webpage %>% html_node(".subscribers") %>% html_text() %>% clean_text()
status <- webpage %>% html_node(".usercount") %>% html_text() %>% clean_text()
} else if (grepl("deviantart", url)) {
name <- webpage %>% html_node(".group-name") %>% html_text() %>% clean_text()
description <- webpage %>% html_node(".group-description") %>% html_text() %>% clean_text()
members <- webpage %>% html_node(".group-stats") %>% html_text() %>% clean_text()
status <- "Aktif"
} else if (grepl("flickr", url)) {
name <- webpage %>% html_node(".group-title") %>% html_text() %>% clean_text()
description <- webpage %>% html_node(".group-description") %>% html_text() %>% clean_text()
members <- webpage %>% html_node(".member-count") %>% html_text() %>% clean_text()
status <- "Aktif"
} else if (grepl("goodreads", url)) {
name <- webpage %>% html_node("#groupName") %>% html_text() %>% clean_text()
description <- webpage %>% html_node("#description") %>% html_text() %>% clean_text()
members <- webpage %>% html_node(".members") %>% html_text() %>% clean_text()
status <- "Aktif"
} else {
name <- NA
description <- NA
members <- NA
status <- NA
}
# Menambahkan data ke data frame
community_data <- rbind(community_data, data.frame(
Name = name,
Description = description,
Members = members,
Status = status,
stringsAsFactors = FALSE
))
}, silent = TRUE)
}
# Menampilkan data komunitas
print(community_data)
## Name
## 1 <NA>
## 2 <NA>
## 3 <NA>
## Description
## 1 <NA>
## 2 Deskripsi GrupWelcome to FlickrCentral! Just like Grand Central but without the oyster bar, the trains, New York City...FlickrCentral is a place for the newbies to get a taste of what Flickr is about, and a place for the more experienced users to keep a finger on the pulse of our favorite addiction. This group is for viewing Flickr from high above - a place for posts on things that are about Flickr or would interest MOST Flickrites.We adhere to Flickr's Group Guidelines and Community Guidelines.This is a moderated group. The moderators retain the right to delete (or lock as appropriate) threads and comments that do not follow these rules, guidelines or are perceived to be abusive, redundant, self-promotional/commercial or not leading to novel discussion.
## 3 <NA>
## Members Status
## 1 <NA> Aktif
## 2 <NA> Aktif
## 3 <NA> Aktif