Ë
    m }jÓ   ã                   ó,  — d Z ddlZddlZddlZddlZddlmZ ddlmZ ddl	m	Z	m
Z
 ej                  j                  dej                  j                  dd«      «      Zd	Zd
Zeez   ZdZdZdZddiZd„ Zd„ Zd„ Zd„ Zd„ Zd„ Zd„ Zd„ Zedk(  r e«        yy)u&  
crawl_lbx.py â€” é›·æ³¢åŽ¿äººæ°‘æ”¿åºœÂ·çŽ¯è¯„å…¬å‘Š
========================================
TRS CMSï¼ŒcreatePageHTML(N) åˆ†é¡µï¼Œ0-indexed
é¦–é¡µ index.html é�™æ€�å†…å�«æ–‡ç« åˆ—è¡¨

åˆ—è¡¨ï¼š<li><a href="./YYYYMM/tYYYYMMDD_id.html" title="TITLE">TITLE</a></li>
       æ—¥æœŸä»Ž URL è·¯å¾„æ��å�–
è¯¦æƒ…ï¼š<td id="xilan_cont"> â†’ <div class="TRS_UEDITOR"> æ­£æ–‡
       <meta name="PubDate" content="YYYY-MM-DD HH:MM" /> æ—¥æœŸ

ç”¨æ³•:
    python3 crawl_lbx.py             # å…¨é‡�
    python3 crawl_lbx.py 1           # å¢žé‡�ï¼ˆå�ªçˆ¬é¦–é¡µï¼‰
é    N)ÚBeautifulSoup)Úurljoin)ÚdatetimeÚ	timedeltaÚ	SEARCH_DBÚGOV_DB_PATHz/root/search.dbzhttp://www.lbx.gov.cnz/xxgk/zdxxgk/hjbh/hpgg/u   é›·æ³¢åŽ¿äººæ°‘æ”¿åºœu   é›·æ³¢åŽ¿çŽ¯è¯„å…¬å‘Šé   z
User-AgentzoMozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36c                 ó    — t        d| › �«       y )Nz[lbx] )Úprint)Úmsgs    ú/root/gov_crawler/crawl_lbx.pyÚlogr   -   s   € Ü	ˆF�3�%ˆ.Õó    c                 ó¢   — t        j                  d| «      }|r7|j                  d«      › d|j                  d«      › d|j                  d«      › �S y)uI   Extract date from URL like ./202606/t20260612_2991748.html â†’ 2026-06-12z/t(\d{4})(\d{2})(\d{2})_é   ú-é   é   Ú )ÚreÚsearchÚgroup)ÚurlÚms     r   Úextract_date_from_urlr   0   sH   € ä
�	‰	Ð-¨sÓ3€AÙØ—'‘'˜!“*�˜Q˜qŸw™w q›z˜l¨!¨A¯G©G°A«J¨<Ð8Ð8Ør   c                 ó"   — | j                  «       S )zClean title if needed©Ústrip)Útitles    r   Úclean_titler    7   s   € à�;‰;‹=Ðr   c                 ó<   — | dk(  rt         S t        › t        › d| › d�S )u?   page_index: 0-based. 0 â†’ index.html, 1 â†’ index_1.html, etc.r   Úindex_z.html)ÚLIST_URLÚBASE_URLÚ	LIST_PATH)Ú
page_indexs    r   Úbuild_list_urlr'   ;   s%   € à�Q‚ÜˆÜˆZœ	�{ &¨¨°EÐ:Ð:r   c                 óÒ  — t        | «      }t        d| › d|› �«       	 t        j                  |t        d¬«      }d|_        |j                  }t        |d«      }g }|j                  d	t        j                  d
«      ¬«      D ]¥  }|j                  d«      }|r|j                  d«      sŒ(|d   j                  «       }	|	j                  d«      rd|	vrŒQ|j                  dd«      xs |j                  d¬«      }
t!        t"        |	«      }t%        |	«      }|j'                  ||
|f«       Œ§ t        dt)        |«      › d�«       |S # t        $ r}t        d|› �«       g cY d}~S d}~ww xY w)z9Fetch one list page, return [(url, title, date_str), ...]zFetching list page ú: é   ©ÚheadersÚtimeoutúutf-8z  ERROR fetching list page: Núhtml.parserÚlizWIDTH:\s*100%)ÚstyleÚaÚhrefz./z/tr   r   Tr   z  Found ú	 articles)r'   r   ÚrequestsÚgetÚHEADERSÚencodingÚtextÚ	Exceptionr   Úfind_allr   ÚcompileÚfindr   Ú
startswithÚget_textr   r#   r   ÚappendÚlen)r&   r   ÚrespÚhtmlÚeÚsoupÚitemsr0   r2   r3   r   Úfull_urlÚdate_strs                r   Úfetch_list_pagerI   A   sS  € ä
˜Ó
$€CÜÐ
˜j˜\¨¨C¨5Ð1Ô2ðÜ�|‰|˜C¬¸"Ô=ˆØˆŒØ�y‰yˆô
 ˜˜}Ó-€DØ€Eð �m‰m˜D¬¯
