Ë
    '}j.&  ã                   óø   — 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mZmZ ddl	m
Z
 dZdZdj                  e«      ZdZd	Zd
ZdZdZdddddddddez   dddgZd„ Zd„ Zd„ Zd„ Zd„ Zd„ Zd„ Zed k(  r e«        yy)!uÄ   
Crawler for äº‘æ¢¦åŽ¿ç”Ÿæ€�çŽ¯å¢ƒå±€ - çŽ¯å¢ƒè¯„ä»·
CMS: Hanweb/JPAAS, static .jhtml pages
Site: www.yunmeng.gov.cn/c/ymxsthjj/hjpj1.jhtml
Note: Requires --resolve + HTTPS to bypass JS challenge
é    N)ÚdatetimeÚ	timedelta)ÚBeautifulSoupzhttps://www.yunmeng.gov.cnÚymxsthjjz/c/{}/hjpj1z58.51.146.198u%   äº‘æ¢¦åŽ¿ç”Ÿæ€�çŽ¯å¢ƒå±€-çŽ¯å¢ƒè¯„ä»·é   é   é   Úcurlz-sz-kz--connect-timeoutÚ10z
--max-timeÚ20z	--resolvezwww.yunmeng.gov.cn:443:z-AzoMozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36z--compressedc                 ó:  — t         | gz   }t        j                  |ddd¬«      }|j                  dk7  r2t	        dj                  |j                  |j                  dd «      «      ‚|j                  }d|v r&d	|vr"d
|vrd|vrd|v sd|v sd|dd v rt	        d«      ‚|S )z"Fetch URL via curl with --resolve.Té   )Úcapture_outputÚtextÚtimeoutr   zcurl failed: {} (stderr: {})NéÈ   z<scriptú	news-listú
news-titleÚhtmledit_viewsÚP54ÚYf1Úfunctionz-Got JS challenge page instead of real content)Ú	BASE_CURLÚ
subprocessÚrunÚ
returncodeÚ	ExceptionÚformatÚstderrÚstdout)ÚurlÚcmdÚrÚhtmls       ú"/root/gov_crawler/crawl_yunmeng.pyÚfetchr&      sª   € ä
�s�eÑ
€CÜ�‰�s¨4°dÀBÔG€AØ‡|�|�qÒÜÐ6×=Ñ=¸a¿l¹lÈAÏHÉHÐUYÐVYÈNÓ[Ó\Ð\Ø�8‰8€Dà�DÑ˜k°Ñ5¸,ÈdÑ:RÐWgÐosÑWsØ�D‰=˜E T™M¨Z¸4ÀÀ¸:Ñ-EÜÐKÓLÐLØ€Kó    c                 ó,  — t        | d«      }g }|j                  dd¬«      }|s|S |j                  d«      D ]Ú  }|j                  ddd¬	«      }|sŒ|d
   j                  «       }|j	                  d«      xs |j                  d¬«      }|j                  dd¬«      }|r|j                  d¬«      nd}	|j                  d«      s'|j                  d«      r
t        |z   }nt        dz   |z   }|sŒ¶|sŒ¹|j                  |j                  «       ||	f«       ŒÜ |S )z3Parse list page, return list of (title, url, date).úhtml.parserÚulr   ©Úclass_ÚliÚar   T)r,   Úhrefr/   Útitle©ÚstripÚspanz	news-timeÚ Úhttpú/)	r   ÚfindÚfind_allr2   ÚgetÚget_textÚ
startswithÚBASE_URLÚappend)
r$   ÚsoupÚitemsr*   r-   r.   r/   r0   r3   Údates
             r%   Ú
