Kode Class 10 Scrape (WEBTOONS)

JavaScriptPublic
by zx-apiJul 28, 2026, 06:13 AMExpires: Never62 views
Kode Class 10 Scrape (WEBTOONS)
Raw
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