©
Ð3CÓ(DˆmÓEò 2ˆØ�G‰G�C‹LˆÙ˜Ÿ™˜fœØØ�‰y�‰Ó ˆà�‰˜tÔ$¨°DÑ(8Øà—‘�g˜rÓ"Ò< a§j¡j°t jÓ&<ˆÜœ8 TÓ*ˆÜ(¨Ó.ˆØ�‰�h  xÐ0Õ1ð2ô ˆ(”3�u“:�,˜iÐ(Ô)Ø€Løô/ ò ÜÐ*¨1¨#Ð.Ô/Ø�	ûðús   ž/E Å	E&ÅE!ÅE&Å!E&c                 óŠ  — 	 t        j                  | t        d¬«      }d|_        |j                  }t        |d«      }d	}|j                  d
d¬«      }|r?|j                  dt        j                  d«      ¬«      }|rt        |«      }nt        |«      }d	}|j                  dddi¬«      }	|	rM|	j                  d«      r<|	d   j                  «       }
t        j                  d|
«      }|r|j                  d«      }|st        | «      }|st        d| › �«       d|fS ||fS # t
        $ r}t        d| › d|› �«       Y d}~yd}~ww xY w)z/Return (content_html, date_str) or (None, None)r*   r+   r.   z  ERROR fetching r)   N)NNr/   r   ÚtdÚ
xilan_cont)ÚidÚdivÚTRS_UEDITOR)Úclass_ÚmetaÚnameÚPubDate)ÚattrsÚcontentz(\d{4}-\d{2}-\d{2})r   z  WARNING: no content for )r5   r6   r7   r8   r9   r:   r   r   r=   r   r<   Ústrr   Úmatchr   r   )r   rB   rC   rD   rE   Úcontent_htmlrK   ÚeditorrH   rQ   Úrawr   s               r   Úfetch_detailr[   b   sE  € ðÜ�|‰|˜C¬¸"Ô=ˆØˆŒØ�y‰yˆô ˜˜}Ó-€DØ€Là	�‰�4˜LˆÓ	)€BÙ	à—‘˜¤r§z¡z°.Ó'A�ÓBˆÙÜ˜v›;‰Lô ˜r›7ˆLð €HØ�9‰9�V F¨IÐ#6ˆ9Ó7€DÙ�—‘˜Ô#Ø�9‰o×#Ñ#Ó%ˆä�H‰HÐ+¨SÓ1ˆÙØ—w‘w˜q“zˆHñ Ü(¨Ó-ˆáÜÐ(¨¨Ð.Ô/Ø�Xˆ~Ðà˜Ð!Ð!øôI ò ÜÐ ˜u B q cÐ*Ô+Üûðús   ‚/D Ä	EÄ'D=Ä=Ec           
      óÔ  — ddl }| st        d«       yt        dt        › �«       |j                  t        «      }|j	                  «       }d}| D ]6  \  }}}}	 |j                  dt        |t        |«      ||t        f«       |dz  }Œ8 |j                  «        |j                  «        t        d	|› d
t        | «      › d�«       y# t        $ r}	t        d|› d|	› �«       Y d}	~	Œ”d}	~	ww xY w)zUpsert records into search.dbr   NzNo items to savezOpening DB: zœINSERT OR REPLACE INTO gov_raw
                   (site_name, page_url, title, publish_date, content, category)
                   VALUES (?, ?, ?, ?, ?, ?)r   z  DB error for r)   zSaved ú/z records to DB)Úsqlite3r   ÚDB_PATHÚconnectÚcursorÚexecuteÚ	SITE_NAMEr    ÚSOURCEr:   ÚcommitÚcloserA   )
rF   r^   ÚconnÚcÚinsertedr   r   rH   rX   rD   s
             r   Ú
save_to_dbrj   Ž   sñ   € ãáÜÐÔØäˆ,”w�iÐ Ô!Ø�?‰?œ7Ó#€DØ�‰‹€Aà€HØ.3ò .Ñ*ˆˆU�H˜lð	.Ø�I‰Ið0ô ØÜ Ó&ØØ Üðô	ð ˜‰M‰Hð.ð& 	‡K�K„MØ‡J�J„LÜˆ&��
˜!œC ›J˜< ~Ð6Õ7øô ò 	.Ü�/ #  b¨¨Ð,×-Ñ-ûð	.ús   Á.CÃ	C'ÃC"Ã"C'c                  óð  ‡— t        t        j                  «      dkD  xr t        j                  d   dk(  } t        j                  «       t        d¬«      z
  j                  d«      Št        d‰› �«       g }t        t        «      D ]É  }t        |«      }|st        d|› �«        n¬|D ���cg c]  \  }}}|sŒ
|‰k\  sŒ|||f‘Œ }}}}|j                  |«       | rt        d«        ni|sŒf|d	   d
   t        j                  «       t        d¬«      z
  j                  d«      k  sŒ t        ˆfd„|D «       «      }|dk(  sŒºt        d|› d�«        n t        dt        |«      › �«       g }	t        |d«      D ]z  \  }
