Ë
    ­�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	m
Z
 ddlm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d„ Zd„ Zd„ Z d„ Z!dd„Z"e#dk(  r e!«        yy)uA  é‚›å´ƒå¸‚äººæ°‘æ”¿åºœ - çŽ¯è¯„å…¬ç¤ºæ �ç›®çˆ¬è™«
ç«™ç‚¹: https://qionglai.gov.cn (å››å·�æˆ�éƒ½)
æ �ç›®: /qlsgzxxw/hpgs/list.shtml (çŽ¯è¯„å…¬ç¤º, 219æ�¡/11é¡µ)
WAF: ç‘žæ•°4ä»£ JS æŒ‘æˆ˜ (412, $_ts) â†’ Playwright è¿‡æŒ‘æˆ˜; è¯�ä¹¦è¿‡æœŸé¡» ignore_https_errors=True
åˆ—è¡¨: GET /es-search/search/{channeId}?_template=ucap/cdtf&_pageSize=20&page=N
  è¿”å›ž JSON: {total, page, rows, results:[{title, contentHtml(å®žä½“è½¬ä¹‰éœ€unescape), url, publishedTimeStr}]}
  æ­£æ–‡ç”¨ API contentHtml (å®Œæ•´); âš ï¸� é™„ä»¶ä¸�åœ¨ contentHtml ä¸­ â†’ æ¯�æ�¡è¡¥æŠ“è¯¦æƒ…é¡µ div#content æ��å�–
channeId 82b381f29b954d85bb0a2051af47acbd (meta name=column)
å…¥åº“: è‡ªåŠ¨æ£€æµ‹ /root/search.db å­˜åœ¨åˆ™ INSERT OR IGNORE ç›´æ�’ gov_raw (FTS è§¦å�‘å™¨è‡ªåŠ¨å�Œæ­¥ gov_search)
è¿�è¡Œ: python3 crawl_qionglai_hpgs.py [--pages=N] [--no-db] [--sync-only]
é    N)ÚdatetimeÚ	timedelta)Úsync_playwrightu   é‚›å´ƒå¸‚-çŽ¯è¯„å…¬ç¤ºzhttps://qionglai.gov.cnz0https://qionglai.gov.cn/qlsgzxxw/hpgs/list.shtmlÚ 82b381f29b954d85bb0a2051af47acbdé   é   iG  )Údaysz%Y-%m-%dzoMozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36z/tmp/qionglai_hpgs.jsonlz/root/search.dbu   çŽ¯è¯„å…¬ç¤ºc                  óÎ   — t         j                  dd D ]O  } | j                  d«      rt        | j	                  d«      d   «      c S | j                  «       sŒDt        | «      c S  y)u   æ”¯æŒ� --pages=N å’Œçº¯æ•°å­—é   Nz--pages=ú=r   )ÚsysÚargvÚ
startswithÚintÚsplitÚisdigit)Úas    ú(/root/gov_crawler/crawl_qionglai_hpgs.pyÚparse_pages_argr      sU   € ä�X‰X�a�bˆ\ò ˆØ�<‰<˜
Ô#Ü�q—w‘w˜s“| A‘Ó'Ò'Ø�9‰9�;Ü�q“6ŠMð	ð
 ó    c                 óœ   — t        j                  dd| xs d«      j                  «       } | j                  dd«      j                  dd«      } | S )Nu   ^[â€¢Â·Â·\s]+Ú u   â€‹u   ï»¿)ÚreÚsubÚstripÚreplace©Úts    r   Úclean_titler   '   sD   € Ü
�‰Ð  Q¢W¨"Ó-×3Ñ3Ó5€AØ	�	‰	�(˜BÓ×'Ñ'¨°"Ó5€AØ€Hr   c                 ó  — ddl m}  || d«      }|j                  d„ «      D ]  }|j                  «        Œ |j                  ddg«      D ]  }|j	                  «        Œ 	 |j                  d«      D �cg c]  }|j                  d«      sŒ|‘Œ }}|sn|d   j	                  «        ŒG|j                  d«      D ]?  }|j                  d«      sŒ|j                  d	«      rd	|j                  d	«      ini |_        ŒA t        |«      S c c}w )
uL   æ­£æ–‡æ¸…æ´—: span/font unwrap + åµŒå¥—pæ‰�å¹³åŒ– + o:pæ¸…ç�† + ä¿�ç•™è¡¨æ ¼r   )ÚBeautifulSoupzhtml.parserc                 ó:   — | j                   xr d| j                   v S )Nú:)Únamer   s    r   ú<lambda>zclean_content.<locals>.<lambda>0   s   €  q§v¡vÒ'?°#¸¿¹°-€ r   ÚspanÚfontÚpÚstyleÚalign)	Úbs4r!   Úfind_allÚ	decomposeÚunwrapÚfindÚgetÚattrsÚstr)Úhtmlr!   ÚsoupÚtagr(   Únesteds         r   Úclean_contentr7   ,   sø   € å!Ù˜˜}Ó-€DØ�}‰}Ñ?Ó@ò ˆØ�‰�ðà�}‰}˜f fÐ-Ó.ò ˆØ�
‰
�ðð Ø!Ÿ]™]¨3Ó/Ö?˜°1·6±6¸#µ;’!Ð?ˆÐ?ÙØØˆq‰	×ÑÔð	 ð
 �]‰]˜3Óò JˆØ�5‰5��>Ø34·5±5¸´>�w §¡ g£Ñ/ÀrˆA�GðJô ˆt‹9Ðùò @s   Á3DÂ
Dc           
      ód  — dt         › dt        › d|› �}t        d«      D ]D  }	 | j                  dt        |z   «      }t        j                  |j                  dd«      «      }|c S  y
# t        $ r?}t        d|› d	t        |«      d
d › d�d¬«       t        j                  d«       Y d
}~Œ‹d
}~ww xY w)u   es-search API åˆ†é¡µz/es-search/search/z?_template=ucap/cdtf&_pageSize=z&page=é   úAasync (u) => { const r = await fetch(u); return await r.text(); }z&#34;ú"u     APIé¡µu	    å¤±è´¥: NéP   u
    é‡�è¯•...T©Úflushé   )Ú	CHANNE_IDÚ	PAGE_SIZEÚrangeÚevaluateÚBASEÚjsonÚloadsr   Ú	ExceptionÚprintr2   ÚtimeÚsleep)ÚpageÚpnÚapiÚ_ÚbodyÚdataÚes          r   Ú	fetch_apirR   @   s³   € àœy˜kÐ)HÌÈÐSYÐZ\ÐY]Ð
^€CÜ�1‹Xò ˆð	Ø—=‘=Ð!hÔjnÐqtÑjtÓuˆDÜ—:‘:˜dŸl™l¨7°CÓ8Ó9ˆDØŠKð	ð øô ò 	Ü�H˜R˜D 	¬#¨a«&°°"¨+¨°jÐAÈÕNÜ�J‰J�q�M‰Mûð	ús   £?A'Á'	B/Á05B*Â*B/c                 óÀ   — |j                  dt        «      }t        d«      D ]  }	 | j                  d|«      c S  y# t        $ r t        j                  d«       Y Œ:w xY w)ug   fetch è¯¦æƒ…é¡µæ��å�–é™„ä»¶ (API contentHtml ä¸�å�«é™„ä»¶åŒº, é™„ä»¶åœ¨è¯¦æƒ…é¡µ div#content è¡¨æ ¼å†…)zhttp://www.qionglai.gov.cnr9   r:   N)r   rD   rB   rC   rG   rI   rJ   )rK   Ú
detail_urlÚ	fetch_urlrN   s       r   Úfetch_detailrV   M   sa   € à×"Ñ"Ð#?ÄÓF€IÜ�1‹Xò ˆð	Ø—=‘=Ð!hÐjsÓtÒtðð
 øô ò 	Ü�J‰J�qŽMð	ús   ¦<¼AÁAc                 ó  — g }t        j                  d| t         j                  t         j                  z  «      D �]  }|j	                  d«      j                  «       |j	                  d«      }}|r|j                  d«      rŒHt        j                  d|t         j                  «      sŒnt        j                  dd|«      j                  «       dd	 }|j                  d
«      r
t        |z   }n-|j                  d«      rn|j                  d
d«      d   d
z   |z   }|j                  |xs |j                  d
«      d   |dœ«       �Œ
 t        «       }g }|D ]/  }	|	d   |vsŒ|j                  |	d   «       |j                  |	«       Œ1 |S )uI   æ­£æ–‡å†…é™„ä»¶é“¾æŽ¥: <a href="*.pdf/doc/xls...">, ç›¸å¯¹è·¯å¾„ç»�å¯¹åŒ–z$<a[^>]+href="([^"]+)"[^>]*>(.*?)</a>r   r9   Ú
javascriptz\.(pdf|docx?|xlsx?|zip|rar|7z)$ú<[^>]+>r   Néd   ú/Úhttpr   éÿÿÿÿ)r$   Úurlr^   )r   ÚfinditerÚIÚSÚgroupr   r   Úsearchr   rD   ÚrsplitÚappendr   ÚsetÚadd)
Ú	html_fragrT   ÚattsÚmÚhrefÚ	name_htmlr$   ÚseenÚuniqr   s
             r   Úextract_attachmentsro   W   sR  € à€DÜ�[‰[Ð@À)ÌRÏTÉTÔTV×TXÑTXÉ[ÓYó LˆØŸ'™' !›*×*Ñ*Ó,¨a¯g©g°a«jˆiˆÙ�t—‘ |Ô4ØÜ�9‰9Ð7¸¼r¿t¹tÕDÜ—6‘6˜* b¨)Ó4×:Ñ:Ó<¸T¸cÐBˆDØ�‰˜sÔ#Ü˜d‘{‘Ø—‘ Ô(Øà!×(Ñ(¨¨aÓ0°Ñ3°cÑ9¸DÑ@�Ø�K‰K Ò!<¨¯©°C«¸Ñ)<ÀTÑJÖKðLô ‹5€DØ€DØò ˆØˆU‰8˜4ÒØ�H‰H�Q�u‘XÔØ�K‰K˜�Nðð €Kr   c                 ó´  — | syt         j                  j                  t        «      st	        dt        › d�d¬«       yt        j                  t        d¬«      }|j                  d«       d	x}}|j                  «       }| D ]�  }	 |j                  d
t        |d   |d   |d   |d   |d   |d   xs dd d t        d|d   |j                  dd«      |j                  dd«      f«       |j                  d	kD  r|dz  }n|dz  }|j                  «        Œ‘ |j                  «        ||fS # t
        j                  $ r}t	        d|› �d¬«       |dz  }Y d }~ŒSd }~ww xY w)N)r   r   u     æœªå�‘çŽ° u   , è·³è¿‡å…¥åº“ (ä»…å†™ JSONL)Tr=   i"  )ÚtimeoutzPRAGMA busy_timeout=290000r   zçINSERT OR IGNORE INTO gov_raw
                   (site_name, source_url, page_url, title, publish_date, content, summary, category, script_name, attachments, group_name, industry)
                   VALUES (?,?,?,?,?,?,?,?,?,?,?,?)r^   ÚtitleÚpub_dateÚcontentr   iô  zcrawl_qionglai_hpgs.pyÚattachmentsÚ
group_nameõ   å››å·�ÚindustryÚotherr   z
  DB err: )ÚosÚpathÚexistsÚDB_PATHrH   Úsqlite3ÚconnectÚexecuteÚcursorÚ	SITE_NAMEÚCATEGORYr0   ÚrowcountÚErrorÚcommitÚclose)ÚresultsÚconnÚaddedÚskippedÚcurÚrrQ   s          r   Ú
push_to_dbrŽ   o   s[  € ÙØÜ�7‰7�>‰>œ'Ô"Ü�œW˜IÐ%BÐCÈ4ÕPØÜ�?‰?œ7¨CÔ0€DØ‡L�LÐ-Ô.ØÐ€EˆGØ
�+‰+‹-€CØò ˆð	Ø�K‰Kð7ô ˜A˜e™H a¨¡h°°'±
¸A¸j¹MÈ1ÈYÉ<Ø�I‘,Ò$ " d sÐ+¬XÐ7OÐQRÐS`ÑQaØ—‘�| XÓ.°·±°jÀ'Ó0JðLô	ð �|‰|˜aÒØ˜‘
‘à˜1‘�ð 	�‰�ð#ð$ 	‡J�J„LØ�'ˆ>Ðøô �}‰}ò 	Ü�J˜q˜cÐ"¨$Õ/Ø�q‰L�Gûð	ús   ÂA<D%Ä%EÄ8EÅEc                  óÈ  ‡— t        «       } dt        j                  v }dt        j                  v rt        dd¬«       y t        dt        › d| xs d› d	t
        › �d¬«       g }d
d
d
d
d
d
dœ}t        «       5 }|j                  j                  dg d¢¬«      }|j                  t        ddddœd¬«      }|j                  «       }	 |j                  t        dd¬«       d}t        d«      D ]O  }	|j!                  d«       	 |j#                  «       }
d|
vsŒ*t%        |
«      dkD  sŒ9t        d|	dz  › d�d¬«       d} n |s't        dd¬«       |j'                  «        	 d d d «       y | r| nt(        }d}t        d|dz   «      D �]<  }t+        ||«      }|st        d |› d!�d¬«       Œ$|j-                  d"g «      }|j-                  d#d
«      }|s �nót        d |› d$|› d%t%        |«      › d&|› d'�	d¬«       |D �]¡  }|d(xx   dz  cc<   t/        |j-                  d)d*«      «      }|j-                  d+«      xs d*d d, }|j-                  d-d*«      Š|r|t
        k  r|d.xx   dz  cc<   d} �n2|j-                  d/d*«      xs d*}t1        j2                  |«      }|rt5        |«      nd*}t7        j8                  d0d*|«      j;                  «       }t%        |«      d,k  r&d1|vr"t        d2|d d3 › �d¬«       |d4xx   dz  cc<   �Œd1|v rt7        j8                  d5ˆfd6„|«      }g }t=        |‰«      }|r|d7xx   dz  cc<   t?        |‰«      }n|d8xx   dz  cc<   t        |||‰‰d9d:|rtA        jB                  |d¬;«      nd*d<œ	}|jE                  |«       |d=xx   dz  cc<   �Œ¤ |rt        d>d¬«        ntG        jH                  d?«       �Œ? |j'                  «        d d d «       tK        ||«       |s"tM        |«      \  }}t        d@|› dA|› dB�d¬«       t        dC|d(   › dD|d=   › dE|d.   › dF|d4   › dG|d7   › dH|d8   › dB�d¬«       y # t        $ r Y �Œjw xY w# t        $ r Y �Œmw xY w# 1 sw Y   ŒŒxY w)INz--no-dbz--sync-onlyu2   sync-only: æŠ“å�–+å…¥åº“ä¸€ä½“, æ— éœ€å�•ç‹¬å�Œæ­¥Tr=   u   ç«™ç‚¹: u    æœ€å¤§é¡µ: u   å…¨é‡�z	 CUTOFF: r   )Ú	total_apiÚkeptÚcutoffÚemptyÚ
att_detailÚatt_fail)z--no-sandboxz---disable-blink-features=AutomationControlledz--disable-dev-shm-usage)ÚheadlessÚargszzh-CNiV  i„  )ÚwidthÚheight)Ú
user_agentÚlocaleÚviewportÚignore_https_errorsi`ê  r†   )rq   Ú
wait_untilFr   i¸  z$_tsiˆ  u   ç‘žæ•°æŒ‘æˆ˜é€šè¿‡ r?   Úsu   æŒ‘æˆ˜å¤±è´¥!r   u     é¡µu
    APIå¤±è´¥rˆ   Útotalr[   z API u    æ�¡ (total ú)r�   rr   r   ÚpublishedTimeStré
   r^   r’   ÚcontentHtmlrY   z<imgu       ç©ºæ­£æ–‡è·³è¿‡: é   r“   z(<img[^>]+src=")([^"]+)(")c                 ór  •— | j                  d«      | j                  d«      j                  d«      r| j                  d«      na| j                  d«      j                  d«      rt        | j                  d«      z   n)‰j                  dd«      d   dz   | j                  d«      z   z   | j                  d«      z   S )Nr   r9   r\   r[   r   r?   )rb   r   rD   rd   )ÚmmrT   s    €r   r%   zmain.<locals>.<lambda>×   s  ø€  2§8¡8¨A£;ÀÇÁÈ!Ã×AWÑAWÐX^ÔA_°"·(±(¸1´+Ð|~÷  }Eñ  }Eð  FGó  }H÷  }Sñ  }Sð  TWô  }XÔfjÐmo×muÑmuÐvwÓmxÒfxð  ^h÷  ^oñ  ^oð  psð  uvó  ^wð  xyñ  ^zð  }@ñ  ^@ð  CE÷  CKñ  CKð  LMó  CNñ  ^Nñ  $Pð  SU÷  S[ñ  S[ð  \]ó  S^ñ  $^€ r   r”   r•   rw   ry   ©Úensure_ascii)	Ú	site_namerr   rs   rt   Ú
source_urlr^   rv   rx   ru   r‘   u       æ—¥æœŸ < CUTOFF å�œæ­¢gš™™™™™é?u   === å…¥åº“: æ–°å¢žu    è·³è¿‡z ===u   === å®Œæˆ�: APIu    ä¿�ç•™u
    CUTOFFæˆªu    ç©ºu	    è¯¦æƒ…OKu    è¯¦æƒ…fail)'r   r   r   rH   r‚   ÚCUTOFFr   ÚchromiumÚlaunchÚnew_contextÚUAÚnew_pageÚgotoÚLIST_1rG   rB   Úwait_for_timeoutrt   Úlenr‡   ÚTOTAL_PAGESrR   r0   r   Úhtml_libÚunescaper7   r   r   r   rV   ro   rE   Údumpsre   rI   rJ   Úsave_resultsrŽ   )Ú	max_pagesÚno_dbrˆ   Ústatsr(   ÚbrowserÚctxrK   ÚpassedÚir3   Útotal_pagesÚ
cutoff_hitrL   rP   Úresults_listr    r�   rr   rs   Úcontent_htmlrt   Útextri   Údetail_htmlÚrecrŠ   r‹   rT   s                               @r   ÚmainrÉ   Ž   s  ø€ ÜÓ!€IØœŸ™Ð!€EØœŸ™Ñ ÜÐBÈ$ÕOØÜ	ˆH”Y�K˜|¨IÒ,A¸Ð+BÀ)ÌFÈ8Ð
TÐ\`Õaà€GØ Q°!¸aÈqÐ^_Ñ`€EÜ	Ó	ð [˜aØ—*‘*×#Ñ#ØÚmð $ó oˆð ×!Ñ!¬R¸ÐTXÐdgÑJhð  CÐ!ó  DˆØ�|‰|‹~ˆð	Ø�I‰I”f e¸ˆIÔAð ˆÜ�r“ò 		ˆAØ×!Ñ! $Ô'ðØ—|‘|“~�ð ˜TÒ!¤c¨$£i°$Ó&6ÜÐ+¨A¨a©C¨5°Ð2¸$Õ?Ø�Ùð		ñ Ü�/¨Õ.Ø�M‰MŒOØ÷5[ð [ñ: $-‘i´+ˆØˆ
Ü˜˜;¨™?Ó+ó :	ˆBÜ˜T 2Ó&ˆDÙÜ˜˜b˜T Ð,°DÕ9ØØŸ8™8 I¨rÓ2ˆLØ—H‘H˜W aÓ(ˆEÙÚÜ�E˜"˜˜Q˜{˜m¨5´°\Ó1BÐ0CÀ<ÐPUÈwÐVWÐXÐ`dÕeØ!ó ,#�Ø�kÓ" aÑ'Ó"Ü# A§E¡E¨'°2Ó$6Ó7�ØŸE™EÐ"4Ó5Ò;¸¸S¸bÐA�ØŸU™U 5¨"Ó-�
Ù ¬6Ò 1Ø˜(“O qÑ(“OØ!%�JÚà Ÿu™u ]°BÓ7Ò=¸2�Ü'×0Ñ0°Ó>�Ù9Eœ-¨Ô5È2�Ü—v‘v˜j¨"¨gÓ6×<Ñ<Ó>�Ü�t“9˜r’> f°GÑ&;ÜÐ1°%¸¸°*°Ð>ÀdÕKØ˜'“N aÑ'“NÙà˜WÑ$Ü Ÿf™fØ5ó ^Øó!�Gð
 �Ü*¨4°Ó<�ÙØ˜,Ó'¨1Ñ,Ó'Ü.¨{¸JÓG‘Dà˜*Ó%¨Ñ*Ó%ä!*Ø"Ø (Ø&Ø",Ø%Ø"*Ø 'ÙKO¤4§:¡:¨dÀÕ#GÐUWñ
�ð —‘˜sÔ#Ø�f“ Ñ"•ðY,#ñZ ÜÐ2¸4Õ@ÙÜ�J‰J�sŽOðu:	ðx 	�‰Œ÷w[ôz �˜%Ô ÙÜ# GÓ,‰ˆˆwÜÐ" 5 '¨°°	¸Ð>ÀdÕKÜ	ˆO˜E +Ñ.Ð/¨w°u¸V±}°oÀZÐPUÐV^ÑP_ÐO`Ð`dÐejÐkrÑesÐdtÐt}ð  Dð  EQñ  Rð  ~Sð  S^ð  _dð  eoñ  _pð  ^qð  quð  vð  ~Bö  Cøôo ò 	Úð	ûô ò Úðú÷#[ð [úsh   Á5AQÃP8Ã!QÃ<QÄQÄQÄ 9QÅ"I+QÐ8	QÑQÑQÑQÑ	QÑQÑQÑQÑQ!c                 óô   — t        t        dd¬«      5 }| D ]+  }|j                  t        j                  |d¬«      dz   «       Œ- 	 d d d «       t        dt        | «      › dt        › �d	¬
«       y # 1 sw Y   Œ*xY w)NÚwzutf-8)ÚencodingFr¨   ú
u   å·²å†™ u    æ�¡åˆ° Tr=   )ÚopenÚOUTÚwriterE   r¹   rH   rµ   )rˆ   r½   Úfr�   s       r   rº   rº   û   sm   € Ü	Œc�3 Ô	)ð >¨QØò 	>ˆAØ�G‰G”D—J‘J˜q¨uÔ5¸Ñ<Õ=ñ	>÷>ô 
ˆG”C˜“L�> ¬#¨Ð
/°tÖ<÷>ð >ús   “1A.Á.A7Ú__main__)N)$Ú__doc__rE   rz   r   r   rI   r~   r3   r·   r   r   Úplaywright.sync_apir   r‚   rD   r³   r@   rA   r¶   ÚnowÚstrftimer¬   r°   rÏ   r}   rƒ   r   r   r7   rR   rV   ro   rŽ   rÉ   rº   Ú__name__© r   r   ú<module>rÙ      s¶   ðñ
÷ :× 9× 9Ó 9ß (Ý /à$€	Ø €Ø	;€Ø.€	Ø€	Ø€Ø
ˆ(�,‰,‹.™9¨%Ô0Ñ
0×	:Ñ	:¸:Ó	F€Øv€Ø €Ø
€Ø€òòò
ò(òòò0ò>kCóZ=ð ˆzÒÙ…Fð r   