μλ§μκΈκ³ (KFCC) μΉμ¬μ΄νΈμμ κΈλ¦¬ μ 보μ κ²½μμ€ννκ° λ°μ΄ν°λ₯Ό μλμΌλ‘ μμ§νμ¬ JSON APIλ‘ μ 곡νλ Python ν¬λ‘€λ¬μ λλ€.
git clone https://github.com/hosoodev/kfcc-Rates-Api.git
cd kfcc-Rates-Api/backend
pip install -r requirements.txt
# κΈ°λ³Έ ν¬λ‘€λ§ (μ μ£Όλλ§)
python src/main.py
# μ 체 μ§μ ν¬λ‘€λ§ (config.pyμμ μ£Όμ ν΄μ )
python src/main.py
# 30μΌ μ΄μ λ λ°μ΄ν° μ 리νλ©° ν¬λ‘€λ§
python src/main.py --cleanup 30
# ν΅κ³ μ λ³΄λ§ μΆλ ₯
python src/main.py --stats
# κ²½μμ€ννκ° μμ§ (1μ, 7μμλ§)
python src/main.py --grades
backend/
βββ src/
β βββ main.py # λ©μΈ μ€ν νμΌ
β βββ config.py # μ€μ νμΌ
β βββ crawler.py # κΈλ¦¬ ν¬λ‘€λ¬
β βββ grade_crawler.py # κ²½μμ€ννκ° ν¬λ‘€λ¬
β βββ parser.py # HTML νμ
β βββ storage.py # λ°μ΄ν° μ μ₯ κ΄λ¦¬
βββ data/
β βββ banks.json # μν λͺ©λ‘
β βββ summary.json # μμ½ ν΅κ³
β βββ rates/ # μΌλ³ κΈλ¦¬ λ°μ΄ν°
β β βββ 2025-09-15.json
β β βββ ...
β βββ grades/ # κ²½μμ€ννκ° λ°μ΄ν°
β βββ grades_2025_06.json # 6μ νκ° (7μ 15μΌ μμ§)
β βββ grades_2025_12.json # 12μ νκ° (1μ 15μΌ μμ§)
βββ .github/workflows/
β βββ crawler.yml # λ©μΈ ν¬λ‘€λ§ μν¬νλ‘μ°
β βββ grade-crawler.yml # κ²½μμ€ννκ° μν¬νλ‘μ°
βββ scripts/
β βββ restore-july-schedule.py # 7μ μ€μΌμ€ 볡μ
β βββ restore-july-schedule.md # 볡μ κ°μ΄λ
βββ requirements.txt # Python μμ‘΄μ±
{
"metadata": {
"date": "2025-09-15",
"total_banks": 74,
"successful_banks": 74,
"crawled_at": "2025-09-15T21:33:04.455000",
"version": "1.1"
},
"summary": {
"total_banks": 74,
"total_products": 292,
"average_rate": 1.33,
"min_rate": 0.01,
"max_rate": 3.5,
"rate_range": {
"min": 0.01,
"max": 3.5
},
"duration_stats": {
"0": {
"count": 135,
"average_rate": 0.11,
"min_rate": 0.01,
"max_rate": 1.0
},
"12": {
"count": 116,
"average_rate": 2.5,
"min_rate": 1.6,
"max_rate": 3.1
}
},
"product_type_stats": {
"μꡬλΆμνκΈ": {
"count": 135,
"average_rate": 0.11,
"min_rate": 0.01,
"max_rate": 1.0
}
}
},
"rates": [
{
"bank": {
"gmgoCd": "6705",
"name": "λ²ν(λ³Έμ )",
"city": "μ μ£Ό",
"district": "μκ·ν¬μ",
"phone": "064-739-1234",
"address": "μ μ£Ό μκ·ν¬μ μ€μλ‘ 123"
},
"base_date": "2025-09-15",
"products": [
{
"product_name": "μ¨λΌμΈμ립μνκΈ",
"duration_months": 0,
"interest_rate": 0.1,
"duration_text": "",
"rate_text": "0.10%",
"product_type": "μꡬλΆμνκΈ"
}
],
"crawled_at": "2025-09-15T21:33:08.829000",
"total_products": 2
}
]
}
{
"collection_info": {
"collected_at": "2025-07-15T02:00:00.000000",
"total_banks": 41,
"evaluation_year": 2025,
"evaluation_month": 6
},
"grades": [
{
"gmgo_cd": "6705",
"bank_name": "λ²ν(λ³Έμ )",
"city": "μ μ£Ό",
"district": "μκ·ν¬μ",
"evaluation_agency": "λ²νμλ§μκΈκ³ ",
"evaluation_date": "20250630",
"grade_code": "2",
"grade_name": "μνΈ",
"grade_description": "κ²½μμνκ° μνΈν μν",
"collected_at": "2025-07-15T02:00:00.000000",
"evaluation_year": 2025,
"evaluation_month": 6
}
]
}
{
"collection_info": {
"collected_at": "2025-09-15T21:30:00.000000",
"total_banks": 3000,
"regions": 17,
"version": "1.1"
},
"banks": [
{
"gmgoCd": "6705",
"name": "λ²ν(λ³Έμ )",
"city": "μ μ£Ό",
"district": "μκ·ν¬μ",
"phone": "064-739-1234",
"address": "μ μ£Ό μκ·ν¬μ μ€μλ‘ 123",
"region": "μ μ£Ό"
}
]
}
{
"total_banks": 3000,
"total_products": 12000,
"average_rate": 2.15,
"min_rate": 0.01,
"max_rate": 4.5,
"rate_range": {
"min": 0.01,
"max": 4.5
},
"duration_stats": {
"0": {
"count": 5000,
"average_rate": 0.15,
"min_rate": 0.01,
"max_rate": 1.2
},
"12": {
"count": 4000,
"average_rate": 2.8,
"min_rate": 1.5,
"max_rate": 4.0
},
"24": {
"count": 3000,
"average_rate": 3.2,
"min_rate": 2.0,
"max_rate": 4.5
}
},
"product_type_stats": {
"μꡬλΆμνκΈ": {
"count": 5000,
"average_rate": 0.15,
"min_rate": 0.01,
"max_rate": 1.2
},
"κ±°μΉμμνκΈ": {
"count": 4000,
"average_rate": 2.8,
"min_rate": 1.5,
"max_rate": 4.0
},
"μ 립μμνκΈ": {
"count": 3000,
"average_rate": 2.5,
"min_rate": 1.0,
"max_rate": 3.8
}
},
"crawled_at": "2025-09-15T21:30:00.000000"
}
REGIONS = {
"μμΈ": ["λλ΄κ΅¬", "λ§ν¬κ΅¬", "κ΄μ
ꡬ", ...],
"μΈμ²": ["κ°νκ΅°", "μꡬ", "λꡬ", ...],
"κ²½κΈ°": ["κΉν¬μ", "νμ£Όμ", "μ°μ²κ΅°", ...],
# ... λͺ¨λ μ/λ
}
CRAWLER_CONFIG = {
'timeout': 10, # μμ² νμμμ (μ΄)
'max_workers_list': 5, # μν λͺ©λ‘ μμ§ μ컀 μ
'max_workers_rate': 10, # κΈλ¦¬ μμ§ μ컀 μ
'retry_count': 3, # μ¬μλ νμ
'retry_delay': 1 # μ¬μλ κ°κ²© (μ΄)
}
GRADE_CONFIG = {
'enabled': True, # μμ§ νμ±ν
'collection_month': [1, 7], # μμ§ μ (1μ 15μΌ, 7μ 15μΌ)
'evaluation_year': 2025, # νκ° μ°λ (λΉν΄λ
λ μλ)
'evaluation_month': [6, 12], # νκ° κΈ°μ€ μ (6μ, 12μ)
'retry_count': 3,
'retry_delay': 1,
'timeout': 10
}
python src/main.py [μ΅μ
]
μ΅μ
:
--cleanup DAYS μ§μ λ μΌμ μ΄μ λ λ°μ΄ν° μ 리
--stats μ μ₯μ ν΅κ³ μ λ³΄λ§ μΆλ ₯
--grades κ²½μμ€ννκ° λ°μ΄ν° μμ§ (1μ, 7μμλ§)
--help λμλ§ μΆλ ₯
--version λ²μ μ 보 μΆλ ₯
# κ²½μμ€ννκ° κ°μ μ€ν (μ μ ν 무μ)
export FORCE_GRADE_COLLECTION=true
python src/main.py --grades
python src/main.py μ€νrequests>=2.31.0
beautifulsoup4>=4.12.0
python-dotenv>=1.0.0
# κ°μνκ²½ μμ±
python -m venv venv
# κ°μνκ²½ νμ±ν (Windows)
venv\Scripts\activate
# κ°μνκ²½ νμ±ν (Linux/Mac)
source venv/bin/activate
# μμ‘΄μ± μ€μΉ
pip install -r requirements.txt
# κΈ°λ³Έ ν¬λ‘€λ§ ν
μ€νΈ
python src/main.py --stats
# κ²½μμ€ννκ° ν
μ€νΈ (νκ²½λ³μ μ€μ )
export FORCE_GRADE_COLLECTION=true
python src/main.py --grades
MIT License
git checkout -b feature/AmazingFeature)git commit -m 'Add some AmazingFeature')git push origin feature/AmazingFeature)β μ΄ νλ‘μ νΈκ° λμμ΄ λμλ€λ©΄ Starλ₯Ό λλ¬μ£ΌμΈμ!