\  }}}t        d|
› dt        |«      › d|d d › d�«       t        |«      \  }}|xs |}|r|	j                  ||||f«       ŒWt        d|› d�«       |	j                  |||df«       Œ| t!        |	«       t        dd› �«       t        dt        |	«      › d�«       |	r9t#        |	D �cg c]  }|d
   sŒ	|d
   ‘Œ c}«      }t        d|d   › d|d	   › �«       	 dd l}|j'                  t(        «      }|j+                  dt,        f«       |j/                  «        |j1                  «        t        d «       t        d› «       y c c}}}w c c}w # t2        $ r}t        d!|› �«       Y d }~Œ5d }~ww xY w)"Nr   Ú1iG  )Údaysz%Y-%m-%dz3-year cutoff: z%  No more articles, stopping at page zIncremental mode: page 0 onlyéÿÿÿÿr   iÚ  c              3   ó<   •K  — | ]  \  }}}|sŒ
|‰k\  sŒd –— Œ y­w)r   N© )Ú.0Ú_ÚdÚthree_years_agos      €r   ú	<genexpr>zmain.<locals>.<genexpr>Ë   s    øè ø€ Ò!Z©¨¨1¨aºqÀQÈ/ÓEY¤!Ñ!Zùs   ƒ�•r   z  Page z&: all articles before cutoff, stoppingz$Total articles after 3-year filter: ú[r]   z] é2   z...z  WARNING: saving z without contentr   ú
z2==================================================zDone. Total: r4   zDate range: z ~ a  
            INSERT OR REPLACE INTO gov_search(rowid, title, site_name, summary)
            SELECT rowid, title, site_name, 
                   CASE WHEN length(content) > 200 THEN substr(content, 1, 200) ELSE content END
            FROM gov_raw WHERE category = ?
        z!FTS index rebuilt for new entrieszFTS rebuild note: )rA   ÚsysÚargvr   Únowr   Ústrftimer   ÚrangeÚPAGESrI   ÚextendÚsumÚ	enumerater[   r@   rj   Úsortedr^   r`   r_   rb   rd   re   rf   r:   )ÚincrementalÚall_articlesÚpiÚarticlesÚuÚtrs   ÚfilteredÚremaining_youngÚresultsÚir   r   rH   rX   Údetail_dateÚ
final_dateÚrÚdatesr^   rg   rD   rt   s                         @r   Úmainr‘   ²   sô  ø€ Ü”c—h‘h“- !Ñ#Ò:¬¯©°©°sÑ(:€KÜ—|‘|“~¬	°wÔ(?Ñ?×IÑIÈ*ÓU€OÜˆ/˜/Ð*Ð+Ô,ð €LÜ”E‹lò ˆÜ" 2Ó&ˆÙÜÐ7¸°tÐ<Ô=Ùð .6×TÐT¡' ! Q¨º¸qÀOÓ?S�Q˜˜1’IÐTˆÒTØ×Ñ˜HÔ%ñ ÜÐ/Ô0Ùò ˜ ™ Q™¬8¯<©<«>¼IÈ7Ô<SÑ+S×*]Ñ*]Ð^hÓ*iÓiä!Ó!Z°8Ô!ZÓZˆOØ !Ó#Ü�g˜b˜TÐ!GÐHÔIÙð+ô. Ð
.¬s°<Ó/@Ð.AÐBÔCð €GÜ%.¨|¸QÓ%?ò 9Ñ!ˆÑ!ˆC�˜Üˆa�ˆs�!”C˜Ó%Ð& b¨¨s°¨¨°CÐ8Ô9Ü$0°Ó$5Ñ!ˆ�kØ Ò, Hˆ
ÙØ�N‰N˜C ¨
°LÐAÕBäÐ$ S EÐ)9Ð:Ô;Ø�N‰N˜C ¨
°BÐ7Õ8ð9ô ˆwÔô ˆ"ˆVˆHˆÔÜˆ-œ˜G›�~ YÐ/Ô0ÙÜ gÖ6 °°1³˜˜!›Ò6Ó7ˆÜˆl˜5 ™8˜* C¨¨b©	 {Ð3Ô4ð&ÛØ�‰œwÓ'ˆØ�‰ð ô
 ˆYô	ð 	�‰ŒØ�
‰
ŒÜÐ/Ô0ô ˆ6ˆ(Õùôq UùòJ 7øô  ò &ÜÐ   Ð$×%Ñ%ûð&ús7   Â+K
Â7K
Â=K
È/
KÈ:KÉ AK Ë	K5ËK0Ë0K5Ú__main__)Ú__doc__Úosr   ry   r5   Úbs4r   Úurllib.parser   r   r   Úenvironr6   r_   r$   r%   r#   rc   rd   r~   r7   r   r   r    r'   rI   r[   rj   r‘   Ú__name__rp   r   r   ú<module>r™      s¾   ðñó  
Û 	Û 
Û Ý Ý  ß (ð �*‰*�.‰.˜ b§j¡j§n¡n°]ÐDUÓ&VÓ
W€ð #€Ø%€	Ø�iÑ€Ø#€	Ø	 €Ø	€ð ð 3ð€òòòò;òòB*"òX"8òHFðR ˆzÒÙ…Fð r   