Skip to content

Commit 4434b1c

Browse files
committed
Merge remote-tracking branch 'origin/main' into deploy
2 parents 5e84ec6 + a464765 commit 4434b1c

File tree

10 files changed

+1178
-10
lines changed

10 files changed

+1178
-10
lines changed

CHANGELOG.json

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,33 @@
11
{
22
"metadata": {
3-
"lastUpdated": "2026-01-13T15:12:41Z",
4-
"currentVersion": "0.1.2",
3+
"lastUpdated": "2026-01-18T04:58:48Z",
4+
"currentVersion": "0.1.3",
55
"projectType": "python",
6-
"totalReleases": 3
6+
"totalReleases": 4
77
},
88
"releases": [
9+
{
10+
"version": "0.1.3",
11+
"project_type": "python",
12+
"date": "2026-01-18",
13+
"pr_number": 13,
14+
"raw_summary": "## Summary by CodeRabbit\n\n## 새 기능\n\n* Google 지도와 네이버 지도에서 장소 정보를 검색하고 수집하는 기능 추가\n* 새로운 API 엔드포인트를 통해 두 지도 서비스에서 장소명 검색 지원\n* 검색 결과로부터 주소, 평점, 영업 시간, 전화번호, 이미지 등의 상세 정보 추출",
15+
"parsed_changes": {
16+
"google_지도와_네이버_지도에서_장소_정보를_검색하고_수집하는_기능_추가": {
17+
"title": "Google 지도와 네이버 지도에서 장소 정보를 검색하고 수집하는 기능 추가",
18+
"items": []
19+
},
20+
"새로운_api_엔드포인트를_통해_두_지도_서비스에서_장소명_검색_지원": {
21+
"title": "새로운 API 엔드포인트를 통해 두 지도 서비스에서 장소명 검색 지원",
22+
"items": []
23+
},
24+
"검색_결과로부터_주소__평점__영업_시간__전화번호__이미지_등의_상세_정보_추출": {
25+
"title": "검색 결과로부터 주소, 평점, 영업 시간, 전화번호, 이미지 등의 상세 정보 추출",
26+
"items": []
27+
}
28+
},
29+
"parse_method": "markdown"
30+
},
931
{
1032
"version": "0.1.2",
1133
"project_type": "python",

CHANGELOG.md

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,19 @@
11
# Changelog
22

3-
**현재 버전:** 0.1.2
4-
**마지막 업데이트:** 2026-01-13T15:12:41Z
3+
**현재 버전:** 0.1.3
4+
**마지막 업데이트:** 2026-01-18T04:58:48Z
5+
6+
---
7+
8+
## [0.1.3] - 2026-01-18
9+
10+
**PR:** #13
11+
12+
**Google 지도와 네이버 지도에서 장소 정보를 검색하고 수집하는 기능 추가**
13+
14+
**새로운 API 엔드포인트를 통해 두 지도 서비스에서 장소명 검색 지원**
15+
16+
**검색 결과로부터 주소, 평점, 영업 시간, 전화번호, 이미지 등의 상세 정보 추출**
517

618
---
719

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# MapSee-AI
22

33
<!-- 수정하지마세요 자동으로 동기화 됩니다 -->
4-
## 최신 버전 : v0.1.1 (2026-01-11)
4+
## 최신 버전 : v0.1.2 (2026-01-13)
55

66
[전체 버전 기록 보기](CHANGELOG.md)
77

src/apis/test_router.py

Lines changed: 71 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,11 @@
33
"""
44
import logging
55
from fastapi import APIRouter
6-
from pydantic import BaseModel
6+
from pydantic import BaseModel, Field
77

88
from src.services.scraper.scrape_router import route_and_scrape
9+
from src.services.scraper.platforms.naver_map_scraper import NaverMapScraper
10+
from src.services.scraper.platforms.google_map_scraper import GoogleMapScraper
911

1012
logger = logging.getLogger(__name__)
1113
router = APIRouter(prefix="/api/test", tags=["테스트 API"])
@@ -15,6 +17,16 @@ class ScrapeRequest(BaseModel):
1517
url: str
1618

1719

20+
class NaverMapSearchRequest(BaseModel):
21+
"""네이버 지도 검색 요청"""
22+
query: str = Field(..., description="검색어 (예: 늘푸른목장)", min_length=1)
23+
24+
25+
class GoogleMapSearchRequest(BaseModel):
26+
"""구글 지도 검색 요청"""
27+
query: str = Field(..., description="검색어 (예: 늘푸른목장)", min_length=1)
28+
29+
1830
@router.post("/scrape", status_code=200)
1931
async def scrape_url(request: ScrapeRequest):
2032
"""
@@ -33,3 +45,61 @@ async def scrape_url(request: ScrapeRequest):
3345
async def health_check():
3446
"""스크래핑 테스트 API 상태 확인"""
3547
return {"status": "ok"}
48+
49+
50+
@router.post("/naver-map", status_code=200)
51+
async def scrape_naver_map(request: NaverMapSearchRequest):
52+
"""
53+
네이버 지도에서 장소 정보 스크래핑
54+
55+
장소명을 검색하여 첫 번째 검색 결과의 상세 정보를 추출합니다.
56+
57+
- POST /api/test/naver-map
58+
- Body: {"query": "늘푸른목장"}
59+
- 성공: 200 + NaverPlaceInfo
60+
- 실패: 4xx/5xx + 에러 메시지
61+
62+
추출 정보:
63+
- 장소명, 카테고리
64+
- 별점, 리뷰 수 (방문자/블로그)
65+
- 주소, 지하철 정보
66+
- 영업 상태, 영업 시간
67+
- 전화번호, 편의시설
68+
"""
69+
logger.info(f"네이버 지도 스크래핑 요청: query='{request.query}'")
70+
71+
scraper = NaverMapScraper()
72+
result = await scraper.search_and_scrape(request.query)
73+
74+
logger.info(f"스크래핑 완료: {result.name} ({result.place_id})")
75+
return result
76+
77+
78+
@router.post("/google-map", status_code=200)
79+
async def scrape_google_map(request: GoogleMapSearchRequest):
80+
"""
81+
구글 지도에서 장소 정보 스크래핑
82+
83+
장소명을 검색하여 첫 번째 검색 결과의 상세 정보를 추출합니다.
84+
85+
- POST /api/test/google-map
86+
- Body: {"query": "늘푸른목장"}
87+
- 성공: 200 + GooglePlaceInfo
88+
- 실패: 4xx/5xx + 에러 메시지
89+
90+
추출 정보:
91+
- 장소명, 카테고리
92+
- 별점, 리뷰 수
93+
- 가격대, 주소
94+
- 영업 상태, 요일별 영업 시간
95+
- 전화번호, Plus Code
96+
- 위도/경도, 웹사이트 URL
97+
- 대표 이미지 URL
98+
"""
99+
logger.info(f"구글 지도 스크래핑 요청: query='{request.query}'")
100+
101+
scraper = GoogleMapScraper()
102+
result = await scraper.search_and_scrape(request.query)
103+
104+
logger.info(f"스크래핑 완료: {result.name} ({result.place_id})")
105+
return result

src/models/google_place_info.py

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
"""src.models.google_place_info
2+
구글 지도 장소 정보 스키마
3+
"""
4+
from pydantic import BaseModel, Field
5+
6+
7+
class GooglePlaceInfo(BaseModel):
8+
"""
9+
구글 지도 장소 상세 정보
10+
11+
구글 지도 검색 결과에서 추출한 장소 정보를 담는 스키마입니다.
12+
"""
13+
# 기본 정보
14+
place_id: str = Field(..., description="구글 Place ID (URL에서 추출)")
15+
name: str = Field(..., description="장소명")
16+
category: str | None = Field(default=None, description="카테고리 (예: 숯불구이/바베큐전문점)")
17+
18+
# URL 정보
19+
google_map_url: str | None = Field(default=None, description="구글 지도 상세 페이지 URL")
20+
21+
# 위치 정보
22+
latitude: float | None = Field(default=None, description="위도")
23+
longitude: float | None = Field(default=None, description="경도")
24+
address: str | None = Field(default=None, description="주소")
25+
plus_code: str | None = Field(default=None, description="Plus Code (예: G35M+R3 서울특별시)")
26+
27+
# 평점/리뷰
28+
rating: float | None = Field(default=None, description="별점 (0.0 ~ 5.0)")
29+
review_count: int | None = Field(default=None, description="리뷰 수")
30+
price_level: str | None = Field(default=None, description="가격대 (예: ₩₩₩)")
31+
32+
# 영업 정보
33+
business_status: str | None = Field(default=None, description="영업 상태 (예: 영업 중)")
34+
business_hours: dict[str, str] | None = Field(default=None, description="요일별 영업 시간")
35+
36+
# 연락처/링크
37+
phone_number: str | None = Field(default=None, description="전화번호")
38+
website_url: str | None = Field(default=None, description="웹사이트 URL")
39+
40+
# 부가 정보
41+
description: str | None = Field(default=None, description="장소 설명/소개")
42+
amenities: list[str] = Field(default_factory=list, description="편의시설/서비스 옵션")
43+
popular_times: str | None = Field(default=None, description="인기 시간대 정보")
44+
45+
# 이미지
46+
image_url: str | None = Field(default=None, description="대표 이미지 URL")
47+
image_urls: list[str] = Field(default_factory=list, description="이미지 URL 목록 (최대 10개)")
48+
49+
class Config:
50+
json_schema_extra = {
51+
"example": {
52+
"place_id": "0x357ca44d6e36590b:0xc0019dfb09b9a4e2",
53+
"name": "늘푸른목장 잠실본점",
54+
"category": "숯불구이/바베큐전문점",
55+
"google_map_url": "https://www.google.com/maps/place/...",
56+
"latitude": 37.509573,
57+
"longitude": 127.0826454,
58+
"address": "서울특별시 송파구 백제고분로9길 34",
59+
"plus_code": "G35M+R3 서울특별시",
60+
"rating": 4.2,
61+
"review_count": 753,
62+
"price_level": "₩₩₩",
63+
"business_status": "영업 중",
64+
"business_hours": {
65+
"일요일": "24시간 영업",
66+
"월요일": "PM 12:00~AM 12:00",
67+
"화요일": "PM 12:00~AM 12:00",
68+
"수요일": "PM 12:00~AM 12:00",
69+
"목요일": "PM 12:00~AM 12:00",
70+
"금요일": "PM 12:00~AM 12:00",
71+
"토요일": "PM 12:00~AM 12:00"
72+
},
73+
"phone_number": "02-3431-4520",
74+
"website_url": "https://example.com",
75+
"description": "된장찌개와 냉면으로 완성하는 한상차림",
76+
"amenities": ["매장 내 식사", "테이크아웃", "배달"],
77+
"popular_times": "오후 7시~9시 가장 붐빔",
78+
"image_url": "https://lh5.googleusercontent.com/...",
79+
"image_urls": ["https://...", "https://..."]
80+
}
81+
}

src/models/naver_place_info.py

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
"""src.models.naver_place_info
2+
네이버 지도 장소 정보 스키마
3+
"""
4+
from pydantic import BaseModel, Field
5+
6+
7+
class NaverPlaceInfo(BaseModel):
8+
"""
9+
네이버 지도 장소 상세 정보
10+
11+
네이버 지도 검색 결과에서 추출한 장소 정보를 담는 스키마입니다.
12+
"""
13+
# 기본 정보
14+
place_id: str = Field(..., description="네이버 Place ID")
15+
name: str = Field(..., description="장소명")
16+
category: str | None = Field(default=None, description="카테고리 (예: 소고기구이)")
17+
18+
# URL 정보 (라우팅용)
19+
naver_map_url: str | None = Field(default=None, description="네이버 지도 상세 페이지 URL")
20+
21+
# 위치 정보
22+
latitude: float | None = Field(default=None, description="위도")
23+
longitude: float | None = Field(default=None, description="경도")
24+
address: str | None = Field(default=None, description="주소")
25+
road_address: str | None = Field(default=None, description="도로명 주소")
26+
subway_info: str | None = Field(default=None, description="지하철 정보 (예: 잠실새내역 4번 출구에서 412m)")
27+
directions_text: str | None = Field(default=None, description="찾아가는 길 설명")
28+
29+
# 평점/리뷰
30+
rating: float | None = Field(default=None, description="별점 (0.0 ~ 5.0)")
31+
visitor_review_count: int | None = Field(default=None, description="방문자 리뷰 수")
32+
blog_review_count: int | None = Field(default=None, description="블로그 리뷰 수")
33+
34+
# 영업 정보
35+
business_status: str | None = Field(default=None, description="영업 상태 (예: 영업 중)")
36+
business_hours: str | None = Field(default=None, description="영업 시간 요약")
37+
open_hours_detail: list[str] = Field(default_factory=list, description="요일별 상세 영업시간")
38+
holiday_info: str | None = Field(default=None, description="휴무일 정보")
39+
40+
# 연락처/링크
41+
phone_number: str | None = Field(default=None, description="전화번호")
42+
homepage_url: str | None = Field(default=None, description="홈페이지 URL")
43+
reservation_available: bool = Field(default=False, description="예약 가능 여부")
44+
45+
# 부가 정보
46+
description: str | None = Field(default=None, description="한줄 설명")
47+
amenities: list[str] = Field(default_factory=list, description="편의시설 목록")
48+
keywords: list[str] = Field(default_factory=list, description="키워드/태그")
49+
tv_appearances: list[str] = Field(default_factory=list, description="TV 방송 출연 정보")
50+
menu_info: list[str] = Field(default_factory=list, description="대표 메뉴")
51+
52+
# 이미지
53+
image_url: str | None = Field(default=None, description="대표 이미지 URL")
54+
image_urls: list[str] = Field(default_factory=list, description="이미지 URL 목록 (최대 10개)")
55+
56+
class Config:
57+
json_schema_extra = {
58+
"example": {
59+
"place_id": "11679241",
60+
"name": "늘푸른목장 잠실본점",
61+
"category": "소고기구이",
62+
"naver_map_url": "https://map.naver.com/p/search/늘푸른목장/place/11679241",
63+
"latitude": 37.5112,
64+
"longitude": 127.0867,
65+
"address": "서울 송파구 백제고분로9길 34 1F",
66+
"road_address": "서울 송파구 백제고분로9길 34 1F",
67+
"subway_info": "잠실새내역 4번 출구에서 412m",
68+
"directions_text": "잠실새내역 4번 출구에서 맥도널드 골목 끼고...",
69+
"rating": 4.42,
70+
"visitor_review_count": 1510,
71+
"blog_review_count": 1173,
72+
"business_status": "영업 중",
73+
"business_hours": "24:00에 영업 종료",
74+
"open_hours_detail": ["월 11:30 - 24:00", "화 11:30 - 24:00"],
75+
"holiday_info": "연중무휴",
76+
"phone_number": "02-3431-4520",
77+
"homepage_url": "http://example.com",
78+
"reservation_available": True,
79+
"description": "된장찌개와 냉면으로 완성하는 한상차림",
80+
"amenities": ["단체 이용 가능", "주차", "발렛파킹"],
81+
"keywords": ["소고기", "한우", "회식"],
82+
"tv_appearances": ["줄서는식당 14회 (24.05.13)"],
83+
"menu_info": ["경주갈비살", "한우된장밥"],
84+
"image_url": "https://...",
85+
"image_urls": ["https://...", "https://..."]
86+
}
87+
}

0 commit comments

Comments
 (0)