Back to Home
Gistify Snippet
kyiov
3d agoยท1 file(s)
Public

GitHub Trending Repositories Scraper

Modul JavaScript ini mengekstrak daftar repositori trending GitHub secara asinkron, memanfaatkan Cheerio untuk parsing HTML efisien dan menyediakan fallback data saat gagal.

#scraper#github#cheerio#nodejs#web-scraping
1
Raw
github_trending.jsjavascript
89 lines
1/**
2 * @fileoverview Modul Scraper GitHub Trending Repositories.
3 *
4 * Mengimplementasikan web scraper ringan untuk mengekstrak daftar repositori yang sedang tren di GitHub.
5 * Dilengkapi dengan penanganan kesalahan otomatis, fallback data analitik, dan parsing elemen DOM
6 * yang efisien tanpa ketergantungan library eksternal yang berat.
7 *
8 * @module scrapers/github-trending
9 * @version 1.1.0
10 * @author kyiov
11 * @license MIT
12 */
13
14import * as cheerio from 'cheerio'
15import { pathToFileURL } from 'node:url'
16
17/**
18 * @typedef {Object} TrendingRepo
19 * @property {string} title - Nama lengkap repositori (owner/repo)
20 * @property {string} desc - Deskripsi repositori
21 * @property {string} lang - Bahasa pemrograman utama
22 * @property {string} starsToday - Jumlah perolehan bintang hari ini
23 */
24
25/**
26 * Mengambil daftar repositori trending dari GitHub secara asinkron.
27 *
28 * @param {number} [limit=5] - Jumlah repositori maksimum yang ingin diekstrak
29 * @returns {Promise<TrendingRepo[]>} Daftar repositori yang sedang tren
30 */
31export async function fetchGitHubTrending(limit = 5) {
32 try {
33 const res = await fetch('https://github.com/trending', {
34 headers: {
35 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
36 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8'
37 },
38 signal: AbortSignal.timeout(8000)
39 })
40
41 if (!res.ok) throw new Error(`HTTP ${res.status}`)
42 const html = await res.text()
43 const $ = cheerio.load(html)
44 const repos = []
45
46 $('article.Box-row').slice(0, limit).each((_, el) => {
47 const rawTitle = $(el).find('h2 a').text().replace(/\s+/g, ' ').trim()
48 const title = rawTitle.replace(/\s*\/\s*/g, '/')
49 const desc = $(el).find('p').text().replace(/\s+/g, ' ').trim()
50 const lang = $(el).find('[itemprop="programmingLanguage"]').text().trim() || 'Tech'
51 const starsToday = $(el).find('span.d-inline-block.float-sm-right').text().replace(/\s+/g, ' ').trim() || ''
52
53 if (title) {
54 repos.push({
55 title,
56 desc: desc || 'Proyek open-source populer di GitHub',
57 lang,
58 starsToday
59 })
60 }
61 })
62
63 if (repos.length > 0) return repos
64 } catch (e) {
65 console.warn('[GitHub Trending Scraper] Galat jaringan/DOM, beralih ke fallback:', e.message)
66 }
67
68 return [
69 { title: 'Open-source AI Tools', desc: 'Perkembangan pesat model reasoning AI & tool coding otonom di komunitas open-source.', lang: 'AI / Python', starsToday: '๐Ÿ”ฅ Trending' },
70 { title: 'Modern Web & Lightweight Frameworks', desc: 'Tren transisi ke framework fullstack yang lebih cepat dengan memory footprint kecil.', lang: 'TypeScript / Rust', starsToday: '๐Ÿ”ฅ Trending' },
71 { title: 'Local LLM & Edge Inference', desc: 'Inovasi menjalankan model AI besar langsung di laptop/HP tanpa GPU server mahal.', lang: 'C++ / ONNX', starsToday: '๐Ÿ”ฅ Trending' }
72 ]
73}
74
75export default {
76 fetchGitHubTrending
77}
78
79// Eksekusi mandiri untuk pengujian langsung tanpa argumen CLI
80if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
81 try {
82 const repos = await fetchGitHubTrending(3)
83 console.log(JSON.stringify(repos, null, 2))
84 } catch (err) {
85 console.error('Galat eksekusi:', err.message || err)
86 }
87}
88
89
Discussion & Comments0

No comments yet โ€” be the first to leave feedback or start a code discussion.

Sign in with your GitHub account to write comments and join the discussion.