parse_listrA   +   s  € ä˜˜}Ó-€DØ€EØ	�‰�4 ˆÓ	,€BÙØˆØ�k‰k˜$Óò 6ˆØ�G‰G�C °4ˆGÓ8ˆÙØØ�‰y�‰Ó ˆØ—‘�g“Ò8 !§*¡*°4 *Ó"8ˆØ�w‰w�v kˆwÓ2ˆÙ,0ˆt�}‰} 4ˆ}Ô(°bˆà�‰˜vÔ&Ø�‰˜sÔ#Ü $‘‘ä #‘~¨Ñ,�â’TØ�L‰L˜%Ÿ+™+›-¨¨tÐ4Õ5ð!6ð" €Lr'   c                 óØ  ‡— t        | d«      }d}|j                  dd¬«      }|r%|j                  d«      }|r|j                  d¬«      }d}|j                  dd	¬«      }|rU|j                  d
«      }|D ]?  }	|	j                  d¬«      }
t	        j
                  d|
«      }|sŒ.|j                  d«      } n |s0|j                  dddi¬«      }|r|j                  d«      r|d   dd }d}|j                  dd¬«      }|r|j                  «       }n%|j                  dd¬«      }|r|j                  «       }g }|r«t        |d«      }|j                  dd¬«      D ]‰  }|d   j                  «       Št        ˆfd„dD «       «      sŒ+‰j                  d«      s&‰j                  d«      r	t        ‰z   nt        dz   ‰z   Š|j                  |j                  d¬«      xs d‰dœ«       Œ‹ |||||d œS )!zParse detail page content.r)   r4   Údivr   r+   Úh2Tr1   znews-infr3   z(\d{4}[-/]\d{1,2}[-/]\d{1,2})é   ÚmetaÚnameÚPubDate)ÚattrsÚcontentNé
   Úarticler   znews-boxr.   )r/   r/   c              3   óB   •K  — | ]  }|‰j                  «       v –— Œ y ­w©N©Úlower©Ú.0ÚextÚahrefs     €r%   ú	<genexpr>zparse_detail.<locals>.<genexpr>u   s   øè ø€ Ò~¨C�3˜%Ÿ+™+›-Ô'Ñ~ùó   ƒ)	ú.pdfú.docú.docxú.xlsú.xlsxú.zipú.rarz.jpgz.pngr5   r6   u   é™„ä»¶)r0   r!   ©r0   r@   rJ   ÚattachmentsÚ
source_url)r   r7   r:   r8   ÚreÚsearchÚgroupr9   Údecode_contentsr2   Úanyr;   r<   r=   )r$   r!   r>   r0   Ú
news_titlerD   Úpub_dateÚnews_infÚspansÚsr   ÚmrF   Úcontent_htmlrL   Únews_boxr_   ÚcsoupÚa_tagrT   s                      @r%   Úparse_detailrp   F   s  ø€ ä˜˜}Ó-€Dð €EØ—‘˜5¨�Ó6€JÙØ�_‰_˜TÓ"ˆÙØ—K‘K d�KÓ+ˆEð €HØ�y‰y˜ zˆyÓ2€HÙØ×!Ñ! &Ó)ˆØò 	ˆAØ—:‘: D�:Ó)ˆDÜ—	‘	Ð:¸DÓAˆAÚØŸ7™7 1›:�Ùð	ñ Ø�y‰y˜¨°	Ð':ˆyÓ;ˆÙ�D—H‘H˜YÔ'Ø˜I‘ s¨Ð+ˆHð €LØ�i‰i˜	Ð*:ˆiÓ;€GÙØ×.Ñ.Ó0‰ð —9‘9˜U¨:�9Ó6ˆÙØ#×3Ñ3Ó5ˆLð €KÙÜ˜l¨MÓ:ˆØ—^‘^ C¨d�^Ó3ò 	ˆEØ˜&‘M×'Ñ'Ó)ˆEÜÓ~Ð3}Ô~Õ~Ø×'Ñ'¨Ô/Ø05×0@Ñ0@ÀÔ0EœH uÒ,Ì8ÐVYÉ>Ð\aÑKa�EØ×"Ñ"Ø"Ÿ^™^°$˜^Ó7ÒC¸8Ø ñ$õ ð	ð ØØØ"Øñð r'   c                 ó&  ‡
— | rt        | j                  «       «      dk  rdj                  ||«      S t        | d«      }g }|j                  D �]Ö  }|j
                  €%|j                  «       }|sŒ#|j                  |«       Œ5|j
                  dk(  r(|j                  dd¬«      }|sŒZ|j                  |«       Œl|j
                  d	k(  rHt        |«      }|j                  d
||j                  d«      d j                  dd«      d   z   dz   «       ŒÃ|j
                  dk(  r(|j                  dd¬«      }|sŒè|j                  |«       Œú|j
                  dk(  r�Œ|j
                  dk(  s�Œ|j                  dd«      Š
|j                  d¬«      }|s�ŒD‰
s�ŒH‰
j                  d«      r�Œ[t        ˆ
fd„dD «       «      r#|j                  dj                  |‰
«      «       �Œ’‰
j                  d«      r#|j                  dj                  |‰
«      «       �ŒÆ|j                  |«       �ŒÙ dj                  d„ |D «       «      j                  «       }	t        j                   dd|	«      }	t        |	j                  «       «      dk  rdj                  ||«      S |	S )z9Convert HTML to readable text with paragraphs and tables.é2   ú[{}]({})r)   NÚpú Tr1   Útablez<table>ú>z</table>rE   r   rC   Úbrr.   r/   r4   Ú
javascriptc              3   óB   •K  — | ]  }|‰j                  «       v –— Œ y ­wrN   rO   rQ   s     €r%   rU   z!render_content.<locals>.<genexpr>¦   s   øè ø€ Òr°�s˜eŸk™k›mÔ+ÑrùrV   )rW   rX   rY   rZ   r[   r\   r]   r5   z

