# Task: 네이버플레이스 감지 수정 (se-placesMap)

## 긴급도: critical
네이버 플레이스 모듈이 감지 안 되는 버그 수정.

---

## 1. 문제

SmartEditor의 플레이스 모듈은 `place.naver.com` URL이 아닌 **임베드 위젯**으로 삽입됨.
- CSS 클래스: `.se-placesMap`, `.se-section-placesMap`
- `data-linkdata`에 `placeId`, `name`, `address`, `tel` 포함
- 링크는 `href="#"` → URL 매칭 불가

**실제 사례** (blog.naver.com/contend14313/224188352496):
```html
<div class="se-component se-placesMap">
  <div data-linkdata='{"eventTarget":"placeDesc","placeId":"1183901452","name":"포레메디한방병원","address":"서울특별시 송파구 오금로 129","tel":"02-1899-8580"}'>
```

---

## 2. 수정

### 파일: `/home/jay/projects/InfoKeyword/worker/crawler/blog_content.py`

`_detect_naver_special_links()` 함수 (라인 203~239):

**수정할 부분 (라인 216-218)**:
```python
# 기존
if soup.select_one(".se-module-map, .se-map, .se_map"):
    has_place = True

# 수정: se-placesMap, se-section-placesMap 추가
if soup.select_one(".se-module-map, .se-map, .se_map, .se-placesMap, .se-section-placesMap"):
    has_place = True
```

**추가: data-linkdata에서 placeId 감지 (라인 220-231 부근에 추가)**:
```python
# 5. data-linkdata에서 placeId 감지 (SmartEditor 플레이스 위젯)
for tag in soup.find_all(attrs={"data-linkdata": True}):
    raw = tag.get("data-linkdata", "")
    try:
        link_data = json.loads(raw)
        # placeId가 있으면 네이버 플레이스 임베드
        if link_data.get("placeId"):
            has_place = True
        # eventTarget이 placeDesc인 경우
        if link_data.get("eventTarget") == "placeDesc":
            has_place = True
        # 기존 URL 기반 감지도 유지
        link_url = link_data.get("link", "").lower()
        if "place.naver.com" in link_url or "map.naver.com" in link_url:
            has_place = True
        if "talk.naver.com" in link_url or "talkpf.naver.com" in link_url:
            has_talktalk = True
    except (json.JSONDecodeError, TypeError):
        pass
```

주의: 기존 data-linkdata 루프(라인 220-231)를 위 코드로 교체. `placeId`와 `eventTarget` 감지를 추가하면서 기존 URL 감지도 유지.

---

## 3. 검증

```bash
cd /home/jay/projects/InfoKeyword
source /home/jay/workspace/.env.keys
unset CLAUDECODE
python3 -c "
import asyncio
from worker.crawler.blog_content import get_blog_content

async def test():
    # 플레이스가 있는 블로그 (포레메디 한방병원)
    content = await get_blog_content('https://blog.naver.com/contend14313/224188352496')
    print(f'has_place: {content[\"has_place\"]}')  # True여야 함
    print(f'has_talktalk: {content[\"has_talktalk\"]}')

    # 플레이스가 없는 일반 블로그
    content2 = await get_blog_content('https://blog.naver.com/hyo761/224028943165')
    print(f'has_place: {content2[\"has_place\"]}')  # False여야 함

asyncio.run(test())
"
```

예상:
- contend14313: `has_place=True` ✅
- hyo761: `has_place=False` ✅

---

## 4. Worker 재시작

```bash
cd /home/jay/projects/InfoKeyword
fuser 8100/tcp 2>/dev/null | xargs -r kill
sleep 1
source /home/jay/workspace/.env.keys
unset CLAUDECODE
nohup python3 -m uvicorn worker.main:app --host 0.0.0.0 --port 8100 > /tmp/infokeyword-worker.log 2>&1 &
sleep 2
curl -s http://localhost:8100/health
```

---

## 수정 대상 파일
1. `worker/crawler/blog_content.py` — `_detect_naver_special_links()` 플레이스 셀렉터 + placeId 감지
