
    j9!                       d Z ddlmZ ddlZddlZddlZddlmZmZ ddl	m
Z
 ddlmZmZmZmZmZmZ ddlZddlmZ  e
e      j-                         j.                  Zedz  Zed	z  Zd
diZ ed       G d d             ZddZddZddZd dZ d!dZ!d"dZ"d"dZ#d"dZ$	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 d#dZ%d$dZ&d%dZ'd&dZ(d'dZ)e*dk(  r e)        yy)(a,  Collect current domestic chain listings from known Korean supplier sites.

The output is evidence data. Matching is intentionally conservative: only product
titles containing a candidate name/alias are linked automatically. Internal TN
sources are not handled here and never count as public sellers.
    )annotationsN)	dataclassasdict)Path)parse_qsquote	urlencodeurljoinurlsplit
urlunsplit)BeautifulSoupzcandidates-v0.jsonzdomestic-public-listings.jsonz
User-Agentz8Mozilla/5.0 (compatible; TN-Silver-catalog-research/1.0)T)frozenc                  6    e Zd ZU ded<   ded<   ded<   ded<   y)ProductstrsellertitleurlsourceN)__name__
__module____qualname____annotations__     >.runtime/chain-catalog-data/research_domestic_chain_catalog.pyr   r      s    KJ	HKr   r   c                `    dj                  | j                  dd      j                               S )N u   상품명 : )joinreplacesplit)texts    r   cleanr$   $   s%    88DLL399;<<r   c                    t        |       j                         }|j                  dd      j                  dd      }t        j                  dd|      S )Nu   커팅u   컷팅u   비형u   b형u   [^0-9a-z가-힣]+r   )r$   lowerr!   resub)r#   values     r   
normalizedr*   (   sE    $KEMM(H-55hGE66&E22r   c                
   t        |       }t        |j                        }g }dD ]&  }||v s||   s|j                  |||   d   f       ( t	        |j
                  |j                  |j                  t        |      df      S )N)it_idgoodsNo
product_nobranduidr   r   )	r   r   queryappendr   schemenetlocpathr	   )r   partsr0   keptkeys        r   	clean_urlr8   .   s|    SMEU[[!ED= .%<E#JKKeCjm,-. u||U\\5::yPRSTTr   c                    | j                  |d      }|j                          t        j                  d       t	        |j
                  d      S )N   )timeoutgQ?zhtml.parser)getraise_for_statustimesleepr   content)sessionr   responses      r   r<   r<   8   s?    {{3{+HJJt))=99r   c                   |j                   r|j                  sy |j                  t        |j                        f}t	        |j                  t        |j                         t        |j                        |j                        | |<   y N)r   r   r   r8   r   r$   r   )productsproductr7   s      r   add_productrG   ?   sZ    ==>>9W[[1
2CGNNE'--,@)GKKBXZaZhZhiHSMr   c                   dD ]  }t        | |      }|j                  d      D ]`  }|j                  d      }|j                  d      }|s(|s+t        |t	        d|j                  dd      t        ||d	         |             b  y )
N)z&https://kjfmall.com/shop/list-10204010z+https://kjfmall.com/shop/list-102040?page=2z	li.sct_liz.sct_txt__titleza[href*="it_id="]u   KJF한국주얼리부속r   Tstriphref)r<   select
select_onerG   r   get_textr
   )rA   rE   r   soupitem
title_nodelinks          r   collect_kjfrS   F   s     	R 7C KK, 	RD):;J??#67DdHg.H*J]J]^aimJ]Jnpwx{  ~B  CI  ~J  qK  MP  'Q  R		R	Rr   c                t   t        dd      D ]  }d| dt        d       }t        | |      }d}|j                  d      D ]p  }|j	                  dd	
      }|sd|d   v s!|d   j                  d      r6|dz  }t        |t        d|j                  dd	      t        ||d         |             r |r y  y )N      z8https://www.e-deasung.co.kr/goods/goods_search.php?page=z	&keyword=u   체인r   
.item_nameaTrK   goodsNo=rK   u   대성재료상사r   rI   )
ranger   r<   rL   find_parentendswithrG   r   rN   r
   rA   rE   pager   rO   foundrQ   rR   s           r   collect_daesungra   S   s    a 