c              3   ó&   K  — | ]	  }|sŒ|–— Œ y ­wrN   © )rR   rt   s     r%   rU   z!render_content.<locals>.<genexpr>­   s   è ø€ Ò/˜qªQœÑ/ùs   ‚Šz\n{3,}é   )Úlenr2   r   r   ÚchildrenrG   r=   r:   ÚstrÚindexÚrsplitr9   r;   re   Újoinra   Úsub)rl   r0   r!   r>   ÚpartsÚelr   Ú
table_htmlÚatextÚresultrT   s             @r%   Úrender_contentrŠ   †   s#  ø€ áœ3˜|×1Ñ1Ó3Ó4°rÒ9Ø× Ñ  ¨Ó,Ð,ä˜ }Ó5€DØ€Eà�m‰mó (ˆØ�7‰7ˆ?Ø—8‘8“:ˆDÚØ—‘˜TÕ"Ø�W‰W˜Š^Ø—;‘;˜s¨$�;Ó/ˆDÚØ—‘˜TÕ"Ø�W‰W˜Òä˜R›ˆJØ�L‰L˜ Z°
×0@Ñ0@ÀÓ0EÐ0FÐ%G×%NÑ%NÈzÐ[\Ó%]Ð^_Ñ%`Ñ`ÐcmÑmÕnØ�W‰W˜ÒØ—;‘;˜s¨$�;Ó/ˆDÚØ—‘˜TÕ"Ø�W‰W˜Š_ÙØ�W‰W˜Œ^Ø—F‘F˜6 2Ó&ˆEØ—K‘K d�KÓ+ˆEÛ› u×'7Ñ'7¸Ö'EäÓrÐ7qÔrÔrØ—L‘L ×!2Ñ!2°5¸%Ó!@ÖAØ×%Ñ% fÔ-Ø—L‘L ×!2Ñ!2°5¸%Ó!@ÖAà—L‘L Ö'ð;(ð> �[‰[Ñ/ EÔ/Ó/×5Ñ5Ó7€FÜ�V‰V�I˜v vÓ.€Fä
ˆ6�<‰<‹>Ó˜RÒØ× Ñ  ¨Ó,Ð,Ø€Mr'   c                  ój   — t        t        j                  «      dkD  xr t        j                  d   dk(  S )NrE   Úincremental)r~   ÚsysÚargvr|   r'   r%   Úis_incrementalr�   µ   s'   € ÜŒs�x‰x‹=˜1ÑÒ=¤§¡¨!¡°Ñ!=Ð=r'   c                  óê  — t        «       } t        dj                  t        | t        «      «       g }t        dt        dz   «      D ]Ÿ  }|dk(  rt        t        z   dz   }ndj                  t        t        z   |«      }t        dj                  ||«      «       	 t        |«      }t        |«      }t        dj                  t        |«      «      «       |s n|j                  |«       Œ¡ t        dj                  t        |«      «      «       |st        d	«       y | rœt        j                  «       t        t         ¬
«      z
  }t        dj                  |j#                  «       «      «       |D ��	�
cg c]  \  }}	}
|
sŒ
t%        |
|«      sŒ||	|
f‘Œ }}	}}
|}t        dj                  t        |«      «      «       g }t'        |«      D ]‡  \  }\  }}}t        dj                  |dz   t        |«      |d d «      «       	 t        |«      }t+        ||«      }|d   s||d<   |d   s||d<   t-        |d   |d   |«      |d<   |j)                  |«       Œ‰ t        dj                  t        |«      «      «       |st        d«       y t/        j0                  dddd¬«      }dj                  t        t        |«      «      }|D ]X  }|d   |d   |d   |d   t        |d   |j3                  dg «      dœ}|j5                  t7        j8                  |d¬«      d z   «       ŒZ |j;                  «        t        d!j                  |j<                  «      «       t?        j@                  d"j                  |j<                  |«      «      }|d#k(  rt        d$«       n/t        d%j                  |«      «       tC        jD                  d«       	 t?        jF                  |j<                  «       y # t        $ r%}t        dj                  |«      «       Y d }~�Œ»d }~ww xY wc c}
}	}w # t        $ rL}t        dj                  |«      «       |j)                  ||dj                  ||«      g |dœ«       Y d }~�Œœd }~ww xY w# tH        $ r Y y w xY w)&Nz2[{}] Starting crawl (incremental={}, max_pages={})rE   z.jhtmlz{}_{}.jhtmlz  Fetching page {}: {}z    ERROR: {}z    Found {} itemsz
  Total items from list: {}z  No items found, exiting)Údaysz  Incremental mode: cutoff = {}z$  After incremental filter: {} itemsz  [{}/{}] Fetching: {}...é(   rs   r^   r0   r@   rJ   z
  Total valid items: {}z  No items to import, exitingÚwz.jsonlFz/tmp)ÚmodeÚsuffixÚdeleteÚdiru
   {} ({}æ�¡)r`   r_   )r0   Úpage_urlrJ   Úpublish_dateÚ	site_namer`   r_   )Úensure_asciiú
