Ë
    m }jê(  ã            	       óN  — 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ddedz   dddddœddedz   dddddœgZddiZd„ Zd„ Zd%d„Zd„ Zd „ Zd!„ Zd&d"„Zd#„ Zed$k(  r e«        yy)'u:  
crawl_hhgj.py â€” ä¸ªæ—§å¸‚äººæ°‘æ”¿åºœÂ·çŽ¯å¢ƒä¿�æŠ¤/çŽ¯ä¿�ä¿¡æ�¯
=============================================
TRS CMSï¼Œé�™æ€�åˆ†é¡µ

æ �ç›®1: hjbh1.htm â†’ hjbh1/{N}.htm   (çŽ¯å¢ƒä¿�æŠ¤, 8é¡µ, NEWâ†’OLD)
æ �ç›®2: hbxx.htm  â†’ hbxx/{N}.htm    (çŽ¯ä¿�ä¿¡æ�¯, 54é¡µ, OLDâ†’NEW)

åˆ—è¡¨ï¼š<li><a href="../../info/XXXXX/XXXXX.htm">Title YYYY.MM.DD</a></li>
è¯¦æƒ…ï¼š<div class="content"> æ­£æ–‡ | <meta name="PubDate"> æ—¥æœŸ

ç”¨æ³•:
    python3 crawl_hhgj.py               # å…¨é‡�ï¼ˆä¸¤ä¸ªæ �ç›®ï¼‰
    python3 crawl_hhgj.py 1             # å¢žé‡�ï¼ˆå�ªçˆ¬é¦–é¡µï¼‰
é    N)ÚBeautifulSoup)Úurljoin)ÚdatetimeÚ	timedeltaÚ	SEARCH_DBÚGOV_DB_PATHz/root/search.dbzhttps://www.hhgj.gov.cnu   ä¸ªæ—§å¸‚äººæ°‘æ”¿åºœu   çŽ¯å¢ƒä¿�æŠ¤u   ä¸ªæ—§å¸‚çŽ¯å¢ƒä¿�æŠ¤z/ztlm/ggqsydwxxgkpt/hjbh1.htmz/ztlm/ggqsydwxxgkpt/hjbh1é   Ú
new_to_oldÚdot)ÚnameÚsourceÚlist_urlÚpage_dirÚn_pagesÚ	directionÚdate_fmtu   çŽ¯ä¿�ä¿¡æ�¯u   ä¸ªæ—§å¸‚çŽ¯ä¿�ä¿¡æ�¯z"/zfxxgk/fdzdgknr/zdlyxxgk/hbxx.htmz/zfxxgk/fdzdgknr/zdlyxxgk/hbxxé6   Ú
old_to_newÚdashz
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[hhgj] )Úprint)Úmsgs    ú/root/gov_crawler/crawl_hhgj.pyÚlogr   >   s   € Ü	ˆG�C�5ˆ/Õó    c                 ób   — | j                  dd«      j                  dd«      j                  «       S )Nu   -ä¸ªæ—§å¸‚äººæ°‘æ”¿åºœÚ u
   -ä¸ªæ—§å¸‚)ÚreplaceÚstrip)Útitles    r   Úclean_titler!   A   s*   € Ø�=‰=Ð1°2Ó6×>Ñ>¸|ÈRÓP×VÑVÓXÐXr   c                 ó   — |dk(  rPt        j                  d| «      }|r7|j                  d«      › d|j                  d«      › d|j                  d«      › �S yt        j                  d| «      }|r|j                  d«      S y)	z Extract date from list item textr   z(\d{4})\.(\d{2})\.(\d{2})é   ú-é   é   ú(\d{4}-\d{2}-\d{2})r   )ÚreÚsearchÚgroup)ÚtextÚfmtÚms      r   Úextract_date_from_textr.   D   sx   € à
