Ë
    €Ûµ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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d
dœZdZdZdZdZdZddd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 å�¯ä¸œå¸‚äººæ°‘æ”¿åºœ - å…¬å‘Šå…¬ç¤º (qidong.gov.cn)
CMS: TrueCMS with jPage client-side pagination
List: div#initData (inline) + API /truecms/messageController/getMessage.do
Detail: div#zoom.content > p, h2 title, div.tips date

Usage:
    python3 /root/gov_crawler/crawl_qidong_gggs.py             # Full crawl
    python3 /root/gov_crawler/crawl_qidong_gggs.py --max-items 15  # Incremental
é    N)Údatetime)ÚBeautifulSoup)Úurljoinz/root/search.dbu"   å�¯ä¸œå¸‚äººæ°‘æ”¿åºœ-å…¬å‘Šå…¬ç¤ºu   å…¬å‘Šå…¬ç¤ºu   æ±Ÿè‹�z/http://www.qidong.gov.cn/qdsrmzf/gggs/gggs.htmlzoMozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36)ú
User-AgentÚRefererz@http://www.qidong.gov.cn/truecms/messageController/getMessage.doz$485473dc-7534-4359-be92-06cc7252f718zwww.qidong.gov.cnéw   é   z?text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8zzh-CN,zh;q=0.9,en;q=0.8)r   ÚAcceptzAccept-Languagec                 ó0  ‡— g }| j                  dd«      j                  dd«      }t        |d«      }|j                  dd¬«      D ]Ô  }|j                  d«      }|sŒ|j                  d	«      }|j                  d
d¬«      }|r|j	                  d«      sŒO|d   j                  «       }	|j                  d¬«      }
t        j                  dd|
«      j                  «       }
t        ||	«      Š|r|j                  d¬«      nd}|
sŒ¾‰sŒÁ|j                  |
‰|f«       ŒÖ |j                  d«      D ]æ  }|j                  d	«      }|r|j	                  d«      sŒ(|d   j                  «       }	t        ||	«      Št        ˆfd„|D «       «      rŒ\|j                  d¬«      }
t        j                  dd|
«      j                  «       }
|j                  d
«      xs |j                  d«      }|r|j                  d¬«      nd}|
sŒÐ‰sŒÓ|j                  |
‰|f«       Œè |S )Nz	<![CDATA[Ú z]]>úhtml.parserÚulzlist-ul©Úclass_ÚliÚaÚiÚtimedateÚhrefT©Ústripz
\.{3,}\s*$c              3   ó.   •K  — | ]  }|d    ‰k(  –— Œ y­w)é   N© )Ú.0r   Úpage_urls     €ú&/root/gov_crawler/crawl_qidong_gggs.pyú	<genexpr>z(parse_items_from_html.<locals>.<genexpr>I   s   øè ø€ Ò/ Aˆq�‰t�xÕÑ/ùs   ƒÚspan)Úreplacer   Úfind_allÚfindÚgetr   Úget_textÚreÚsubr   ÚappendÚany)Úhtml_fragmentÚbase_urlÚitemsÚcleanedÚsoupr   r   r   Údate_ir   ÚtitleÚdate_strÚdate_tagr   s                @r   Úparse_items_from_htmlr2   ,   sã  ø€ Ø€Eà×#Ñ# K°Ó4×<Ñ<¸UÀBÓG€GÜ˜ -Ó0€Dà�m‰m˜D¨ˆmÓ3ò 6ˆØ�W‰W�T‹]ˆÙØØ�G‰G�C‹LˆØ—‘˜ Z�Ó0ˆÙ˜Ÿ™˜fœØØ�‰y�‰Ó ˆØ—
‘
 �
Ó&ˆÜ—‘�} b¨%Ó0×6Ñ6Ó8ˆÜ˜8 TÓ*ˆÙ28�6—?‘?¨�?Ô.¸bˆÚ’XØ�L‰L˜% ¨8Ð4Õ5ð6ð  �m‰m˜DÓ!ò 6ˆØ�G‰G�C‹LˆÙ˜Ÿ™˜fœØà�‰y�‰Ó ˆÜ˜8 TÓ*ˆÜÓ/¨Ô/Ô/ØØ—
‘
 �
Ó&ˆÜ—‘�} b¨%Ó0×6Ñ6Ó8ˆà—7‘7˜3“<Ò2 2§7¡7¨6£?ˆÙ4<�8×$Ñ$¨4Ð$Ô0À"ˆÚ’XØ�L‰L˜% ¨8Ð4Õ5ð6ð  €Ló    c                 óŽ  — | dz
  t         z  }|t         z   dz
  }||t         t        dœ}	 t        j                  t        |t
        d¬«      }|j                  dk(  r4|j                  «       }|j                  dd«      }|rt        |t        «      S g S # t        $ r,}t        d| › d	|› �t        j                  ¬
«       Y d }~g S d }~ww xY w)Nr   )ÚstartrecordÚ	endrecordÚperpageÚcolumnIdé   )ÚparamsÚheadersÚtimeoutéÈ   Úresultr   z  Error fetching API page ú: ©Úfile)ÚPER_PAGEÚAPI_COLUMN_IDÚrequestsr#   ÚAPI_URLÚAPI_HEADERSÚstatus_codeÚjsonr2   ÚLIST_URLÚ	ExceptionÚprintÚsysÚstderr)Úpage_numr5   r6   r:   ÚrÚdataÚhtmlÚes           r   Úfetch_api_pagerS   U   sÂ   € Ø˜a‘<¤8Ñ+€KØœhÑ&¨Ñ*€Ià"ØÜÜ!ñ	€FðMÜ�L‰Lœ¨¼ÈbÔQˆØ�=‰=˜CÒØ—6‘6“8ˆDØ—8‘8˜H bÓ)ˆDÙÜ,¨T´8Ó<Ð<ð €Iøô ò MÜÐ*¨8¨*°B°q°cÐ:ÄÇÁ×LÑLØ€IûðMús   ©A#B Â	CÂ!B?Â?Cc                  ó8  — g } 	 t        j                  t        t        d¬«      }d|_        t        |j                  d«      }|j                  dd¬	«      }|r(| j                  t        t        |«      t        «      «       t        | «      }d
}|t         k  rPt#        |«      }|s	 | S | j                  |«       t        | «      }|dz  }t%        j&                  d«       |t         k  rŒP| S # t
        $ r*}t        d|› �t        j                  ¬«       | cY d }~S d }~ww xY w)Nr9   ©r;   r<   úutf-8z  Error fetching list: r@   r   ÚdivÚinitData©Úidé   r   g333333Ó?)rD   r#   rI   ÚHEADERSÚencodingrJ   rK   rL   rM   r   Útextr"   Úextendr2   ÚstrÚlenÚTOTAL_ITEMSrS   ÚtimeÚsleep)r+   rO   rR   r-   Ú	init_dataÚtotal_loadedrN   Ú	api_itemss           r   Úextract_all_itemsrh   j   sü   € Ø€EðÜ�L‰Lœ¬7¸BÔ?ˆØˆŒ
ô
 ˜Ÿ™ Ó/€DØ—	‘	˜% J�	Ó/€IÙØ�‰Ô*¬3¨y«>¼8ÓDÔEô �u“:€LØ€HØ
œÒ
$Ü" 8Ó,ˆ	ÙØð €Lð 	�‰�YÔÜ˜5“zˆØ�A‰ˆÜ�
‰
�3Œð œÓ
$ð €Løô+ ò ÜÐ'¨ sÐ+´#·*±*Õ=Ø�ûðús   „'C& Ã&	DÃ/DÄDÄDc                 óÌ  — 	 t        j                  | t        d¬«      }d|_        t        |j                  d«      }d}|j                  d	d
¬«      }d }|r|j                  d«      }|s|j                  d«      }|r|j                  d¬«      }d}|j                  d	d¬«      }|r7t        j                  d|j                  «       «      }	|	r|	j                  d«      }d}
|rw|j!                  ddg«      D ]  }|j#                  «        Œ g }|j!                  d«      D ](  }|j                  d¬«      }|sŒ|j%                  |«       Œ* dj'                  |«      }
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|j1                  |«       |j%                  ||dœ«       |
sŒ¡|
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)#Nr9   rU   rV   z  fetch_detail error r?   r@   r   r   rW   ÚzoomrY   Úh2Tr   Útipsr   z(\d{4}-\d{2}-\d{2})r   ÚscriptÚstyleÚpz