z  JSONL written: {}z3python3 /root/gov_crawler/import_jsonl.py '{}' '{}'r   z  OK Import completez  FAIL Import failed (exit={}))%r�   Úprintr   Ú	SITE_NAMEÚ	MAX_PAGESÚranger<   Ú	LIST_PATHr&   r   rA   r~   Úextendr   Únowr   ÚINCREMENTAL_DAYSr@   Ú_date_filterÚ	enumerater=   rp   rŠ   ÚtempfileÚNamedTemporaryFiler9   ÚwriteÚjsonÚdumpsÚcloserG   ÚosÚsystemr�   ÚexitÚunlinkÚOSError)rŒ   Ú	all_itemsÚpager˜   r$   Úer?   Úcutoff_dateÚtÚuÚdÚfilteredÚresultsÚidxr0   r!   Údate_from_listÚdetailÚtmpÚlabelr#   ÚlineÚrets                          r%   ÚmainrÂ   ¹   s  € Ü Ó"€KÜ	Ð
>×
EÑ
EÄiÐQ\Ô^gÓ
hÔið €IÜ�aœ Q™Ó'ò  ˆØ�1Š9Ü¤)Ñ+¨hÑ6‰Hà$×+Ñ+¬H´yÑ,@À$ÓGˆHäÐ&×-Ñ-¨d°HÓ=Ô>ð	Ü˜“?ˆDô ˜4Ó ˆÜÐ"×)Ñ)¬#¨e«*Ó5Ô6ÙÙØ×Ñ˜Õð! ô$ 
Ð
)×
0Ñ
0´°Y³Ó
@ÔAÙÜÐ)Ô*Øñ Ü—l‘l“n¤yÔ6FÔ'GÑGˆÜÐ/×6Ñ6°{×7GÑ7GÓ7IÓJÔKØ-6×]Ð]¡' ! Q¨º!ÄÈQÐP[Õ@\�Q˜˜1’IÐ]ˆÒ]Øˆ	ÜÐ4×;Ñ;¼CÀ	»NÓKÔLð €GÜ-6°yÓ-Aò Ñ)ˆÑ)ˆe�S˜.ÜÐ)×0Ñ0°°q±¼#¸i».È%ÐPSÐQSÈ*ÓUÔVð		Ü˜“:ˆDô ˜d CÓ(ˆØ�gŠØ#ˆF�7‰OØ�fŠ~Ø+ˆF�6‰Nä*¨6°)Ñ+<¸fÀW¹oÈsÓSˆˆyÑØ�‰�vÕð)ô, 
Ð
%×
,Ñ
,¬S°«\Ó
:Ô;ÙÜÐ-Ô.Øô ×
%Ñ
%¨3°xÈÐSYÔ
Z€CØ×Ñ¤	¬3¨w«<Ó8€EØò 
?ˆà�w‘ZØ˜,™Ø˜‘|Ø˜f™IÜ"Ø˜L™/ØŸ5™5 °Ó3ñ
ˆð 	�	‰	”$—*‘*˜T°Ô6¸Ñ=Õ>ð
?ð ‡I�I„KÜ	Ð
×
&Ñ
& s§x¡xÓ
0Ô1ô �)‰)ÐI×PÑPÐQT×QYÑQYÐ[`ÓaÓ
b€CØ
ˆa‚xÜÐ$Õ%äÐ.×5Ñ5°cÓ:Ô;Ü�‰�ŒðÜ
�	‰	�#—(‘(Õøô[ ò 	Ü�/×(Ñ(¨Ó+Ô,Ýûð	üô$ ^øô ò 	Ü�/×(Ñ(¨Ó+Ô,Ø�N‰NØ¨Ø%×,Ñ,¨U°CÓ8Ø!°ñô õ
 ûð	ûôd ò ÙðúsU   ÂOÅ,PÅ8PÆPÇ8PÎ6Q& Ï	PÏO?Ï?PÐ	Q#ÐAQÑQ#Ñ&	Q2Ñ1Q2c                 óX   — 	 t        j                  | d«      }||k\  S # t        $ r Y yw xY w)Nz%Y-%m-%dT)r   ÚstrptimeÚ
ValueError)Údate_strÚcutoffr¸   s      r%   r¥   r¥     s5   € ðÜ×Ñ˜h¨
Ó3ˆØ�F‰{ÐøÜò Ùðús   ‚ �	)¨)Ú__main__)Ú__doc__r­   ra   rª   r�   r   r§   r   r   Úbs4r   r<   ÚCHANNELr   r¡   Ú
RESOLVE_IPrž   r¤   rŸ   ÚPER_PAGEr   r&   rA   rp   rŠ   r�   rÂ   r¥   Ú__name__r|   r'   r%   ú<module>rÏ      s·   ðñ÷ /× .× .ß (Ý à'€Ø
€Ø× Ñ  Ó)€	Ø€
Ø3€	ØÐ Ø€	Ø€ð ˆD�$Ð+¨T°<ÀØÐ*¨ZÑ7ØÐ
{Øð	€	òòò6=ò@,ò^>ò^òBð ˆzÒÙ…Fð r'   