현재 이 라이브러리는 개발 중인 상태입니다.
이 프로젝트의 초기 구현은 EAT-SSU/Food-Crawling 내부 구현을 바탕으로 작성되었습니다.
- Node.js:
>= 18 - 공개 라이선스: GPL-3.0
- OpenAI 파서를 사용하려면 프로젝트에
openai가 별도 설치되어 있어야 합니다. (openai는 선택 의존성입니다)
패키지 배포는 다음 스크립트를 사용합니다.
pnpm run release:patch
pnpm run release:minor
pnpm run release:majorUsing npm:
npm i @bluessu/meal-scraperGPT 파서를 사용하려면 먼저 OpenAI 클라이언트를 설치하세요.
pnpm add openaiUsing yarn
yarn add @bluessu/meal-scraperUsing pnpm:
pnpm add @bluessu/meal-scrapercreateMealClient()또는new MealClient()로 클라이언트 생성- 단건 조회/배치 조회/범위 조회 지원
- 날짜 입력을
string또는Date로 유연하게 지원 - 내부 구현 분리로 공개 API가 간결하고 유지보수하기 쉬운 구조
src/index.ts에서 노출되는 주요 API는 다음과 같습니다.
MealClientcreateMealClientnormalizeMenuDatebuildDateRange- 타입
MenuDateInputMenuDateParserModeMealClientOptionsRangeOptions
- 도메인/설정
CafeteriaTypeRawMenuDataDailyMenuFoodCrawlerSettingsdefaultSettings
- 예외
BaseCafeteriaExceptionHolidayExceptionMenuFetchExceptionMenuParseException
import {
MealClient,
createMealClient,
CafeteriaType,
normalizeMenuDate,
buildDateRange,
} from "@bluessu/meal-scraper";
const client = createMealClient();
await client.getRawMenu(CafeteriaType.DODAM, new Date());
await client.getDailyMenu(CafeteriaType.HAKSIK, "2026-02-28");
await client.getDailyMenusByRange(CafeteriaType.FACULTY, "2026-02-28", "2026-03-02", {
concurrency: 3,
});export type ParserMode = "noop" | "gpt" | "custom";noop(기본): 기본 파서(NoopMenuParser) 사용gpt: OpenAI 파서 사용 (gptApiKey필수)custom: 직접 구현한 파서를parserImpl로 주입
import { createMealClient } from "@bluessu/meal-scraper";
// GPT 모드 예시 (키가 없으면 생성 단계에서 에러)
const gptClient = createMealClient({
parser: "gpt",
gptApiKey: process.env.OPENAI_API_KEY,
});
// 커스텀 파서 주입 예시
const customClient = createMealClient({
parser: "custom",
parserImpl: {
parseMenu: async (raw) => {
// 사용자 구현
return {
date: raw.date,
cafeteria: raw.cafeteria,
status: "open",
breakfast: {},
lunch: {},
dinner: {},
};
},
},
});import { normalizeMenuDate, buildDateRange } from "@bluessu/meal-scraper";
normalizeMenuDate("2026-02-28"); // "2026-02-28"
normalizeMenuDate(new Date(2026, 1, 28)); // "2026-02-28"
buildDateRange("2026-02-28", "2026-03-02"); // ["2026-02-28","2026-03-01","2026-03-02"]지원 날짜 포맷은 내부적으로 모두 YYYY-MM-DD로 정규화됩니다.
getRawMenu(cafeteria, date): Promise<RawMenuData>getDailyMenu(cafeteria, date): Promise<DailyMenu>getRawMenus(cafeteria, dates, options?): Promise<RawMenuData[]>getDailyMenus(cafeteria, dates, options?): Promise<DailyMenu[]>getRawMenusByRange(cafeteria, start, end, options?): Promise<RawMenuData[]>getDailyMenusByRange(cafeteria, start, end, options?): Promise<DailyMenu[]>
RangeOptionsstartInclusive?: boolean(기본값:true)concurrency?: number(기본값:3)
import { HolidayException, MenuFetchException } from "@bluessu/meal-scraper";
try {
const menu = await client.getDailyMenu(CafeteriaType.DORMITORY, "2026-02-28");
} catch (error) {
if (error instanceof HolidayException) {
console.log("휴일입니다");
} else if (error instanceof MenuFetchException) {
console.log("수집 실패");
} else {
console.error(error);
}
}현재 공개 엔트리는 src/index.ts에 집중하고, 실제 구현은 내부 레이어로 분리되어 있습니다.
src/index.ts: 라이브러리 바렐(export hub)src/client/*: 클라이언트 API 및 유틸src/services/*: 수집/파싱 오케스트레이션src/repositories/*: 사이트별 스크래퍼src/parsers/*: 파싱 전략src/domain.ts,src/config.ts,src/errors.ts: 도메인/설정/예외
GNU General Public License Version 3 (GPL-3.0) 입니다.
라이선스 파일은 LICENSE를 확인하세요.