ˆe‚|Ü�I‰IÐ2°DÓ9ˆÙØ—g‘g˜a“j�\  1§7¡7¨1£: ,¨a°·±¸³
¨|Ð<Ð<ð
 ô �I‰IÐ,¨dÓ3ˆÙØ—7‘7˜1“:ÐØr   c                 ó¸  — |dk(  r| d   }nt         › | d   › d|› d�}	 t        j                  |t        d¬«      }d|_        |j
                  }g }t        j                  d|t        j                  «      D �]¹  }|j                  d«      }t        j                  d|«      }	|	sŒ.|	j                  d«      }
t        j                  d|t        j                  «      }|r4t        j                  dd|j                  d«      «      j                  «       nd}t        j                  dd|«      j                  «       }t        j                  dd|«      j                  «       }t        |«      }t!        || d   «      }|
j#                  d«      r-t         › ddj%                  |
j'                  d«      dd «      › �}nh|
j#                  d«      rt         › d|
dd › �}nH|
j#                  d«      rt         › d|
dd › �}n(|
j#                  d«      rt         › |
› �}nt)        ||
«      }|j+                  |||f«       �Œ¼ |S # t        $ r}t        d	|› d
|› �«       g cY d}~S d}~ww xY w)z9Fetch one list page, return [(url, title, date_str), ...]r#   r   r   ú/z.htmé   ©ÚheadersÚtimeoutúutf-8ú  ERROR fetching ú: Nz<li[^>]*>(.*?)</li>z.href=\"([^\"]*(?:info|content)/\d+/\d+\.htm)\"z<a[^>]*>(.*?)</a>z<[^>]+>r   z\d{4}\.\d{2}\.\d{2}z\d{4}-\d{2}-\d{2}r   z	../../../r&   z../../é   z../)ÚBASE_URLÚrequestsÚgetÚHEADERSÚencodingr+   Ú	Exceptionr   r(   ÚfinditerÚDOTALLr*   r)   Úsubr   r!   r.   Ú
startswithÚjoinÚsplitr   Úappend)ÚcolÚpage_numÚurlÚrespÚhtmlÚeÚitemsr-   ÚliÚaÚhrefÚ
text_matchr+   r    Údate_strÚfull_urls                   r   Úfetch_list_pagerS   P   s/  € à�1‚}Ø�*‰o‰ä�
˜3˜z™?Ð+¨1¨X¨J°dÐ;ˆðÜ�|‰|˜C¬¸"Ô=ˆØˆŒØ�y‰yˆð €Eä�[‰[Ð/°´r·y±yÓAó 2ˆØ�W‰W�Q‹ZˆÜ�I‰IÐGÈÓLˆÙØØ�w‰w�q‹zˆä—Y‘YÐ3°R¼¿¹ÓCˆ
ÙFPŒr�v‰v�j " j×&6Ñ&6°qÓ&9Ó:×@Ñ@ÔBÐVXˆô —‘Ð-¨r°4Ó8×>Ñ>Ó@ˆÜ—‘Ð+¨R°Ó7×=Ñ=Ó?ˆÜ˜EÓ"ˆô *¨$°°J±Ó@ˆð �?‰?˜;Ô'Ü"˜ 1 S§X¡X¨d¯j©j¸«o¸a¸bÐ.AÓ%BÐ$CÐD‰HØ�_‰_˜XÔ&Ü"˜ 1 T¨!¨" X JÐ/‰HØ�_‰_˜UÔ#Ü"˜ 1 T¨!¨" X JÐ/‰HØ�_‰_˜SÔ!Ü"˜ D 6Ð*‰Hä˜s DÓ)ˆHà�‰�h  xÐ0Ö1ð=2ð@ €LøôO ò ÜÐ ˜u B q cÐ*Ô+Ø�	ûðús   ž/H3 È3	IÈ<IÉIÉIc                 óÄ  — 	 t        j                  | t        d¬«      }d|_        |j                  }t        |d«      }d	}d
ddidfd
ddidfd
dt        j                  d«      idffD ])  }|j                  |d   |d   «      }|sŒt        |«      } n d	}|j                  dddi¬«      }	|	rM|	j                  d«      r<|	d   j                  «       }
t        j                  d|
«      }|r|j                  d«      }|s)t        j                  d|«      }|r|j                  d«      }|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)r1   r2   r5   r6   r7   N)NNzhtml.parserr   ÚdivÚclassÚcontentzxxgk-conÚidÚvsb_contentr   r#   Úmetar   ÚPubDate)Úattrsr'   u(   å�‘å¸ƒæ—¥æœŸ[ï¼š:]\s*(\d{4}-\d{2}-\d{2})z  WARNING: no content for )r:   r;   r<   r=   r+   r>   r   r   r(   ÚcompileÚfindÚstrr   Úmatchr*   r)   )rH   rI   rJ   rK   ÚsoupÚcontent_htmlÚselectorrU   rQ   rZ   Úrawr-   s               r   Úfetch_detailre   „   s‡  € ðÜ�|‰|˜C¬¸"Ô=ˆØˆŒØ�y‰yˆô
 ˜˜}Ó-€Dð €Là	�˜)Ð$ dÐ+Ø	�˜*Ð% tÐ,Ø	�”r—z‘z .Ó1Ð2°DÐ9ðò ˆð
 �i‰i˜ ™ X¨a¡[Ó1ˆÚÜ˜s›8ˆLÙðð €HØ�9‰9�V F¨IÐ#6ˆ9Ó7€DÙ�—‘˜Ô#Ø�9‰o×#Ñ#Ó%ˆÜ�H‰HÐ+¨SÓ1ˆÙØ—w‘w˜q“zˆHñ Ü�I‰IÐAÀ4ÓHˆÙØ—w‘w˜q“zˆHáÜÐ(¨¨Ð.Ô/Ø�Xˆ~Ðà˜Ð!Ð!øôK ò ÜÐ ˜u B q cÐ*Ô+Üûðús   ‚/D; Ä;	EÅEÅEc           
      ór  — dd l }| syt        dt        › �«       |j                  t        «      }|j	                  «       }d}| D ]*  \  }}}}}		 |j                  dt        |||||	f«       |dz  }Œ, |j                  «        |j                  «        |S # t        $ r}