HiX]^fXgWhi7C ++l3 	LJ))#D)9D
d6l24<;P;PQ[;\
Hg.BJDWDWX[cgDWDhjqruw{  }C  xD  kE  GJ  'K  L		L
 
r   c                ^   t        dd      D ]  }d| d}t        | |      }d}|j                  d      D ]p  }|j                  dd	      }|sd
|d   v s!|d   j	                  d
      r6|dz  }t        |t        d|j                  dd      t        ||d         |             r |r y  y )NrU      z3https://www.gmtool.co.kr/goods/goods_list.php?page=z&cateCd=020001003r   rW   rX   TrY   rZ   rK   u   금속공예공구(GMTOOL)r   rI   )	r[   r<   rL   r\   r]   rG   r   rN   r
   r^   s           r   collect_gmtoolrd   a   s    a 
CD6IZ[7C ++l3 	TJ))#D)9D
d6l24<;P;PQ[;\
Hg.JJL_L_`ckoL_Lpryz}  @D  EK  @L  sM  OR  'S  T		T
 
r   c                   t        d|dz         D ]  }d|v rdnd}	| |	 d| }
t        | |
      }d}|j                  |      D ]x  }|j                  |      }|j                  d      }t	        d |D        d       }|s;|s>|dz  }t        |t        ||j                  dd	
      t        ||d         |
             z |r y  y )NrU   ?&zpage=r   za[href*="/product/"]c              3  J   K   | ]  }d |j                  dd      vs|  yw)z
/list.htmlrK   r   N)r<   ).0rX   s     r   	<genexpr>z*collect_cafe24_category.<locals>.<genexpr>   s"     Sq\vrAR-RSs   ##r   TrI   rK   )	r[   r<   rL   rM   nextrG   r   rN   r
   )rA   rE   r   base_urlcategory_urlitem_selectortitle_selector	max_pagesr_   r    r   rO   r`   rP   rQ   linksrR   s                    r   collect_cafe24_categoryrr   o   s     aQ' \)sstfE$07C KK. 	CD8JKK 67ESESUYZDd
Hgfj6I6I#UY6I6Z\cdlnrsynz\{  ~A  'B  C	C r   c           
         i }t        | |       t        | |       t        | |       t        | |dddddd       t        | |dddddd       t        | |d	d
dddd       t	        |j                         d       S )Nu   신안제작소zhttps://sinan-house.comz7https://sinan-house.com/category/%EC%B2%B4%EC%9D%B8/82/zli.xans-record-z.name   z8https://sinan-house.com/category/%EC%8B%A4%EB%B2%84/188/   Jewcozhttps://kr.jewco.krz4https://kr.jewco.kr/category/%EC%B2%B4%EC%9D%B8/140/zli.df-prl-itemz.df-prl-namec                H    | j                   | j                  | j                  fS rD   )r   r   r   )ps    r   <lambda>z(collect_known_catalogs.<locals>.<lambda>   s    AHHaggquu3M r   )r7   )rS   ra   rd   rr   sortedvalues)rA   rE   s     r   collect_known_catalogsr|      s    /1H"GX&7H%GX/@B[  ^W  Yj  ls  uv  wGX/@B[  ^X  Zk  mt  vw  xGXw8M  PF  HX  Zh  jk  l(//#)MNNr   c           	     :   | d   g| j                  dg       }ddgddgddgd	d
gdgddgddgdgd}|j                  |j                  | d   g              | d   dk(  r|D cg c]
  }|dk7  s	| }}t        t        j	                  d |D                    S c c}w )Nnamealiasesu
   각B체인u   각B형체인u   B형 고방체인u   비형 고방체인u   B형 고방 다이스체인u   비형 고방 다이스체인u   B형 커브체인u   비형 커브체인u   A형 모줄체인u   모줄 B형 컷팅체인u   모줄 비형 컷팅체인u   팔각뱀줄컷팅체인u   팔각뱀줄커팅체인u   팔각줄체인)u   B형각줄체인u   B형고방체인u   B형고방다이스체인u   B형커브체인u   A형모줄체인u   모줄B형컷팅체인u   스네이크팔각컷팅체인u   팔각체인   각줄체인u	   각체인c              3  P   K   | ]  }t        t        |            d k\  s|   yw)   N)lenr*   )ri   terms     r   rj   zterms_for.<locals>.<genexpr>   s"     StJt<L8MQR8RdSs   &&)r<   extendlistdictfromkeys)rP   termsextrasr   s       r   	terms_forr      s    &\4DHHY34E)?;02GH&CEd%e02GH01#=?["\+EGa*b*+	F 