r   )r   r   z&\.(pdf|doc|docx|xls|xlsx|rar|zip|txt)$ú/éÿÿÿÿú?r   )ÚnameÚurlu   

é™„ä»¶ï¼š<p><a href="z">z</a></p>)rD   r#   r\   r]   rJ   rK   rL   rM   r   r^   r"   Úfind_previous_siblingr$   r%   ÚsearchÚgroupr!   Ú	decomposer'   ÚjoinÚsetÚIr   ÚsplitÚadd)rt   rO   rR   r-   r/   rj   rk   r0   rl   ÚmÚcontentÚsÚpartsro   ÚtÚattachmentsÚseenr   r   Úfull_urlrs   s                        r   Úfetch_detailr†   ‹   s_  € ð$Ü�L‰L˜¤g°rÔ:ˆØˆŒ
ô
 ˜Ÿ™ Ó/€Dð €EØ�9‰9�U˜vˆ9Ó&€DØ	€BÙØ×'Ñ'¨Ó-ˆÙØ�Y‰Y�t‹_ˆÙ	Ø—‘ $�Ó'ˆð €HØ�9‰9�U 6ˆ9Ó*€DÙÜ�I‰IÐ,¨d¯m©m«oÓ>ˆÙØ—w‘w˜q“zˆHð €GÙØ—‘ ¨'Ð2Ó3ò 	ˆAØ�K‰K�Mð	àˆØ—‘˜sÓ#ò 	 ˆAØ—
‘
 �
Ó&ˆAÚØ—‘˜Q•ð	 ð —+‘+˜eÓ$ˆð €KÜ‹5€DØ�]‰]˜3 Tˆ]Ó*ò 	VˆØ�‰yˆÜ�9‰9Ð>ÀÄbÇdÁdÕKÜ˜s DÓ)ˆHØ—:‘: D�:Ó)ÒN¨T¯Z©Z¸«_¸RÑ-@×-FÑ-FÀsÓ-KÈAÑ-NˆDØ˜tÒ#Ø—‘˜Ô"Ø×"Ñ"¨D¸Ñ#BÔCÚØÐ!:¸8¸*ÀBÀtÀfÈHÐUÑU‘Gð	Vð �(˜G [Ð0Ð0øôg ò $ÜÐ% c U¨"¨Q¨CÐ0´s·z±zÕBØ�T˜4 Ð#Õ#ûð$ús   ‚#H) È)	I#È2&IÉI#ÉI#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)Nr   Úlockedz  z: locked (attempt rp   z), retry in zs...r@   z	 failed: F)	ÚrangeÚsqlite3ÚOperationalErrorr`   rK   rL   rM   rc   rd   )ÚfnÚdescÚmax_attemptsÚdelayÚattemptrR   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é   )r<   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Ð,Ô-Ø€Kr3   c                 óˆ  — |r|d d 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)Nr=   z\s+ú 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: r@   )r%   r&   r   rH   Údumpsr–   Ú	SITE_NAMEÚCATEGORYÚGROUPÚrowcountrJ   rK   rL   rM   )
r˜   r/   r   Úpublish_dater   rƒ   ÚsummaryÚatt_jsonÚcurrR   s
             r   Úsave_articler¦   Ü   s´   € Ù&ˆg�d�s‰m¨E€GÜ�f‰f�V˜S 'Ó*×0Ñ0Ó2€GÙ>IŒt�z‰z˜+°EÕ:Èt€HðØ�l‰lð8ô ˜ (¨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}ˆfd„}t        |d	t        › �¬