t        d|› d|
› �«       Y d }
~
Œnd }
~
ww xY w)Nr   zOpening DB: zœINSERT OR REPLACE INTO gov_raw
                   (site_name, page_url, title, publish_date, content, category)
                   VALUES (?, ?, ?, ?, ?, ?)r#   z  DB error for r7   )
Úsqlite3r   ÚDB_PATHÚconnectÚcursorÚexecuteÚ	SITE_NAMEr>   ÚcommitÚclose)rL   rg   ÚconnÚcÚinsertedrH   r    rQ   rb   r   rK   s              r   Ú
save_to_dbrr   ±   sÈ   € ÛÙØÜˆ,”w�iÐ Ô!Ø�?‰?œ7Ó#€DØ�‰‹€AØ€HØ6;ò 
.Ñ2ˆˆU�H˜l¨Fð		.Ø�I‰Ið0ô ˜C ¨°,ÀÐGô	ð ˜‰M‰Hð
.ð 	‡K�K„MØ‡J�J„LØ€Oøô	 ò 	.Ü�/ #  b¨¨Ð,×-Ñ-ûð	.ús   Á!BÂ	B6ÂB1Â1B6c                 ó�  — t        j                  «       t        d¬«      z
  j                  d«      }| d   }t	        dd› �«       t	        d|› �«       t	        d|› �«       |r| d	   d
