fix: clinic_registry CSV 임포트 + NaverPlace 검색 개선
- VerifiedChannels에 naverPlace 필드 추가 (registry URL → placeId 전달) - registryToVerifiedChannels: naver_place_url → placeId 추출하여 포함 - collect-channel-data NaverPlace 매칭 완화: exact match → contains match, 의원/병원 suffix 제거 shortName 사용, placeId 힌트로 검색 보강 - clinic_registry에 73개 병원 CSV 데이터 임포트 (올바른 YouTube/Blog/GangnamUnni/NaverPlace URL) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>main
parent
e81c4cfee9
commit
cd2463fb2d
|
|
@ -17,6 +17,7 @@ export interface VerifiedChannels {
|
|||
naverBlog: VerifiedChannel | null;
|
||||
gangnamUnni: VerifiedChannel | null;
|
||||
tiktok: VerifiedChannel | null;
|
||||
naverPlace?: { url: string; placeId?: string } | null; // registry-sourced place URL
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -560,23 +560,35 @@ Deno.serve(async (req) => {
|
|||
const npVerified = (verified as Record<string, unknown>).naverPlace as Record<string, unknown> | null;
|
||||
|
||||
channelTasks.push(wrapChannelTask("naverPlace", async () => {
|
||||
// ── Fast path: already verified in DB ──
|
||||
// ── Fast path 1: already fully verified in DB (has name) ──
|
||||
if (npVerified?.name) {
|
||||
console.log(`[naverPlace] Using verified DB data: ${npVerified.name}`);
|
||||
channelData.naverPlace = npVerified;
|
||||
return;
|
||||
}
|
||||
|
||||
// ── Slow path: first-time discovery via domain-matched search ──
|
||||
// ── Fast path 2: registry-sourced place URL → use Naver Place ID directly ──
|
||||
const registryPlaceUrl = (verified as Record<string, unknown>).naverPlace as { url?: string; placeId?: string } | null;
|
||||
const registryPlaceId = registryPlaceUrl?.placeId;
|
||||
if (registryPlaceId) {
|
||||
console.log(`[naverPlace] Using registry place ID: ${registryPlaceId}`);
|
||||
// Build the Naver local search with placeId as a hint — use clinic name to fetch details
|
||||
// We'll pass through to search but prime the query with clinic name
|
||||
}
|
||||
|
||||
// ── Slow path: search via Naver Local API ──
|
||||
const normalize = (s: string) => (s || '').replace(/<[^>]*>/g, '').toLowerCase();
|
||||
let clinicDomain = '';
|
||||
try { clinicDomain = new URL(row.url || '').hostname.replace('www.', ''); } catch { /* skip */ }
|
||||
|
||||
const districtMatch = address.match(/([가-힣]+(구|동))/);
|
||||
const district = districtMatch?.[1] || '';
|
||||
// Strip 의원/병원 suffixes for broader search match
|
||||
const shortName = clinicName.replace(/의원$|병원$/, '').trim();
|
||||
const queries = [
|
||||
...(district ? [`${clinicName} ${district}`, `${clinicName} 성형 ${district}`] : []),
|
||||
...(district ? [`${clinicName} ${district}`, `${shortName} ${district}`] : []),
|
||||
`${clinicName} 성형외과`,
|
||||
`${shortName} 성형외과`,
|
||||
`${clinicName} 성형`,
|
||||
];
|
||||
|
||||
|
|
@ -591,9 +603,10 @@ Deno.serve(async (req) => {
|
|||
const data = await res.json();
|
||||
const items = (data.items || []) as Record<string, string>[];
|
||||
|
||||
// Match by official domain first (most reliable), then exact name + 성형 category
|
||||
// Match priority: (1) domain match, (2) registry place ID in link, (3) name contains match + 성형 category
|
||||
const match = (clinicDomain ? items.find(i => (i.link || '').includes(clinicDomain)) : null)
|
||||
?? items.find(i => normalize(i.title) === clinicName.toLowerCase() && (i.category || '').includes('성형'))
|
||||
?? (registryPlaceId ? items.find(i => (i.link || '').includes(registryPlaceId)) : null)
|
||||
?? items.find(i => normalize(i.title).includes(shortName.toLowerCase()) && (i.category || '').includes('성형'))
|
||||
?? null;
|
||||
|
||||
if (match) {
|
||||
|
|
|
|||
|
|
@ -74,6 +74,11 @@ function registryToVerifiedChannels(reg: RegistryRow): import("../_shared/verify
|
|||
const blogHandle = extractHandleFromUrl(reg.naver_blog_url || '', 'naverBlog');
|
||||
const ttHandle = extractHandleFromUrl(reg.tiktok_url || '', 'tiktok');
|
||||
|
||||
// Extract Naver Place ID from URL (e.g. https://m.place.naver.com/hospital/11709005 → "11709005")
|
||||
const naverPlaceId = reg.naver_place_url
|
||||
? (reg.naver_place_url.match(/\/(\d+)\/?$/) || [])[1] || undefined
|
||||
: undefined;
|
||||
|
||||
return {
|
||||
instagram: igHandles,
|
||||
youtube: ytHandle ? { handle: ytHandle, verified: true, url: reg.youtube_url! } : null,
|
||||
|
|
@ -81,6 +86,7 @@ function registryToVerifiedChannels(reg: RegistryRow): import("../_shared/verify
|
|||
naverBlog: blogHandle ? { handle: blogHandle, verified: true, url: reg.naver_blog_url! } : null,
|
||||
gangnamUnni: reg.gangnam_unni_url ? { handle: reg.gangnam_unni_url, verified: true, url: reg.gangnam_unni_url } : null,
|
||||
tiktok: ttHandle ? { handle: ttHandle, verified: true, url: reg.tiktok_url! } : null,
|
||||
naverPlace: reg.naver_place_url ? { url: reg.naver_place_url, placeId: naverPlaceId } : null,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue