Ë
    €ÛµjÆ1  ã                   óþ   — d Z ddlZddlZddl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 dZdZdZd	Zd
ZdZdZddddœZg d¢Zd„ Zd„ Zd„ Zd„ Zd„ Zd„ Zd„ Zd„ Zd„ Zd d„Zd„ Z d„ Z!d„ Z"e#dk(  r e"«        yy)!uÓ  
Crawler for æ—¥ç…§å¸‚çŽ¯å¢ƒä¿�æŠ¤ç§‘å­¦ç ”ç©¶æ‰€æœ‰é™�å…¬å�¸ - ä¿¡æ�¯å…¬ç¤º
CMS: Custom PHP (index.php routing)
List: li > a (title) + span (date), 10 items/page
Pagination: index.php/index/category/index/page/N?id=110, 26 pages, ~253 items
Detail: h3 title, div.nscontent content (p tags), div.content_tit date
Attachments: a[href*=pdf|doc|rar|zip]

Usage:
    python3 crawl_rzhks.py             # Full crawl
    python3 crawl_rzhks.py --max-pages 1  # Incremental
é    N)Údatetime)ÚBeautifulSoup)Úurljoinz/root/search.dbu=   æ—¥ç…§å¸‚çŽ¯å¢ƒä¿�æŠ¤ç§‘å­¦ç ”ç©¶æ‰€æœ‰é™�å…¬å�¸-ä¿¡æ�¯å…¬ç¤ºu   ä¿¡æ�¯å…¬ç¤ºu   ä¼�ä¸š-å±±ä¸œzhttp://www.rzhks.comz:http://www.rzhks.com/index.php/index/category/index?id=110é   zoMozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36z?text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8zzh-CN,zh;q=0.9,en;q=0.8)z
User-AgentÚAcceptzAccept-Language)u   ã€�æ‰“å�°æœ¬é¡µã€‘u   ã€�å…³é—­çª—å�£ã€‘u   æ‰“å�°æœ¬é¡µu   å…³é—­çª—å�£u   è½¬è½½åˆ†äº«ï¼šu   æµ�è§ˆé‡�ï¼šu   ç›¸å…³é™„ä»¶ï¼šu   ç›¸å…³ç¨¿ä»¶ï¼šu   æ‰«ä¸€æ‰«åœ¨æ‰‹æœºæ‰“å¼€u	   é™„ä»¶ï¼šu   ç´¯è®¡æ¬¡æ•°ï¼šu	   å­—å�·ï¼šc                 óJ  — g }| j                   D �]s  }t        |t        «      r%|j                  «       }|sŒ'|j	                  |«       Œ9|j
                  dk(  rp|j                  dd«      j                  «       }|j                  d¬«      }|r'|r%t        ||«      }|j	                  d|› d|› d�«       Œ£|sŒ¦|j	                  |«       Œ¸|j
                  d	k(  rU|j                  d
d«      }|sŒÜ|j                  dd«      }	t        ||«      }
|j	                  |	r	d|	› d|
› d�nd|
› d�«       �Œ|j
                  dk(  r|j	                  d«       �Œ>t        |d«      s�ŒL|j                  dd¬«      }|s�Œc|j	                  |«       �Œv dj                  |«      j                  «       S )NÚaÚhrefÚ T©Ústripú[ú](ú)ÚimgÚsrcÚaltú![ú![](Úbrú
Úget_textú )ÚchildrenÚ
isinstanceÚstrr   ÚappendÚnameÚgetr   r   ÚhasattrÚjoin)Úp_tagÚ
detail_urlÚpartsÚelemÚtr
   ÚtextÚfullr   r   Úfull_srcs              ú /root/gov_crawler/crawl_rzhks.pyÚrender_paragraphr+   ,   sl  € Ø€EØ—‘ó  ˆÜ�dœCÔ Ø—
‘
“ˆAÚØ—‘˜Q•Ø�Y‰Y˜#ÒØ—8‘8˜F BÓ'×-Ñ-Ó/ˆDØ—=‘= t�=Ó,ˆDÙ™Ü˜z¨4Ó0�Ø—‘˜q   b¨¨¨aÐ0Õ1ÚØ—‘˜TÕ"Ø�Y‰Y˜%ÒØ—(‘(˜5 "Ó%ˆCÚØ—h‘h˜u bÓ)�Ü" :¨sÓ3�Ø—‘¹˜r #  b¨¨
°!Ñ4À4ÈÀzÐQRÐASÖTØ�Y‰Y˜$ÒØ�L‰L˜ÖÜ�T˜:Ö&Ø—‘˜c¨�Ó.ˆAÛØ—‘˜Q–ð1 ð2 �8‰8�E‹?× Ñ Ó"Ð"ó    c                 óü   — g }| j                  d«      D ]e  }|j                  dd«      }|sŒt        ||«      }|j                  dd«      }|j                  |r	d|› d|› d�nd|› d�«       |j	                  «        Œg |S )	Nr   r   r   r   r   r   r   r   )Úfind_allr   r   r   Ú	decompose)Úcontent_divr#   Úimgsr   r   r)   r   s          r*   Úextract_imagesr2   J   sˆ   € Ø€DØ×#Ñ# EÓ*ò ˆØ�g‰g�e˜RÓ ˆÚÜ˜z¨3Ó/ˆHØ—'‘'˜% Ó$ˆCØ�K‰K±3˜"˜S˜E  H :¨QÑ/¸dÀ8À*ÈAÐ<NÔOØ�M‰M�Oðð €Kr,   c                 óÊ   — g }| j                  d«      D ]L  }t        |«      }t        |j                  d¬«      «      dk\  r|j	                  |«       |j                  «        ŒN |S )NÚtableTr   é   )r.   r   Úlenr   r   r/   )r0   Útablesr4   Ú
table_htmls       r*   Úextract_tablesr9   V   s_   € Ø€FØ×%Ñ% gÓ.ò ˆÜ˜“Zˆ
Üˆu�~‰~ Dˆ~Ó)Ó*¨bÒ0Ø�M‰M˜*Ô%Ø�‰Õð	ð
 €Mr,   c                 ó   — t        | «      S )u'   ä¿�ç•™ HTML è¡¨æ ¼ç»“æž„ï¼ˆä¸�è½¬ mdï¼‰)r   )r4   ÚargsÚkwargss      r*   Útable_to_mdr=   `   s   € äˆu‹:Ðr,   c                 óV  ‡
— g }| j                  ddg«      D ]  }|j                  «        Œ t        | «      }t        | |«      }t	        | j                  g d¢d¬«      «      D ]U  }|j
                  dk(  sŒt        ||«      Š
‰
sŒ"t        ˆ
fd„t        D «       «      rŒ;|r‰
|d   vsŒE|j                  ‰
«       ŒW d	j                  |«      }|r6|D ]1  }t        |d
«      j                  d«      }	|	sŒ!|d	t        |	«      z   z  }Œ3 |r|d	d	j                  |«      z   z  }|j                  «       S )NÚscriptÚstyle)Úpr4   ÚdivÚsectionÚcenterÚfontT)Ú	recursiverA   c              3   ó&   •K  — | ]  }|‰v –— Œ
 y ­w©N© )Ú.0ÚskÚtxts     €r*   ú	<genexpr>z"extract_content.<locals>.<genexpr>p   s   øè ø€ Ò>¨R˜r SœyÑ>ùs   ƒéÿÿÿÿú

úhtml.parserr4   )r.   r/   r9   r2   Úlistr   r+   ÚanyÚ
SKIP_TEXTSr   r!   r   Úfindr=   r   )r0   r#   r$   ÚsÚtable_htmlsÚ	img_linesÚchildÚresultÚt_htmlÚ	table_tagrL   s             @r*   Úextract_contentr\   d   s)  ø€ Ø€Eà×!Ñ! 8¨WÐ"5Ó6ò ˆØ	�‰�ðô ! Ó-€KÜ˜{¨JÓ7€Iä�k×*Ñ*Ò+]ÐimÐ*ÓnÓoò &ˆØ�:‰:˜ÓÜ" 5¨*Ó5ˆCÚœ3Ó>´:Ô>Õ>Ù ¨5°©9Ò 4Ø—L‘L Õ%ð&ð �[‰[˜Ó€FÙà!ò 	:ˆFÜ% f¨mÓ<×AÑAÀ'ÓJˆIÚØ˜&¤;¨yÓ#9Ñ9Ñ9‘ð	:ñ Ø�&˜6Ÿ;™; yÓ1Ñ1Ñ1ˆà�<‰<‹>Ðr,   c                 ó„  — g }t        «       }| j                  dd¬«      D ]�  }|d   }t        j                  d|t        j                  «      sŒ.t        ||«      }|j                  d¬«      xs& |j                  d«      d   j                  d	«      d
   }||vsŒy|j                  |«       |j                  ||dœ«       ŒŸ |S )Nr	   T)r
   r
   z&\.(pdf|doc|docx|xls|xlsx|rar|zip|txt)$r   ú/rN   ú?r   )r   Úurl)
Úsetr.   ÚreÚsearchÚIr   r   ÚsplitÚaddr   )Úsoupr#   ÚattsÚseenr	   r
   Úfull_urlr   s           r*   Úextract_attachmentsrk   ƒ   s²   € Ø€DÜ‹5€DØ�]‰]˜3 Tˆ]Ó*ò =ˆØ�‰yˆÜ�9‰9Ð>ÀÄbÇdÁdÕKÜ˜z¨4Ó0ˆHØ—:‘: D�:Ó)ÒN¨T¯Z©Z¸«_¸RÑ-@×-FÑ-FÀsÓ-KÈAÑ-NˆDØ˜tÒ#Ø—‘˜Ô"Ø—‘ T°(Ñ;Õ<ð=ð €Kr,   c                 ó\  — 	 t        j                  | t        d¬«      }d|_        t        |j                  d«      }|j                  d«      }|r|j                  d	¬
«      nd}d}|j                  dd¬«      }|r;|j                  d	¬
«      }t        j                  d|«      }	|	r|	j                  d«      }|j                  dd¬«      }
d}|
rt        |
| «      }n)|j                  d«      }|r|j                  dd	¬
«      d d }t!        || «      }t#        |j%                  «       «      dk  r“d| › d|xs | › d�}|j'                  d«      }g }|D ]U  }|j                  dd«      }|sŒt)        | |«      }|j                  dd«      }|j+                  |r	d|› d|› d�nd|› d�«       ŒW |r|ddj-                  |«      z   z  }|r-|D ](  }d |d!   › d|d"   › d�}||vsŒ|d#|d!   › d|d"   › d�z  }Œ* ||||fS # t        $ r1}t        d| › d|› �t        j                  ¬«       d d d g fcY d }~S d }~ww xY w)$Né   ©ÚheadersÚtimeoutúutf-8z  fetch_detail error ú: ©ÚfilerP   Úh3Tr   r   rB   Úcontent_tit©Úclass_u"   å�‘å¸ƒæ—¶é—´ï¼š(\d{4}-\d{2}-\d{2})é   Ú	nscontentÚbodyr   iô  z<p><a href="z">z</a></p>r   r   r   r   r   r   r   rO   r   r   r`   u   

é™„ä»¶ï¼š[)Úrequestsr   ÚHEADERSÚencodingÚ	ExceptionÚprintÚsysÚstderrr   r'   rT   r   rb   rc   Úgroupr\   rk   r6   r   r.   r   r   r!   )r`   ÚrÚerg   ru   ÚtitleÚdate_strÚctÚct_textÚmr0   Úcontentr{   Úattachmentsr1   rW   r   r   r)   r   r	   Úinline_markers                         r*   Úfetch_detailrŽ   “   sv  € ð$Ü�L‰L˜¤g°rÔ:ˆØˆŒ
ô
 ˜Ÿ™ Ó/€Dð 
�‰�4‹€BÙ')ˆB�K‰K˜dˆKÔ#¨r€Eð €HØ	�‰�5 ˆÓ	/€BÙ	Ø—+‘+ D�+Ó)ˆÜ�I‰IÐ;¸WÓEˆÙØ—w‘w˜q“zˆHð —)‘)˜E¨+�)Ó6€KØ€GáÜ! +¨sÓ3‰ð �y‰y˜Ó ˆÙØ—m‘m C¨t�mÓ4°T°cÐ:ˆGô & d¨CÓ0€Kô ˆ7�=‰=‹?Ó˜bÒ Ø    R¨ª° ~°XÐ>ˆØ�}‰}˜UÓ#ˆØˆ	Øò 	YˆCØ—'‘'˜% Ó$ˆCÚÜ" 3¨Ó,�Ø—g‘g˜e RÓ(�Ø× Ñ ¹C 2 c U¨"¨X¨J°aÑ!8ÀtÈHÈ:ÐUVÐEWÕXð	Yñ Ø�v §¡¨IÓ 6Ñ6Ñ6ˆGñ Øò 	EˆAØ  &¡	˜{¨"¨Q¨u©X¨J°aÐ8ˆMØ GÒ+Ø˜^¨A¨f©I¨;°b¸¸5¹¸
À!ÐDÑD‘ð	Eð
 �(˜G [Ð0Ð0øôo ò $ÜÐ% c U¨"¨Q¨CÐ0´s·z±zÕBØ�T˜4 Ð#Õ#ûð$ús   ‚#G1 Ç1	H+Ç:&H&È H+È&H+c                 ó"   — | dk(  rt         S d| › �S )Nry   z@http://www.rzhks.com/index.php/index/category/index?id=110&page=)ÚLIST_URL)Úpage_nums    r*   Úget_list_urlr’   Ó   s   € Ø�1‚}ÜˆØMÈhÈZÐXÐXr,   c                 ó,  — t        | «      }	 t        j                  |t        d¬«      }d|_        |j                  dk7  r-t        d| › d	|j                  › �t        j                  ¬«       g S t        |j                  d
«      }|j                  dd¬«      }|sg S g }|j                  d«      D ]¬  }|j                  d«      }|r|j                  d«      sŒ(|d   j                  «       }	|j                  d¬«      }
|	j!                  d«      r|	nt#        ||	«      }|j                  d«      }|r|j                  d¬«      nd}|
sŒ–|sŒ™|j%                  |
||f«       Œ® |S # t
        $ r-}t        d|› d|› �t        j                  ¬«       g cY d }~S d }~ww xY w)Nrm   rn   rq   z  Error fetching rr   rs   éÈ   ú  Page z: HTTP rP   rB   Ú	news_listrw   Úlir	   r
   Tr   ÚhttpÚspanr   )r’   r|   r   r}   r~   r   r€   r�   r‚   Ústatus_coder   r'   rT   r.   r   r   Ú
startswithr   r   )r‘   r`   r„   r…   rg   Úlist_divÚitemsr—   r	   r
   r†   Úpage_urlr™   r‡   s                 r*   Úextract_list_pagerŸ   Ù   sn  € Ü
�xÓ
 €CðÜ�L‰L˜¤g°rÔ:ˆØˆŒ
ð
 	‡}�}˜ÒÜ�˜�z ¨¯©¨Ð8¼s¿z¹zÕJØˆ	ä˜Ÿ™ Ó/€Dà�y‰y˜ {ˆyÓ3€HÙØˆ	à€EØ×Ñ Ó%ò 6ˆØ�G‰G�C‹LˆÙ˜Ÿ™˜fœØà�‰y�‰Ó ˆØ—
‘
 �
Ó&ˆØŸ?™?¨6Ô2‘4¼ÀÀTÓ8Jˆà�w‰w�v‹ˆÙ04�4—=‘= t�=Ô,¸"ˆâ’XØ�L‰L˜% ¨8Ð4Õ5ð6ð €Løô= ò ÜÐ! #  b¨¨Ð,´3·:±:Õ>Ø�	ûðús   �#E Å	FÅ&"FÆFÆFc                 ól  — t        d|dz   «      D ]  }	  | «       c S  y
# t        j                  $ r�}dt        |«      v rC||k  r>t	        d|› d|› d|› d|› d�	t
        j                  ¬«       t        j                  |«       n't	        d|› d	|› �t
        j                  ¬«       Y d }~ y
Y d }~Œžd }~ww xY w)Nry   Úlockedz  z: locked (attempt r^   z), retry in zs...rs   z	 failed: F)	ÚrangeÚsqlite3ÚOperationalErrorr   r€   r�   r‚   ÚtimeÚsleep)ÚfnÚdescÚmax_attemptsÚdelayÚattemptr…   s         r*   Ú
with_retryr¬     s¸   € Ü˜˜L¨1Ñ,Ó-ò 	ˆð	Ù“4ŠKð	ð øô ×'Ñ'ò 	Øœ3˜q›6Ñ! g°Ò&<Ü˜˜4˜&Ð 2°7°)¸1¸\¸NÈ,ÐW\ÐV]Ð]aÐbÔil×isÑisÕtÜ—
‘
˜5Õ!ä˜˜4˜& 	¨!¨Ð-´C·J±JÕ?Ýô "ûð	ús   ”ŸB3²A1B.Â.B3c                  ó€   — t        j                  t        d¬«      } | j                  d«       | j                  d«       | S )Né   )rp   zPRAGMA journal_mode=WALzPRAGMA busy_timeout=30000)r£   ÚconnectÚDB_PATHÚexecute©Úconns    r*   Úinit_dbr´     s1   € Ü�?‰?œ7¨BÔ/€DØ‡L�LÐ*Ô+Ø‡L�LÐ,Ô-Ø€Kr,   c                 ó†  — |r|n|}t        j                  dd|«      j                  «       }|rt        j                  |d¬«      nd}|}	 | j                  dt        |||j                  «       |||t        |t        f
«      }	|	j                  dkD  S # t        $ r(}
t        d|
› �t        j                  ¬	«       Y d }
~
yd }
~
ww xY w)
Nz\s+r   F)Úensure_asciiz[]zÍINSERT OR IGNORE INTO gov_raw
               (site_name, source_url, page_url, title, publish_date, summary, content, category, attachments, group_name)
               VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)r   z  DB error: rs   )rb   Úsubr   ÚjsonÚdumpsr±   Ú	SITE_NAMEÚCATEGORYÚGROUPÚrowcountr   r€   r�   r‚   )r³   r†   rž   Úpublish_dater‹   rŒ   ÚsummaryÚatt_jsonÚ
source_urlÚcurr…   s              r*   Úsave_articlerÃ     s³   € Ù ‰g e€GÜ�f‰f�V˜S 'Ó*×0Ñ0Ó2€GÙ>IŒt�z‰z˜+°EÕ:Èt€HØ€JðØ�l‰lð8ô ˜
 H¨e¯k©k«m¸\Ø�gœx¨´5ð:ó	
ˆð �|‰|˜aÑÐøÜò Ü�˜Q˜CÐ ¤s§z¡zÕ2Üûðús   Á
AB Â	C ÂB;Â;C c            
      óð  ‡— t         } t        t        j                  «      dkD  r	 t	        t        j                  d   «      } t        dt        › d| › �t        j                  ¬«       t        «       Šd}d}ˆfd„}t        |d	t        › �¬
«       t        dt        › �t        j                  ¬«       t        d| dz   «      D �][  }t        |«      }|s"t        d|› d�t        j                  ¬«        �n,|t        |«      z  }|D ]Ø  \  }}}|r*|dk  r%t        d|› d|d d › �t        j                  ¬«       Œ3‰j                  d|f«      }	|	j                  «       rŒWt        |«      \  }
}}}|
xs |}|xs |}|xs	 d|› d|› d�}|xs g }t!        ‰|||||«      r.|dz  }|dk  r$t        d|› d|d d › �t        j                  ¬«       t#        j$                  d«       ŒÚ t        d|› dt        |«      › d|› d�t        j                  ¬«       ‰j'                  «        �Œ^ ˆfd„}t        |dt        › �¬
«       t        dt        › �t        j                  ¬«       ‰j)                  «        t        d |› d!|› �t        j                  ¬«       y # t
        $ rb t        j                  d   dv rIt        t        j                  «      dkD  r-	 t	        t        j                  d   «      } n# t
        $ r Y nw xY wY �Œ³w xY w)"Nry   )z--max-pagesé   z	Scraping z, max pages: rs   r   c                  ó&   •— ‰ j                  «        y rH   )Úcommitr²   s   €r*   Údo_cleanzmain.<locals>.do_clean=  s   ø€ ð 	�‰�r,   zClean )r¨   z  Cleaned old data for r•   z: 0 articles (end)z
2020-01-01z  Skip old: r   é(   z)SELECT id FROM gov_raw WHERE page_url = ?r   r   r   é   z  + é2   g333333Ó?rr   z found, z totalc                  óT   •— ‰ j                  dt        f«       ‰ j                  «        y )Nz~INSERT INTO gov_search(rowid, title, site_name, summary) SELECT id, title, site_name, summary FROM gov_raw WHERE site_name = ?)r±   rº   rÇ   r²   s   €r*   Údo_ftszmain.<locals>.do_ftsg  s-   ø€ à�‰ð  Vô  Ybð  Xdô  	eØ�‰�r,   zFTS rebuild z  FTS index rebuilt for z
Done! Found: z, New: )Ú	MAX_PAGESr6   r�   ÚargvÚintÚ
ValueErrorr€   rº   r‚   r´   r¬   r¢   rŸ   r±   ÚfetchonerŽ   rÃ   r¥   r¦   rÇ   Úclose)Ú	max_pagesÚ	total_newÚtotal_foundrÈ   ÚpnÚarticlesr†   rž   ÚdaterÂ   Ú	det_titleÚdet_dateÚdet_contentÚdet_attsÚfinal_titleÚ
final_dateÚfinal_contentÚ
final_attsrÍ   r³   s                      @r*   Úmainrâ   +  s¸  ø€ Ü€IÜ
Œ3�8‰8ƒ}�qÒð	ÜœCŸH™H Q™KÓ(ˆIô 
ˆI”i�[ ¨i¨[Ð
9ÄÇ
Á
ÕKÜ‹9€DØ€IØ€Kôô
 ˆx ¤y kÐ2Õ3Ü	Ð#¤I ;Ð
/´c·j±jÕAä�A�y 1‘}Ó%ó ˆÜ$ RÓ(ˆÙÜ�G˜B˜4Ð1Ð2¼¿¹ÕDÚà”s˜8“}Ñ$ˆà%-ò 	Ñ!ˆE�8˜TÙ˜˜|Ò+Ü˜ T F¨!¨E°#°2¨J¨<Ð8¼s¿z¹zÕJØà—,‘,ÐJÈXÈKÓXˆCØ�|‰|Œ~Øä9EÀhÓ9OÑ6ˆI�x ¨hØ#Ò, uˆKØ!Ò) TˆJØ'ÒI¨Q¨{¨m¸2¸h¸ZÀqÐ+IˆMØ!š RˆJä˜D +¨x¸À]ÐT^Ô_Ø˜Q‘�	Ø ’>Ü˜D  ¨A¨k¸#¸2Ð.>Ð-?Ð@ÄsÇzÁzÕRä�J‰J�s�Oð)	ô, 	�˜�t˜2œc (›m˜_¨H°Y°K¸vÐFÌSÏZÉZÕXØ�‰Žð?ôDô ˆv˜l¬9¨+Ð6Õ7Ü	Ð$¤Y KÐ
0´s·z±zÕBà‡J�J„LÜ	ˆO˜K˜=¨°	¨{Ð
;Ä#Ç*Á*ÖMøô ò 	Ü�x‰x˜‰{Ð.Ñ.´3´s·x±x³=À1Ò3DðÜ #¤C§H¡H¨Q¡KÓ 0‘IøÜ!ò Ùðýð		ús5   ¥J
 Ê
:K5ËK"Ë!K5Ë"	K.Ë+K5Ë-K.Ë.K5Ë4K5Ú__main__)zDB opé
   rÊ   )$Ú__doc__r|   rb   r¸   r£   r¥   Úosr�   r   Úbs4r   Úurllib.parser   r°   rº   r»   r¼   ÚBASE_URLr�   rÎ   r}   rS   r+   r2   r9   r=   r\   rk   rŽ   r’   rŸ   r¬   r´   rÃ   râ   Ú__name__rI   r,   r*   ú<module>rë      s¹   ðñ÷ 2× 1× 1Ó 1Ý Ý Ý  à
€ØK€	Ø€Ø€Ø!€ØG€Ø€	ð DØOØ0ñ€ò€
ò#ò<	òòòò>ò ;1ò@Yò#óPòòò*DNðN ˆzÒÙ…Fð r,   