k(  rdg}n2| d   g}n+| d	   d
k(  rt        d| d   dz   «      }nt        | d   dd«      }g }|D �]  }t        | |«      }|st	        d|› d�«       Œ"|D ��	�
cg c]  \  }}	}
|
sŒ
|
|k\  sŒ||	|
f‘Œ }}	}}
|r8|j                  |«       t	        d|› dt        |«      › dt        |«      › d�«       | d	   dk(  rA|s?|r=t        d„ |D «       «      r+t        d„ |D «       «      }||k  rt	        d|› d|› d�«        nP| d	   d
k(  sŒÑ|rŒÔ|sŒ×t        d„ |D «       «      sŒêt        d„ |D «       «      }||k  s�Œt	        d|› d|› d�«        n t	        dt        |«      › �«       g }t        |d«      D ][  \  }\  }}}t	        d|› dt        |«      › d|dd  › d!�«       t        |«      \  }}|xs |}|j                  ||||xs d"| d#   f«       Œ] |S c c}
}	}w )$z@Crawl a single column, return [(url, title, date, html, source)]iG  )Údaysz%Y-%m-%dr   ú
z2==================================================zColumn: z3-year cutoff: r   r
   r#   r   r   éÿÿÿÿz  Page z: no articlesr7   r0   z	 articlesr   c              3   ó.   K  — | ]  \  }}}|sŒ
|–— Œ y ­w©N© ©Ú.0Ú_Úds      r   ú	<genexpr>zcrawl_column.<locals>.<genexpr>ï   ó   è ø€ Ò?¡g a¨¨AºQ¤Ñ?ùó   ‚Žc              3   ó.   K  — | ]  \  }}}|sŒ
|–— Œ y ­wrx   ry   rz   s      r   r~   zcrawl_column.<locals>.<genexpr>ð   ó   è ø€ Ò$D©7¨1¨a°Â!¤QÑ$Dùr€   z	: oldest=z < cutoff, stoppingc              3   ó.   K  — | ]  \  }}}|sŒ
|–— Œ y ­wrx   ry   rz   s      r   r~   zcrawl_column.<locals>.<genexpr>÷   r   r€   c              3   ó.   K  — | ]  \  }}}|sŒ
|–— Œ y ­wrx   ry   rz   s      r   r~   zcrawl_column.<locals>.<genexpr>ø   r‚   r€   z	: newest=zTotal articles: ú[z] Né2   z...r   r   )r   Únowr   Ústrftimer   ÚrangerS   ÚextendÚlenÚallÚminÚmaxÚ	enumeratere   rE   )rF   ÚincrementalÚthree_years_agor   ÚpagesÚall_articlesÚpnÚarticlesÚuÚtr}   ÚfilteredÚoldest_on_pageÚnewest_on_pageÚresultsÚirH   r    rQ   rb   Údetail_dateÚ
final_dates                         r   Úcrawl_columnrŸ   È   s«  € ä—|‘|“~¬	°wÔ(?Ñ?×IÑIÈ*ÓU€OØˆv‰;€Däˆ"ˆVˆHˆÔÜˆ(�4�&ÐÔÜˆ/˜/Ð*Ð+Ô,ñ Øˆ{Ñ˜|Ò+à�C‰Eð ˜‘^Ð$‰EØ	ˆ[Ñ	˜\Ò	)Ü�a˜˜Y™¨!Ñ+Ó,‰ô �c˜)‘n a¨Ó,ˆà€LØó ˆÜ" 3¨Ó+ˆÙÜ�'˜"˜˜]Ð+Ô,Øð .6×TÐT¡' ! Q¨º¸qÀOÓ?S�Q˜˜1’IÐTˆÒTÙØ×Ñ Ô)Ü�'˜"˜˜R¤ H£˜¨a´°H³¨¸iÐHÔIð ˆ{Ñ˜|Ò+±KÙœCÑ?°Ô?Ô?Ü!$Ñ$D°hÔ$DÓ!D�Ø! OÒ3Ü˜' "  Y¨~Ð.>Ð>QÐRÔSÙð ˆ{Ñ˜|Ó+²KÚœCÑ?°Ô?Õ?Ü!$Ñ$D°hÔ$DÓ!D�Ø! OÔ3Ü˜' "  Y¨~Ð.>Ð>QÐRÔSÙð5ô8 Ð
œ3˜|Ó,Ð-Ð.Ô/ð €GÜ%.¨|¸QÓ%?ò TÑ!ˆÑ!ˆC�˜Üˆa�ˆs�!”C˜Ó%Ð& b¨¨s°¨¨°CÐ8Ô9Ü$0°Ó$5Ñ!ˆ�kØ Ò, Hˆ
Ø�‰˜˜U J°Ò0BÀÀCÈÁMÐRÕSð	Tð €Nùô? Us   ÃI
ÃI
ÃI
c            
      ó  — t        t        j                  «      dkD  xr t        j                  d   dk(  } g }t        D ]  }t	        || «      }|j                  |«       Œ! t        |«      }t        d|› dt        |«      › dt        t        «      › d�«       |rht        |D �cg c]  }|d   sŒ	|d   ‘Œ c}«      }t        d|d	   › d
|d   › �«       t        d„ |D «       «      }t        ddj                  |«      › �«       	 d	d l}|j                  t        «      }	t        D ]  }|	j                  d|d   f«       Œ |	j                  «        |	j!                  «        t        d«       y c c}w # t"        $ r}
t        d|
› �«       Y d }
~
y d }
~
ww xY w)Nr#   Ú1z
Total saved: r0   z (z	 columns)r%   zDate range: r   z ~ rv   c              3   ó&   K  — | ]	  }|d    –— Œ y­w)é   Nry   )r{   Úrs     r   r~   zmain.<locals>.<genexpr>  s   è ø€ Ò0˜q�a˜•dÑ0ùs   ‚z	Sources: 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 = ?
            r   zFTS index rebuiltzFTS rebuild note: )r‹   ÚsysÚargvÚCOLUMNSrŸ   rŠ   rr   r   ÚsortedÚsetrC   rg   ri   rh   rk   rm   rn   r>   )r�   Úall_resultsrF   r›   Úsavedr¤   ÚdatesÚsourcesrg   ro   rK   s              r   Úmainr®   	  sx  € Ü”c—h‘h“- !Ñ#Ò:¬¯©°©°sÑ(:€Kà€KÜò $ˆÜ˜s KÓ0ˆØ×Ñ˜7Õ#ð$ô
 �{Ó#€EÜˆ/˜%˜ ¤# kÓ"2Ð!3°2´c¼'³l°^À9ÐMÔNáÜ kÖ: °Q°q³T˜˜!›Ò:Ó;ˆÜˆl˜5 ™8˜* C¨¨b©	 {Ð3Ô4ÜÑ0 KÔ0Ó0ˆÜˆi˜Ÿ	™	 'Ó*Ð+Ð,Ô-ð&ÛØ�‰œwÓ'ˆÜò 	#ˆCØ�L‰Lð ð
 �h‘-Ð!õ#ð	#ð 	�‰ŒØ�
‰
ŒÜÐÕ ùò% ;øô& ò &ÜÐ   Ð$×%Ñ%ûð&ús%   Â 
E&Â+E&Ä A%E+ Å+	FÅ4FÆFÚ__main__)r   )F)Ú__doc__Úosr(   r¥   r:   Úbs4r   Úurllib.parser   r   r   Úenvironr;   rh   r9   rl   r§   r<   r   r!   r.   rS   re   rr   rŸ   r®   Ú__name__ry   r   r   ú<module>r¶      sð   ðñó  
Û 	Û 
Û Ý Ý  ß (ð �*‰*�.‰.˜ b§j¡j§n¡n°]ÐDUÓ&VÓ
W€ð %€Ø#€	ð Ø)ØÐ>Ñ>Ø/ØØ!Øñð Ø)ØÐCÑCØ4ØØ!Øñð€ð. ð 3ð€òòYó
ò2òh+"òZó.?òB!&ðH ˆzÒÙ…Fð r   