#!/usr/bin/env node // 기준선 글을 다시 받아 온다. style_profile.mjs의 BASE 값을 다시 재려면 이 파일로 원문을 받는다. // // npm i playwright-core # 브라우저 바이너리는 ~/.cache/ms-playwright 에 있어야 한다 // node scripts/fetch_reference.mjs <출력디렉터리> // // techblog.woowahan.com은 curl·fetch·리더 프록시를 403으로 막는다. 실제 브라우저라야 통과한다. import { chromium } from 'playwright-core'; import { writeFileSync, mkdirSync, readdirSync } from 'node:fs'; import { join } from 'node:path'; const URLS = [ 'https://techblog.woowahan.com/26388/', 'https://techblog.woowahan.com/17416/', 'https://techblog.woowahan.com/13429/', 'https://techblog.woowahan.com/20161/', 'https://techblog.woowahan.com/11238/', ]; const outDir = process.argv[2] || 'reference-corpus'; mkdirSync(outDir, { recursive: true }); // 설치된 chromium 아무거나 고른다 const root = join(process.env.HOME, '.cache/ms-playwright'); const dir = readdirSync(root).filter(d => d.startsWith('chromium-')).sort().pop(); const exe = join(root, dir, 'chrome-linux64', 'chrome'); const browser = await chromium.launch({ executablePath: exe, headless: true }); const ctx = await browser.newContext({ locale: 'ko-KR', userAgent: 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36', }); for (const url of URLS) { const page = await ctx.newPage(); try { await page.goto(url, { waitUntil: 'domcontentloaded', timeout: 60000 }); await page.waitForTimeout(2500); const text = await page.evaluate(() => { const root = document.querySelector('.post-content, .entry-content, article, main') || document.body; const out = []; const walk = (el) => { for (const n of el.children) { const tag = n.tagName.toLowerCase(); if (['script', 'style', 'nav', 'aside', 'footer'].includes(tag)) continue; if (/^h[1-6]$/.test(tag)) out.push(`\n## ${n.innerText.trim()}\n`); else if (tag === 'p') { const t = n.innerText.trim(); if (t) out.push(t); } else if (tag === 'li') { const t = n.innerText.trim(); if (t) out.push('- ' + t); } else if (tag === 'pre') out.push('```\n[CODE]\n```'); else if (tag === 'table') out.push('[TABLE]'); else walk(n); } }; walk(root); return out.join('\n\n'); }); const id = url.match(/(\d+)/)[1]; writeFileSync(join(outDir, `woowa-${id}.md`), text); console.log(`OK ${url} (${text.length}자)`); } catch (e) { console.log(`FAIL ${url}: ${e.message.split('\n')[0]}`); } await page.close(); } await browser.close(); console.log(`\n기준선 다시 재기: node scripts/style_profile.mjs --baseline ${outDir}/*.md`);