Ë
    ¸¬ujŽ$  ã            
       ó”  — 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
  ej                  dd«      ZdZdZd	Zd
ZdZdZdZdZdZ ej,                  «        ed¬«      z
  j/                  d«      ZdZd„ Zd„ Zd„ Zd„ Zd„ Zd„ Zd„ Z d1d„Z!d„ Z"e#dk(  �r- e$ejJ                  «      dkD  rejJ                  d   ndZ&e&dk(  r e"«        ye&d k(  rZ e$ejJ                  «      dkD  rejJ                  d   nd!Z'e'd"k(  r
 e!d#¬$«       ye're'jQ                  «       r e)e'«      ndZ* e!e*«       ye&d%k(  r• ee› d&e› d'e› �«      Z+e+re+jY                  d(g «      ng Z- ed) e$e-«      › d*�«       e-dd+ D ]T  Z. ej^                  e.jY                  d,d«      «      j/                  d«      Z0 e1d-e0› d.e.jY                  d/d!«      dd0 › �«       ŒV yyy)2u`   
Crawler: æ¢…å·žå¸‚å…´å®�å¸‚å�¶å¡˜é•‡äººæ°‘æ”¿åºœ - å…¶ä»– (gkmlpt)
API: Lonsun gkmlpt platform
é    N)ÚdatetimeÚ	timedelta)ÚBeautifulSoupÚ	SEARCH_DBz/root/search.dbu   å…´å®�å¸‚å�¶å¡˜é•‡u   å…¶ä»–u   å¹¿ä¸œi9   zhttps://www.xingning.gov.cnz$http://www.xingning.gov.cn/mzxnytzzfÚ753152é   é   iG  ©Údaysú%Y-%m-%d)z.docz.docxz.pdfz.xlsz.xlsxz.pptz.pptxz.zipz.rarz.7zz.tarz.gzz.txtzdownfile.jspzdownload.jspÚdownfileÚdownloadc                 ó2   — t        dt        › d| › �d¬«       y )Nú[z] T)Úflush)ÚprintÚSITE)Úmsgs    ú*/root/gov_crawler/crawl_xingning_yetang.pyÚlogr      s   € Ü	ˆAŒdˆV�2�c�UÐ
 4Ö(ó    c           	      óÊ   — 	 t        j                  dddddd| gddd¬	«      }t        j                  |j                  «      S # t
        $ r}t        d
|› �«       Y d}~yd}~ww xY w)z*Fetch API endpoint and return parsed JSON.Úcurlú-sLú
--max-timeÚ15ú-AúMozilla/5.0Té   ©Úcapture_outputÚtextÚtimeoutzAPI error: N)Ú
subprocessÚrunÚjsonÚloadsÚstdoutÚ	Exceptionr   )ÚurlÚrÚes      r   Ú
fetch_jsonr-       se   € ðÜ�N‰NØ�U˜L¨$°°mÀSÐIØ d°Bô
ˆô �z‰z˜!Ÿ(™(Ó#Ð#øÜò Üˆk˜!˜ÐÔÜûðús   ‚>A Á	A"Á
AÁA"c           	      óþ  — 	 t        j                  dddddd| gddd¬	«      }|j                  }|j                  d«      }|dk  ry|j                  d|dz   «      }|dk  ryd}t        |t        |«      «      D ]C  }||   dk(  r|dz  }Œ||   dk(  sŒ|dz  }|dk(  sŒ%|||dz    }	 t        j                  |«      c S  y# t        $ r}t	        d
| › d|› �«       Y d}~yd}~ww xY w# t        j                  $ r Y  yw xY w)zBFetch a detail page and extract DETAIL.content from the JS config.r   r   r   r   r   r   Tr   r    zFetch error for z: NzDETAIL:r   ú{é   r	   ú})r$   r%   r(   r)   r   ÚfindÚrangeÚlenr&   r'   ÚJSONDecodeError)	r*   r+   Úhtmlr,   ÚidxÚ	obj_startÚdepthÚiÚ
detail_strs	            r   Ú
fetch_htmlr<   -   s,  € ðÜ�N‰NØ�U˜L¨$°°mÀSÐIØ d°Bô
ˆð �x‰xˆð �)‰)�IÓ
€CØ
ˆQ‚wØà—	‘	˜#˜s Q™wÓ'€IØ�1‚}Øà€EÜ�9œc $›iÓ(ò 
 ˆØ�‰7�cŠ>Ø�Q‰J‰EØ�!‰W˜‹^Ø�Q‰JˆEØ˜‹zØ! )¨A¨a©CÐ0�
ð ÜŸ:™: jÓ1Ò1ð
 ð øô3 ò ÜÐ˜s˜e 2 a SÐ)Ô*Üûðûô. ×+Ñ+ò  Úð ús)   ‚,B> Â%C%Â>	C"ÃCÃC"Ã%C<Ã;C<c                 óZ  ‡— | j                  dd«      xs d}|j                  «       syt        |d«      }g }|j                  dd¬«      D ]«  }|j                  dd«      Š|j	                  d¬	«      xs d
}‰j                  d«      r‰nt        ‰z   }t        ˆfd„t        D «       «      r3d|› d|› d�}	|j                  |	«       |j                  d|› d|› d�«       Œ’d|› d|› d�}	|j                  |	«       Œ­ |j                  g d¢«      D ]  }
|
j                  «        Œ g }|j                  d«      D ])  }|j	                  dd¬«      }|sŒ|j                  |«       Œ+ |rdj                  |«      n|j                  «       }|rdj                  |«      nd}|r|r|d|z   z  }||fS |}||fS )z/Extract clean text and attachments from DETAIL.ÚcontentÚ )r?   r?   zhtml.parserÚaT)ÚhrefrA   )Ústripu   é™„ä»¶Úhttpc              3   óB   •K  — | ]  }|‰j                  «       v –— Œ y ­w)N)Úlower)Ú.0ÚextrA   s     €r   ú	<genexpr>z"extract_content.<locals>.<genexpr>_   s   øè ø€ Ò: sˆs�d—j‘j“lÔ"Ñ:ùs   ƒr   z](ú))ÚspanÚbÚstrongÚfontÚemr:   ÚuÚsÚp)Ú	separatorrB   z

ú | )ÚgetrB   r   Úfind_allÚget_textÚ
startswithÚBASE_URLÚanyÚATTACH_EXTSÚreplace_withÚappendÚunwrapÚjoin)ÚdetailÚpage_urlÚtitleÚcontent_htmlÚsoupÚattachmentsÚa_tagr"   Úfull_urlÚmd_linkÚtagÚ
paragraphsrQ   r>   Úatt_strrA   s                  @r   Úextract_contentrk   Q   sÉ  ø€ à—:‘:˜i¨Ó,Ò2°€LØ×ÑÔØä˜ }Ó5€DØ€Kð —‘˜s¨�Ó.ò 
(ˆØ�y‰y˜ Ó$ˆØ�~‰~ Dˆ~Ó)Ò5¨XˆØŸ?™?¨6Ô2‘4¼À4¹ˆÜÓ:¬kÔ:Ô:Ø˜$˜˜r ( ¨1Ð-ˆGØ×Ñ˜wÔ'Ø×Ñ  4 &¨¨8¨*°AÐ6Õ7à˜$˜˜r ( ¨1Ð-ˆGØ×Ñ˜wÕ'ð
(ð �}‰}ÒQÓRò ˆØ�
‰
�ðð €JØ�]‰]˜3Óò $ˆØ�z‰z B¨dˆzÓ3ˆÚØ×Ñ˜dÕ#ð$ñ
 *4ˆf�k‰k˜*Ô%¸×9KÑ9KÓ9M€GÙ)4ˆe�j‰j˜Ô%¸"€GÙÙØ�v Ñ'Ñ'ˆGð �GÐÐð ˆGà�GÐÐr   c                 óÒ  — g }t        «       }|rt        j                  |d«      nd}t        | |dz   «      D �]ž  }t        › dt
        › d|› dt        › �}t        |«      }|st        d|› d�«        |S |j                  d	g «      }	|	st        d|› d
�«        |S d}
|	D ]ö  }|j                  dd«      }|sŒ|j                  d«      r	t        |z   }||v rŒ7|j                  |«       |j                  dd«      }|r't        j                  |«      }|j                  d«      }nd}|r |r	 t        j                  |d«      }||k  rŒ¦	 |j                  dd«      xs dj!                  «       }|rt#        |«      dk  rŒÜ|j%                  ||||dœ«       |
dz  }
Œø t        d|› d|
› dt#        |«      › d�«       |
dk(  r|| kD  r |S t'        j(                  d«       �Œ¡ |S # t        $ r Y Œ¢w xY w)z)Crawl a range of API pages, dedup by URL.r   Nr	   ú/gkmlpt/api/all/z?page=z&sid=z  Page z: no data, stoppingÚarticlesz: no articles, stoppingr   r*   r?   ú/Údatera   é   )ra   r*   rp   Útsz: +z new (total rI   g      à?)Úsetr   Ústrptimer3   ÚAPP_BASEÚCATEGORY_IDÚSIDr-   r   rT   rW   rX   ÚaddÚfromtimestampÚstrftimeÚ
ValueErrorrB   r4   r\   ÚtimeÚsleep)Ú
start_pageÚend_pageÚcutoffÚ	all_itemsÚ	seen_urlsÚ	cutoff_dtÚpgr*   Údatarn   Ú	new_countr@   r`   rr   ÚdtÚdate_strÚdra   s                     r   Úcrawl_pagesrŠ   }   s=  € à€IÜ“€IÙ9?”×!Ñ! &¨*Ô5ÀT€Iä�J ¨1¡Ó-ó 8ˆÜ�
Ð*¬;¨-°v¸b¸TÀÄsÀeÐLˆÜ˜#‹ˆÙÜ�'˜"˜Ð0Ð1Ô2Øðj Ððg —8‘8˜J¨Ó+ˆÙÜ�'˜"˜Ð4Ð5Ô6Øð` Ðð] ˆ	Øò &	ˆAØ—u‘u˜U BÓ'ˆHÙØØ×"Ñ" 3Ô'Ü# hÑ.�ð ˜9Ñ$ØØ�M‰M˜(Ô#ð —‘�v˜qÓ!ˆBÙÜ×+Ñ+¨BÓ/�ØŸ;™; zÓ2‘à�á™XðÜ ×)Ñ)¨(°JÓ?�AØ˜9’}Ø ð %ð
 —U‘U˜7 BÓ'Ò-¨2×4Ñ4Ó6ˆEÙœC ›J¨šNØà×ÑØØØ Øñ	ô ð ˜‰N‰IðM&	ôP 	ˆg�b�T˜˜Y˜K |´C¸	³NÐ3CÀ1ÐEÔFØ˜Š>˜b :šoØð Ðô 	�
‰
�3Žðq8ðt Ðøô) "ò Ùðús   Ä&GÇ	G&Ç%G&c                 óŒ  — t        dt        | «      › d�«       g }t        | d«      D ]š  \  }}t        |d   «      }|rt	        ||d   |d   «      \  }}nd}d}|j                  |d   |d   |d   ||t        › dt        › �t        d	œ«       |d
z  dk(  rt        d|› dt        | «      › �«       t        j                  d«       Œœ |S )z'Fetch detail pages and extract content.z
Fetching details for z	 items...r	   r*   ra   r?   rp   ú-)ra   r`   Úpublish_dater>   rd   Ú	site_nameÚcolumné
   r   z  Progress: ro   g333333Ó?)
r   r4   Ú	enumerater<   rk   r\   r   ÚCOLUMNr|   r}   )r�   Úenrichedr7   Úitemr_   r>   rd   s          r   Úprocess_detailsr•   À   sä   € äÐ
!¤# i£.Ð!1°Ð;Ô<Ø€HÜ˜y¨!Ó,ò ‰	ˆˆTÜ˜D ™KÓ(ˆÙÜ#2°6¸4À¹;ÈÈWÉÓ#VÑ ˆG‘[àˆGØˆKà�‰Ø˜'‘]Ø˜U™Ø  ™LØØ&Ü ˜6 ¤6 (Ð+Üñ
ô 	ð �‰8�qŠ=Ü�,˜s˜e 1¤S¨£^Ð$4Ð5Ô6Ü�
‰
�3�ð)ð, €Or   c                 óð  — ddl }|j                  t        «      }|j                  d«       |j                  d«       |j	                  «       }d}d}| D ]V  }	 |j                  d|d   |d   |d   |d   |d	   |d
   |d
   xs ddd |d   f«       |j
                  dkD  r|dz  }n|dz  }ŒX |j                  «        |j                  «        ||fS # t        $ r}t        d|› �«       |dz  }Y d}~Œžd}~ww xY w)zInsert items into search.db.r   NzPRAGMA journal_mode=WALzPRAGMA busy_timeout=10000z‰INSERT OR IGNORE INTO gov_raw (site_name, source_url, page_url, title, publish_date, content, summary, category) VALUES (?,?,?,?,?,?,?,?)rŽ   r`   ra   r�   r>   r?   iô  r�   r	   z  DB error: )
Úsqlite3ÚconnectÚDB_PATHÚexecuteÚcursorÚrowcountr)   r   ÚcommitÚclose)Úitemsr—   ÚconnÚcr†   Ú
skip_countr”   r,   s           r   Ústore_itemsr£   Ý   s  € ãØ�?‰?œ7Ó#€DØ‡L�LÐ*Ô+Ø‡L�LÐ,Ô-Ø�‰‹€Aà€IØ€JØò ˆð	Ø�I‰Ið,ð ˜Ñ%Ø˜Ñ$Ø˜Ñ$Ø˜‘MØ˜Ñ(Ø˜‘OØ˜)‘_Ò*¨¨D¨SÐ1Ø˜‘Nð	ô	ð �z‰z˜AŠ~Ø˜Q‘‘	à˜a‘�
øð)ð2 	‡K�K„MØ‡J�J„LØ�jÐ Ð øô ò 	Ü�,˜q˜cÐ"Ô#Ø˜!‰O�Jûð	ús   ÁACÃ	C5ÃC0Ã0C5é$   c                 óð   — t        j                  «       t        | dz  ¬«      z
  j                  d«      }t	        d«       t        dd|«      }t        |«      }t        |«      \  }}t	        d|› d|› d�«       y	)
z3New site initial: crawl API pages for initial data.é   r
   r   z$Strategy: initial crawl (first page)r   zResult: ú new, ú skippedN©r   Únowr   rz   r   rŠ   r•   r£   )Úmonths_backr€   rŸ   r“   ÚnewÚskips         r   Ú	crawl_allr®     sm   € ä�l‰l‹nœy¨k¸BÑ.>Ô?Ñ?×IÑIÈ*ÓU€FÜÐ
.Ô0Ü˜˜1˜fÓ%€EÜ˜uÓ%€HÜ˜HÓ%�I€CˆÜˆ(�3�%�v˜d˜V 8Ð,Õ-r   c                  óê   — t        j                  «       t        d¬«      z
  j                  d«      } t	        d«       t        dd| «      }t        |«      }t        |«      \  }}t	        d|› d|› d�«       y	)
z8Daily: fetch page 0, filter recent items, fetch details.r0   r
   r   zIncremental: last 7 daysr   zIncremental result: r§   r¨   Nr©   )r€   rŸ   r“   r¬   r­   s        r   Úcrawl_incrementalr°     si   € ä�l‰l‹nœy¨aÔ0Ñ0×:Ñ:¸:ÓF€FÜÐ
"Ô$Ü˜˜1˜fÓ%€EÜ˜uÓ%€HÜ˜HÓ%�I€CˆÜÐ
˜s˜e 6¨$¨¨xÐ8Õ9r   Ú__main__ÚincrementalÚfullr?   Úalléx   )r«   Úlistrm   z?page=0&sid=rn   zTotal: z	 articlesé   rp   z  rS   ra   é<   )r¤   )2Ú__doc__ÚsysÚosr&   Úrer|   r$   r   r   Úbs4r   Úgetenvr™   r   r’   ÚPROVINCErv   rX   ru   rw   ÚTOTAL_PAGESÚDEFAULT_FULL_PAGESrª   rz   ÚCUTOFF_DATErZ   r   r-   r<   rk   rŠ   r•   r£   r®   r°   Ú__name__r4   ÚargvÚmodeÚarg2ÚisdigitÚintÚmonthsr…   rT   rn   r@   ry   r‡   r   © r   r   ú<module>rË      sû  ðñ÷ +× *× *ß (Ý à
ˆ"�)‰)�KÐ!2Ó
3€Ø€Ø	€Ø€Ø€Ø(€Ø1€Ø€Ø€àÐ Øˆx�|‰|‹~¡	¨uÔ 5Ñ5×?Ñ?À
ÓK€ðG€ò
)ò
ò!òH)òX@òFò:%!óP.ò:ð ˆzÓÙ˜cŸh™h›-¨!Ò+ˆ3�8‰8�AŠ;°€DØˆ}ÒÙÕØ	�ŠÙ! #§(¡(›m¨aÒ/ˆs�x‰x˜Š{°RˆØ�5Š=Ù #Ö&á"&¨4¯<©<¬>‘S˜”Y¸rˆFÙ�fÕØ	�ŠÙ˜X˜JÐ&6°{°mÀ<ÐPSÈuÐUÓVˆÙ/3�4—8‘8˜J¨Ô+¸ˆÙˆg‘c˜(“m�_ IÐ.Ô/Ø˜"˜1�ò 	8ˆAØ'�×'Ñ'¨¯©¨f°aÓ(8Ó9×BÑBÀ:ÓNˆBÙ�B�r�d˜#˜aŸe™e G¨BÓ/°°Ð4Ð5Ð6Õ7ñ	8ð	 
ð r   