«       t        dt        › �t        j                  ¬«       t        «       }|st        dt        j                  ¬«       y t        |«      }t        d|› d�t        j                  ¬«       t        |d |  «      D ]Ò  \  }\  }}}|r|dk  rŒ‰j                  d|f«      }	|	j                  «       rŒ6t        |«      \  }
}}}|
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                  ¬«       |dz   dz  dk(  r‰j#                  «        t%        j&                  d«       ŒÔ ‰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 �ŒMw xY w)Nr   )z--max-itemsr[   z	Scraping z, max items: r@   r   c                  ó&   •— ‰ j                  «        y )N)Úcommitr—   s   €r   Údo_cleanzmain.<locals>.do_clean   s   ø€ à�‰�r3   zClean )r�   z  Cleaned old data for z  No items found!z  Found z itemsz
2020-01-01z)SELECT id FROM gov_raw WHERE page_url = ?ú[z](ú)é   z  + r›   é2   é
   g      à?z
Done! Found: z, New: )rb   ra   rL   ÚargvÚintÚ
ValueErrorrK   rž   rM   r™   r‘   rh   Ú	enumerater–   Úfetchoner†   r¦   r©   rc   rd   Úclose)Ú	max_itemsÚ	total_newrª   Ú	all_itemsÚtotal_foundÚidxr/   r   Údater¥   Ú	det_titleÚdet_dateÚdet_contentÚdet_attsÚfinal_titleÚ
final_dateÚfinal_contentÚ
final_attsr˜   s                     @r   ÚmainrÄ   ð   sS  ø€ Ü€IÜ
Œ3�8‰8ƒ}�qÒð	ÜœCŸH™H Q™KÓ(ˆIô 
ˆI”i�[ ¨i¨[Ð
9ÄÇ
Á
ÕKÜ‹9€DØ€Iôô ˆx ¤y kÐ2Õ3Ü	Ð#¤I ;Ð
/´c·j±jÕAä!Ó#€IÙÜÐ!¬¯
©
Õ3Øä�i“.€KÜ	ˆH�[�M Ð
(¬s¯z©zÕ:ä(1°)¸J¸YÐ2GÓ(Hò Ñ$ˆÑ$ˆe�X˜tÙ�D˜<Ò'ØØ�l‰lÐFÈÈÓTˆØ�<‰<Œ>Øä5AÀ(Ó5KÑ2ˆ	�8˜[¨(ØÒ( 5ˆØÒ% ˆ
Ø#ÒE¨¨;¨-°r¸(¸À1Ð'EˆØ’^ ˆ
ä˜˜k¨8°ZÀÐPZÔ[Ø˜‰NˆIØ˜AŠ~Ü˜˜Z˜L¨¨+°c°rÐ*:Ð);Ð<Ä3Ç:Á:ÕNà�!‰G�r‰>˜QÒØ�K‰KŒMÜ�
‰
�3�ð)ð, 	‡K�K„MØ‡J�J„LÜ	ˆO˜K˜=¨°	¨{Ð
;Ä#Ç*Á*ÖMøôc ò 	Ü�x‰x˜‰{Ð.Ñ.´3´s·x±x³=À1Ò3DðÜ #¤C§H¡H¨Q¡KÓ 0‘IøÜ!ò Ùðýð		ús5   ¥H$ È$:JÉI<É;JÉ<	JÊJÊJÊJÊJÚ__main__)zDB opr¯   r­   )"Ú__doc__rD   r%   rH   rŠ   rc   ÚosrL   r   Úbs4r   Úurllib.parser   r•   rž   rŸ   r    rI   rF   rE   rC   ÚBASE_DOMAINrb   rB   r\   r2   rS   rh   r†   r‘   r™   r¦   rÄ   Ú__name__r   r3   r   ú<module>rÌ      sº   ðñ	÷ 2× 1× 1Ó 1Ý Ý Ý  à
€Ø0€	Ø€Ø€Ø<€ð DØ@ñ€ð
 M€Ø6€Ø!€Ø€Ø€ð DØOØ0ñ€ò&òRò*òB71óxòòò(6Nðr ˆzÒÙ…Fð r3   