Kode Class 10 Scrape (WEBTOONS)
JavaScriptPublicby zx-apiJul 28, 2026, 06:13 AMExpires: Never62 views
1/*
2 * Name: Zix Anjay Slebeww
3 * saluran: https://whatsapp.com/channel/0029Vb6P2e1E50UZYaX4wI0W
4 * support zix: http://unggah.web.id/7cL2Sj1qEbxw.jpeg
5 *
6 * site download video: https://savenest.web.id
7*/
8
9const axios = require('axios');
10const cheerio = require('cheerio');
11
12class WebtoonScraper {
13 constructor() {
14 this.baseUrl = 'https://m.webtoons.com/id';
15 this.imageBaseUrl = 'https://webtoon-phinf.pstatic.net';
16
17 this.client = axios.create({
18 headers: {
19 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36',
20 'Referer': 'https://www.webtoons.com/id',
21 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8'
22 }
23 });
24 }
25
26 async getTrending() {
27 try {
28 const { data } = await this.client.get(this.baseUrl);
29 const $ = cheerio.load(data);
30 const results = [];
31
32 $('ul._trending_page li.item').each((i, el) => {
33 const link = $(el).find('a.link');
34 const title = $(el).find('.info_text .title').text().trim();
35 const genre = $(el).find('.info_text .genre').text().trim();
36 const url = link.attr('href');
37 const titleNo = link.attr('data-title-no');
38 const imageUrl = $(el).find('.image_wrap img').attr('src');
39 const rank = $(el).find('.ranking_text strong span.blind').text().replace(/"/g, '').trim();
40
41 if(title) {
42 results.push({
43 rank: parseInt(rank),
44 titleNo: parseInt(titleNo),
45 title, genre, url, imageUrl
46 });
47 }
48 });
49 return results;
50 } catch (error) {
51 console.error('Gagal mengambil data Trending:', error.message);
52 return [];
53 }
54 }
55
56 async getDaily(day = 'thursday') {
57 try {
58 const url = `${this.baseUrl}/originals/${day}/title?sortOrder=MANA`;
59 const { data } = await this.client.get(url);
60
61 return data.map(item => ({
62 titleNo: item.titleNo,
63 title: item.title,
64 genre: item.representGenre,
65 likes: item.likeitCount,
66 isMature: item.unsuitableForChildren,
67 url: `${this.baseUrl}/${item.representGenreSeoCode}/${item.titleGroupName}/list?title_no=${item.titleNo}`,
68 imageUrl: `${this.imageBaseUrl}${item.posterThumbnail}?type=q70`
69 }));
70 } catch (error) {
71 console.error(`Gagal mengambil API JSON (${day}):`, error.message);
72 return [];
73 }
74 }
75
76 async search(keyword) {
77 try {
78 const [thursdayData, fridayData] = await Promise.all([
79 this.getDaily('thursday'),
80 this.getDaily('friday')
81 ]);
82
83 const allWebtoons = [...thursdayData, ...fridayData];
84 return allWebtoons.filter(item =>
85 item.title.toLowerCase().includes(keyword.toLowerCase())
86 );
87 } catch (error) {
88 console.error('Gagal melakukan pencarian:', error.message);
89 return [];
90 }
91 }
92
93 async getPopular() {
94 try {
95 const { data } = await this.client.get(this.baseUrl);
96 const $ = cheerio.load(data);
97 const results = [];
98
99 $('ul._popular_page li.item').each((i, el) => {
100 const link = $(el).find('a.link');
101 const title = $(el).find('.info_text .title').text().trim();
102 const genre = $(el).find('.info_text .genre').text().trim();
103 const url = link.attr('href');
104 const titleNo = link.attr('data-title-no');
105 const imageUrl = $(el).find('.image_wrap img').attr('src');
106 const rankText = $(el).find('[class^="ranking_number_"] span.blind').text().replace(/"/g, '').trim();
107
108 if(title) {
109 results.push({
110 rank: parseInt(rankText) || (i + 1),
111 titleNo: parseInt(titleNo),
112 title, genre, url, imageUrl
113 });
114 }
115 });
116 return results;
117 } catch (error) {
118 console.error('Gagal mengambil data Populer:', error.message);
119 return [];
120 }
121 }
122
123 async getByCategory() {
124 try {
125 const { data } = await this.client.get(this.baseUrl);
126 const $ = cheerio.load(data);
127 const results = {};
128
129 $('#genre_list ul[role="tabpanel"]').each((i, listEl) => {
130 const categoryName = $(listEl).attr('aria-label');
131 if(!categoryName) return;
132
133 results[categoryName] = [];
134
135 $(listEl).find('li.item').each((j, itemEl) => {
136 const link = $(itemEl).find('a.link');
137 const title = $(itemEl).find('.info_text .title').text().trim();
138 const viewCount = $(itemEl).find('.info_text .view_count').text().trim();
139 const url = link.attr('href');
140 const titleNo = link.attr('data-title-no');
141 const imageUrl = $(itemEl).find('.image_wrap img').attr('src');
142
143 results[categoryName].push({
144 titleNo: parseInt(titleNo),
145 title, viewCount, url, imageUrl
146 });
147 });
148 });
149 return results;
150 } catch (error) {
151 console.error('Gagal mengambil data Kategori:', error.message);
152 return {};
153 }
154 }
155
156 async getNewReleases() {
157 try {
158 const { data } = await this.client.get(this.baseUrl);
159 const $ = cheerio.load(data);
160 const results = [];
161
162 $('ul.newly_released li.item').each((i, el) => {
163 const link = $(el).find('a.link');
164 const url = link.attr('href');
165 const titleNo = link.attr('data-title-no');
166 const imageUrl = $(el).find('.image_wrap img').attr('src');
167
168 let title = "Unknown";
169 if (url) {
170 const urlParts = url.split('/');
171 title = urlParts[urlParts.length - 2].replace(/-/g, ' ');
172 }
173
174 if(titleNo) results.push({ titleNo: parseInt(titleNo), title, url, imageUrl });
175 });
176 return results;
177 } catch (error) {
178 console.error('Gagal mengambil Rilis Terbaru:', error.message);
179 return [];
180 }
181 }
182
183 async getCanvas() {
184 try {
185 const canvasUrl = `${this.baseUrl}/canvas`;
186 const { data } = await this.client.get(canvasUrl);
187 const $ = cheerio.load(data);
188 const results = [];
189
190 $('ul.type_canvas li.item').each((i, el) => {
191 const link = $(el).find('a.link');
192 const title = $(el).find('.info_text .title').text().trim();
193 const genre = $(el).find('.info_text .genre').text().trim() || "Tidak ada";
194 const url = link.attr('href');
195 const titleNo = link.attr('data-title-no');
196 const imageUrl = $(el).find('.image_wrap img').attr('src');
197
198 if(title) results.push({ titleNo: parseInt(titleNo), title, genre, url, imageUrl });
199 });
200 return results;
201 } catch (error) {
202 console.error('Gagal mengambil data Canvas:', error.message);
203 return [];
204 }
205 }
206
207 async getDailyViewCount() {
208 try {
209 const { data } = await this.client.get(this.baseUrl);
210 const $ = cheerio.load(data);
211 const results = [];
212
213 $('#daily_list li.item').each((i, el) => {
214 const title = $(el).find('.info_text .title').text().trim();
215 const genre = $(el).find('.info_text .genre').text().trim();
216 const link = $(el).find('a.link').attr('href');
217 const titleNo = $(el).find('a.link').attr('data-title-no');
218 const imageUrl = $(el).find('.image_wrap img').attr('src');
219 const viewCount = $(el).find('.info_text .view_count.type_like').text().trim();
220 const badge = $(el).find('.icon_area .ico').text().trim() || null;
221
222 if(title) results.push({ titleNo: parseInt(titleNo), title, genre, badge, viewCount, link, imageUrl });
223 });
224 return results;
225 } catch (error) {
226 console.error('Gagal mengambil data Jadwal Harian (HTML):', error.message);
227 return [];
228 }
229 }
230
231 async getCanvasDiscoverView() {
232 try {
233 const canvasUrl = `${this.baseUrl}/canvas`;
234 const { data } = await this.client.get(canvasUrl);
235 const $ = cheerio.load(data);
236 const results = [];
237
238 $('.list_discover li').each((i, el) => {
239 const title = $(el).find('.tit_discover').text().trim();
240 const genre = $(el).find('.genre').text().trim();
241 const link = $(el).find('a.link_discover').attr('href');
242 const imageUrl = $(el).find('.thumb_discover img.img_discover').attr('src');
243 const likes = $(el).find('.info_grade .grade_num').text().trim();
244
245 if(title) results.push({ title, genre, likes, link, imageUrl });
246 });
247 return results;
248 } catch (error) {
249 console.error('Gagal mengambil data Canvas Discover:', error.message);
250 return [];
251 }
252 }
253
254 async getEpisodeImages(episodeUrl) {
255 try {
256 const targetUrl = episodeUrl.replace('https://m.', 'https://www.');
257
258 const { data } = await this.client.get(targetUrl);
259 const $ = cheerio.load(data);
260 const images = [];
261
262 $('#_imageList img._images').each((i, el) => {
263 let imgUrl = $(el).attr('data-url');
264
265 if (imgUrl && imgUrl.startsWith('http') && !imgUrl.includes('warning')) {
266 images.push(imgUrl);
267 }
268 });
269
270 return [...new Set(images)];
271 } catch (error) {
272 console.error('Gagal mengambil gambar episode:', error.message);
273 return [];
274 }
275 }
276}
277
278(async () => {
279 const scraper = new WebtoonScraper();
280 console.log("Memulai pengujian SEMUA fitur scraper...\n");
281
282 console.log("=== 1. TEST TRENDING ===");
283 const trending = await scraper.getTrending();
284 console.log(`Berhasil mengambil ${trending.length} judul trending.`);
285 if (trending.length > 0) console.log("Top 1 Trending:", trending[0]);
286
287 console.log("\n=== 2. TEST JADWAL HARIAN (JSON) ===");
288 const thursday = await scraper.getDaily('thursday');
289 console.log(`Berhasil mengambil ${thursday.length} judul rilis hari Kamis.`);
290 if (thursday.length > 0) console.log("Data pertama:", thursday[0]);
291
292 console.log("\n=== 3. TEST SEARCH ===");
293 const keyword = 'King';
294 const searchRes = await scraper.search(keyword);
295 console.log(`Ditemukan ${searchRes.length} judul dengan kata '${keyword}'.`);
296 if (searchRes.length > 0) console.log("Hasil pencarian pertama:", searchRes[0].title);
297
298 console.log("\n=== 4. TEST POPULER ===");
299 const popular = await scraper.getPopular();
300 console.log(`Berhasil mengambil ${popular.length} judul populer.`);
301 if (popular.length > 0) console.log("Top 1 Populer:", popular[0].title);
302
303 console.log("\n=== 5. TEST KATEGORI (GENRE) ===");
304 const category = await scraper.getByCategory();
305 const listAksi = category['Aksi'] || [];
306 console.log(`Ditemukan ${listAksi.length} webtoon di kategori Aksi.`);
307 if (listAksi.length > 0) console.log("Contoh Aksi Pertama:", listAksi[0].title, "->", listAksi[0].viewCount);
308
309 console.log("\n=== 6. TEST RILIS TERBARU ===");
310 const newReleases = await scraper.getNewReleases();
311 console.log(`Berhasil mengambil ${newReleases.length} judul rilis terbaru.`);
312 if (newReleases.length > 0) console.log("Rilis terbaru pertama:", newReleases[0]);
313
314 console.log("\n=== 7. TEST CANVAS ===");
315 const canvas = await scraper.getCanvas();
316 console.log(`Berhasil mengambil ${canvas.length} judul canvas.`);
317 if (canvas.length > 0) console.log("Canvas pertama:", canvas[0].title);
318
319 console.log("\n=== 8. TEST JADWAL HTML (VIEW COUNT & BADGE) ===");
320 const dailyHtml = await scraper.getDailyViewCount();
321 console.log(`Berhasil mengambil ${dailyHtml.length} jadwal HTML.`);
322 if (dailyHtml.length > 0) console.log("Jadwal HTML pertama:", dailyHtml[0].title, "| Views:", dailyHtml[0].viewCount);
323
324 console.log("\n=== 9. TEST CANVAS TERPOPULER MINGGU INI ===");
325 const canvasDiscover = await scraper.getCanvasDiscoverView();
326 console.log(`Berhasil mengambil ${canvasDiscover.length} canvas terpopuler.`);
327 if (canvasDiscover.length > 0) console.log("Terpopuler 1:", canvasDiscover[0].title, "| Likes:", canvasDiscover[0].likes);
328
329 console.log("\n=== 10. TEST AMBIL PANEL GAMBAR VIEWER ===");
330 const episodeUrl = "https://m.webtoons.com/id/action/manajer-kim/episode-1/viewer?title_no=3856&episode_no=1";
331 const panelImages = await scraper.getEpisodeImages(episodeUrl);
332 console.log(`Berhasil mengekstrak ${panelImages.length} panel gambar dari episode Manajer Kim.`);
333 if (panelImages.length > 0) {
334 console.log("URL Gambar Panel 1:", panelImages[0]);
335 console.log("URL Gambar Panel 2:", panelImages[1]);
336 console.log("URL Gambar Panel 3:", panelImages[2]);
337 }
338
339 console.log("\nSemua pengujian selesai! ๐");
340})();340 linesยท14,068 charsยท13.7 KB
WwrapยทFfullscreen