LLDL"-.F|~%"'?$4;+>??SuSSTT @s   "
B-Bc                   t        |       D cg c]  }t        |       }}g }|D ][  }t        |j                        | d   dk(  r	dv sdv r)| d   dk(  rdv r6t        fd|D              sK|j	                  |       ] |S c c}w )Nr~   r   u	   팔각줄u	   직사각u   사각 링크체인c              3  &   K   | ]  }|v  
 y wrD   r   )ri   r   r   s     r   rj   z!match_products.<locals>.<genexpr>   s     /tu}/s   )r   r*   r   anyr1   )rP   rE   r   r   matchesrF   r   s         @r   match_productsr      s    *3D/:$Z:E:G $7==)<>){e/C{V[G[<00[E5I///NN7#$ N ;s   Bc                 v  
 t        j                  t        j                  d            } | d   D cg c]  }|d   D ]  }|  }}}t	        j
                         5 }|j                  j                  t               t        |      }d d d        g }|D ]W  }t        |      }|j                  |d   |j                  dg       t        |      |D cg c]  }t        |       c}d       Y t        j!                  t        j"                  dd	t%              t'        |D 	ch c]  }	|	j(                   c}	      D 

ci c]  

t+        
fd
|D               c}
|ddd      d       t-        dt         dt%        |       dt%        |       d       y c c}}w # 1 sw Y   xY wc c}w c c}	w c c}
w )Nzutf-8)encodingcandidate_groupsitemsr~   r   )r~   r   searched_termspublic_listingsz
2026-08-21zRKnown domestic supplier category crawl plus conservative exact-name/alias matchingc              3  B   K   | ]  }|j                   k(  sd   yw)rU   N)r   )ri   rF   r   s     r   rj   zmain.<locals>.<genexpr>   s     %\G7>>U[C[a%\s   )
checked_onmethodcatalog_product_countseller_countsrowsF   )ensure_asciiindentzwrote z (z catalog products, z candidates))jsonloadsINPUT	read_textrequestsSessionheadersupdateHEADERSr|   r   r1   r<   r   r   OUTPUT
write_textdumpsr   rz   r   sumprint)datagrouprP   r   rA   rE   r   r   matchrx   r   s             `r   mainr      s   ::eoowo78D#$67SeE'NSDTSTSES				 3ww')'23 D  x0Lxx	2.'o;BC%uC	
 	 djj"f!$Xkq  FN  sO  ABsts{s{  sO  lP  Qag&#%\x%\"\\  Q" !% 07  8 
F6("S]O+>s4yk
VW) T3 3  D sO  Qs#   F+FF,!F1>F6F)__main__)r#   r   returnr   )r   r   r   r   )rA   requests.Sessionr   r   r   r   )rE   dict[tuple[str, str], Product]rF   r   r   None)rA   r   rE   r   r   r   )rA   r   rE   r   r   r   rl   r   rm   r   rn   r   ro   r   rp   intr   r   )rA   r   r   list[Product])rP   r   r   z	list[str])rP   r   rE   r   r   r   )r   r   )+__doc__
__future__r   r   r'   r>   dataclassesr   r   pathlibr   urllib.parser   r   r	   r
   r   r   r   bs4r   __file__resolveparentROOTr   r   r   r   r$   r*   r8   r<   rG   rS   ra   rd   rr   r|   r   r   r   r   r   r   r   <module>r      s4   #  	  )  R R   H~&&##	/	/S
T $  =3U:j
R,  	
     
4OU$X2 zF r   