diff --git a/backend/src/routes/repos.js b/backend/src/routes/repos.js index 6ce62d6..e26656a 100644 --- a/backend/src/routes/repos.js +++ b/backend/src/routes/repos.js @@ -9,7 +9,8 @@ function computeDaysUntilDeletion(row) { } function formatRepo(row) { - return { ...row, days_until_deletion: computeDaysUntilDeletion(row) }; + const { scraped_at, is_today, ...rest } = row; + return { ...rest, days_until_deletion: computeDaysUntilDeletion(row) }; } function getRepos(req, res) { diff --git a/backend/src/scraper.js b/backend/src/scraper.js index 9b764b1..ebe4ed5 100644 --- a/backend/src/scraper.js +++ b/backend/src/scraper.js @@ -89,13 +89,14 @@ function extractFeaturesSection(readme, description) { if (result && result.length > 20) return result; } - // 兜底:取README正文第一段有意义的文字(跳过徽章行) + // 兜底:取README正文第一段有意义的文字(跳过徽章行和分隔线) const lines = readme.split('\n'); const paragraphs = []; for (const line of lines) { const trimmed = line.trim(); if (!trimmed || trimmed.startsWith('#') || trimmed.startsWith('!') || trimmed.startsWith('[!') || trimmed.startsWith('<')) continue; if (trimmed.startsWith('[![') || trimmed.match(/^\[!\[/)) continue; + if (/^[-=]{3,}$/.test(trimmed)) continue; if (trimmed.length > 40) paragraphs.push(trimmed); if (paragraphs.length >= 3) break; } diff --git a/backend/src/translate.js b/backend/src/translate.js index 7618a0c..ac1cadd 100644 --- a/backend/src/translate.js +++ b/backend/src/translate.js @@ -6,8 +6,8 @@ const HTML_TAG_RE = /<[^>]{1,100}>/g; function cleanText(text) { if (!text) return text; return text - .replace(HTML_TAG_RE, ' ') // 去除 HTML 标签 - .replace(/&[a-z]+;/gi, ' ') // 去除 HTML 实体 + .replace(HTML_TAG_RE, ' ') + .replace(/&[a-z]+;/gi, ' ') .replace(/\s+/g, ' ') .trim(); } @@ -15,21 +15,25 @@ function cleanText(text) { async function translate(text) { const cleaned = cleanText(text); if (!cleaned || cleaned.length < 5) return cleaned || text; - if (CJK_RE.test(cleaned)) return cleaned; // 已含中文,跳过 + if (CJK_RE.test(cleaned)) return cleaned; try { - const res = await axios.get('https://api.mymemory.translated.net/get', { - params: { q: cleaned.slice(0, 500), langpair: 'en|zh-CN' }, - headers: { 'User-Agent': 'github-trending-app/1.0' }, + const res = await axios.get('https://translate.googleapis.com/translate_a/single', { + params: { + client: 'gtx', + sl: 'en', + tl: 'zh-CN', + dt: 't', + q: cleaned.slice(0, 500), + }, + headers: { 'User-Agent': 'Mozilla/5.0' }, timeout: 10000, }); - const translated = res.data?.responseData?.translatedText; - if (!translated || translated === cleaned || translated.startsWith('PLEASE SELECT')) { - return cleaned; - } + const translated = res.data?.[0]?.map(s => s?.[0]).filter(Boolean).join(''); + if (!translated || translated === cleaned) return cleaned; return translated.trim(); } catch { - return cleaned; // 失败静默降级,返回清理后原文 + return cleaned; } }