Ë
    ¸¬ujÈ  ã                   óò   — d 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	m
Z
 ddlmZmZ  ej                  dd«      Zd	Zd
ZdZe› d�ZdddœZdZdZd„ Zd„ Zd„ Zd„ Zd„ Zd„ Zd„ Zedk(  r e«        yy)u'  
crawl_ahjx.py â€” æ³¾åŽ¿äººæ°‘æ”¿åºœÂ·å»ºè®¾é¡¹ç›®çŽ¯å¢ƒå½±å“�è¯„ä»·
=================================================
CMS: æ³¾åŽ¿äººæ°‘æ”¿åºœä¿¡æ�¯å…¬å¼€å¹³å�°

åˆ—è¡¨ï¼š/XxgkContent/showList/336/82020/page_N.html (15æ�¡/é¡µ)
      éœ€è¦� token_verified=true cookie ç»•è¿‡å��çˆ¬
è¯¦æƒ…ï¼š/OpennessContent/show/{id}.html
      æ ‡é¢˜ <meta name="ArticleTitle">
      æ—¥æœŸ <meta name="PubDate">
      æ­£æ–‡ <div id="zoom">

ç”¨æ³•:
    python3 crawl_ahjx.py               # å…¨é‡�
    python3 crawl_ahjx.py 1             # å¢žé‡�ï¼ˆä»…æœ€æ–°é¡µï¼‰
é    N)ÚBeautifulSoup)Úurljoin)ÚdatetimeÚ	timedelta)ÚThreadPoolExecutorÚas_completedÚ	SEARCH_DBz/root/search.dbu   æ³¾åŽ¿äººæ°‘æ”¿åºœu   å»ºè®¾é¡¹ç›®çŽ¯å¢ƒå½±å“�è¯„ä»·zhttps://www.ahjx.gov.cnz,/XxgkContent/showList/336/82020/page_{}.htmlzoMozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36ztoken_verified=true)z
User-AgentÚCookieé   é   c                 ó    — t        d| › �«       y )Nz[ahjx] )Úprint)Úmsgs    ú/root/gov_crawler/crawl_ahjx.pyÚlogr   -   s   € Ü	ˆG�C�5ˆ/Õó    c                 ó*  — t         j                  | «      }	 t        j                  |t        d¬«      }d|_        |j                  }g }t        j                  d|t        j                  «      D ]z  }|j                  d«      }|j                  d	«      j                  «       }|j                  d
«      }	|j                  d«      r|nt        t         |«      }
|j#                  |
||	f«       Œ| |S # t        $ r}t        d| › d|› �«       g cY d}~S d}~ww xY w)z<Fetch one list page. Returns list of (url, title, date_str).é   ©ÚheadersÚtimeoutúutf-8z  ERROR list page ú: Nzo<a\s+href="(/OpennessContent/show/\d+\.html)"\s+title="([^"]*)"[^>]*>.*?</a>\s*<span>(\d{4}-\d{2}-\d{2})</span>é   é   é   Úhttp)ÚLIST_URLÚformatÚrequestsÚgetÚHEADERSÚencodingÚtextÚ	Exceptionr   ÚreÚfinditerÚDOTALLÚgroupÚstripÚ
startswithr   ÚBASE_URLÚappend)Úpage_noÚurlÚrespÚhtmlÚeÚitemsÚmÚhrefÚtitleÚdate_strÚfull_urls              r   Úfetch_list_pager9   1   s÷   € ä
�/‰/˜'Ó
"€CðÜ�|‰|˜C¬¸"Ô=ˆØˆŒØ�y‰yˆð
 €Eä�[‰[ð	/àÜ
�	‰	ó	ò 
2ˆð �w‰w�q‹zˆØ—‘˜“
× Ñ Ó"ˆØ—7‘7˜1“:ˆØŸ?™?¨6Ô2‘4¼ÄÈ$Ó8OˆØ�‰�h  xÐ0Õ1ð
2ð €Løô% ò ÜÐ   	¨¨A¨3Ð/Ô0Ø�	ûðús   —/C, Ã,	DÃ5DÄDÄDc                 ó€  — 	 t        j                  | t        d¬«      }d|_        |j                  }t        |d«      }|j                  d	d
di¬«      }|r$|j                  d«      r|d   j                  «       nd}d}|j                  d	d
di¬«      }|rK|j                  d«      r:t        j                  d|d   j                  «       «      }	|	r|	j                  d«      }|j                  d¬«      }
|
rt        |
«      nd}|st        d| › �«       d||fS |||fS # t
        $ r}t        d| › d|› �«       Y d}~yd}~ww xY w)z=Return (content_html, date_str, title) or (None, None, None).r   r   r   z  ERROR r   N©NNNzhtml.parserÚmetaÚnameÚArticleTitle)ÚattrsÚcontentÚ ÚPubDatez(\d{4}-\d{2}-\d{2})r   Úzoom)Úidz  WARNING: no content for )r    r!   r"   r#   r$   r%   r   r   Úfindr*   r&   Úmatchr)   Ústr)r/   r0   r1   r2   ÚsoupÚ
meta_titler6   r7   Ú	meta_dater4   Úcontent_divÚcontent_htmls               r   Úfetch_detailrM   M   sE  € ð Ü�|‰|˜C¬¸"Ô=ˆØˆŒØ�y‰yˆô
 ˜˜}Ó-€Dð —‘˜6¨&°.Ð)A�ÓB€JÙ-7¸J¿N¹NÈ9Ô<UˆJ�yÑ!×'Ñ'Ô)Ð[]€Eð €HØ—	‘	˜&¨°Ð(;�	Ó<€IÙ�Y—]‘] 9Ô-Ü�H‰HÐ+¨Y°yÑ-A×-GÑ-GÓ-IÓJˆÙØ—w‘w˜q“zˆHð —)‘)˜v�)Ó&€KÙ'2”3�{Ô#¸€LáÜÐ(¨¨Ð.Ô/Ø�X˜uÐ$Ð$à˜ 5Ð(Ð(øô5 ò  Üˆh�s�e˜2˜a˜SÐ!Ô"Üûð ús   ‚/D Ä	D=Ä"D8Ä8D=c                 ó$  — i }t        t        ¬«      5 }| D �ci c]  }|j                  t        |«      |“Œ }}t	        |«      D ]  }||   }	 |j                  «       ||<   Œ 	 d d d «       |S c c}w # t        $ r d||<   Y Œ>w xY w# 1 sw Y   |S xY w)N)Úmax_workersr;   )r   ÚMAX_WORKERSÚsubmitrM   r   Úresultr%   )ÚurlsÚresultsÚexr/   Úfut_mapÚfuts         r   Úfetch_detail_batchrX   p   s£   € Ø€GÜ	¬Ô	4ð 2¸Ø@DÖE¸�2—9‘9œ\¨3Ó/°Ñ4ÐEˆÐEÜ Ó(ò 	2ˆCØ˜#‘,ˆCð2Ø"Ÿz™z›|�˜’ñ	2÷2ð €Nùò Føô
 ò 2Ø1�˜“ð2ú÷2ð €Nús?   “B˜A,¶BÁA1ÁBÁ,BÁ1BÁ?BÂBÂBÂBc           
      óT  — | sydd l }|j                  t        «      }|j                  «       }d}| D ]-  \  }}}}	 |j	                  dt
        ||||t        f«       |dz  }Œ/ |j                  «        |j                  «        |S # t        $ r}	t        d|› d|	› �«       Y d }	~	Œqd }	~	ww xY w)Nr   zœINSERT OR REPLACE INTO gov_raw
                   (site_name, page_url, title, publish_date, content, category)
                   VALUES (?, ?, ?, ?, ?, ?)r   z  DB error for r   )Úsqlite3ÚconnectÚDB_PATHÚcursorÚexecuteÚ	SITE_NAMEÚCOLUMN_NAMEr%   r   ÚcommitÚclose)
r3   rZ   ÚconnÚcÚinsertedr/   r6   r7   rL   r2   s
             r   Ú
save_to_dbrf   }   s·   € ÙØÛØ�?‰?œ7Ó#€DØ�‰‹€AØ€HØ.3ò 
.Ñ*ˆˆU�H˜lð		.Ø�I‰Ið0ô ˜C ¨°,ÄÐLô	ð ˜‰M‰Hð
.ð 	‡K�K„MØ‡J�J„LØ€Oøô	 ò 	.Ü�/ #  b¨¨Ð,×-Ñ-ûð	.ús   º%BÂ	B'ÂB"Â"B'c                  óî   — 	 dd l } | j                  t        «      }|j                  dt        f«       |j                  «        |j                  «        y # t        $ r}t        d|› �«       Y d }~y d }~ww xY w)Nr   a  INSERT OR REPLACE INTO gov_search(rowid, title, site_name, summary)
               SELECT rowid, title, site_name,
                      CASE WHEN length(content) > 200 THEN substr(content, 1, 200) ELSE content END
               FROM gov_raw WHERE category = ?z
FTS note: )	rZ   r[   r\   r^   r`   ra   rb   r%   r   )rZ   rc   r2   s      r   Úrebuild_ftsrh   ”   sf   € ðÛØ�‰œwÓ'ˆØ�‰ð2ô ˆNô	
ð 	�‰ŒØ�
‰
�øÜò Üˆj˜˜Ð×Ñûðús   ‚AA Á	A4ÁA/Á/A4c                  ó2  — t        t        j                  «      dkD  xr t        j                  d   dk(  } t        j                  «       t        d¬«      z
  j                  d«      }t        d|› �«       g }d}	 t        |«      }|s|dk(  rt        d«       y nŒt        d|› d	t        |«      › d
�«       |D ���cg c]  \  }}}|sŒ
||k\  sŒ|||f‘Œ }}}}|j                  |«       | rt        d«       n/|r't        |«      t        |«      k  rt        d|› d�«       n|dz  }Œ«t        dt        |«      › �«       |st        d«       y g }	t        dz  }
t        dt        |«      |
«      D ]�  }||||
z    }|D ��cg c]  \  }}}|‘Œ
 }}}t        d|dz   › d|t        |«      z   › dt        |«      › d�«       t        |«      }|D ]A  \  }}}|j                  |d«      \  }}}|xs |}|xs |}|	j                  ||||xs df«       ŒC ŒŸ t        |	«      }t        d|› dt        |	«      › �«       |	rAt!        |	D �cg c]  }|d   sŒ	|d   ‘Œ c}«      }t        d|r|d   nd› d|r|d   nd› �«       t#        «        t        d«       y c c}}}w c c}}w c c}w )Nr   Ú1iG  )Údaysz%Y-%m-%dz3-year cutoff: zNo articles foundzPage r   z	 articleszIncremental: page 1 onlyz': some articles before cutoff, stoppingzTotal articles to process: zNo articles within 3 yearsr   r   z  Details [ú-ú/z]...r;   rA   zSaved: r   zDate range: zN/Az ~ éÿÿÿÿzDone!)ÚlenÚsysÚargvr   Únowr   Ústrftimer   r9   ÚextendrP   ÚrangerX   r!   r-   rf   Úsortedrh   )ÚincrementalÚthree_years_agoÚall_articlesÚpager3   ÚuÚtÚdÚfilteredrT   Ú
batch_sizeÚbatch_startÚbatchÚ_Ú
batch_urlsÚ
detail_mapr/   r6   r7   rL   Údetail_dateÚdetail_titleÚfinal_titleÚ
final_dateÚsavedÚrÚdatess                              r   ÚmainrŒ   ¥   sÊ  € Ü”c—h‘h“- !Ñ#Ò:¬¯©°©°sÑ(:€KÜ—|‘|“~¬	°wÔ(?Ñ?×IÑIÈ*ÓU€OÜˆ/˜/Ð*Ð+Ô,ð €LØ€Dà
Ü Ó%ˆÙØ�qŠyÜÐ'Ô(ØØäˆe�D�6˜œC ›J˜< yÐ1Ô2ð .3×QÐQ¡' ! Q¨²a¸AÀÓ<P�Q˜˜1’IÐQˆÒQØ×Ñ˜HÔ%áÜÐ*Ô+Øñ œ˜H›¬¨E«
Ò2Ü�%˜�vÐDÐEÔFØà�‰	ˆð/ ô2 Ð
%¤c¨,Ó&7Ð%8Ð9Ô:áÜÐ(Ô)Øð €GÜ˜q‘€JÜ˜Q¤ LÓ 1°:Ó>ò 	OˆØ˜[¨°zÑ)AÐBˆØ',×-™G˜A˜q !’aÐ-ˆ
Ñ-Üˆk˜+ a™-˜¨¨+´c¸%³jÑ*@Ð)AÀÄ3À|ÓCTÐBUÐUYÐZÔ[Ü'¨
Ó3ˆ
Ø$)ò 	OÑ ˆC�˜Ø6@·n±nÀSÐJ\Ó6]Ñ3ˆL˜+ |Ø&Ò/¨%ˆKØ$Ò0¨ˆJØ�N‰N˜C ¨j¸,Ò:LÈ"ÐMÕNñ		Oð	Oô �wÓ€EÜˆ'�%�˜œ#˜g›,˜Ð(Ô)áÜ gÖ6 °°1³˜˜!›Ò6Ó7ˆÜˆl¡u˜5 š8°%Ð8¸É¸EÀ"ºIÐTYÐ;ZÐ[Ô\ä„MÜˆ…LùôW Rùó2 .ùò 7s$   Â8JÃJÃ
JÅ9JÈ9
JÉJÚ__main__)Ú__doc__Úosr&   rp   r    Úbs4r   Úurllib.parser   r   r   Úconcurrent.futuresr   r   Úgetenvr\   r_   r`   r,   r   r"   rP   Ú	PAGE_SIZEr   r9   rM   rX   rf   rh   rŒ   Ú__name__© r   r   ú<module>r—      s©   ðñó" 
Û 	Û 
Û Ý Ý  ß (ß ?à
ˆ"�)‰)�KÐ!2Ó
3€Ø €	Ø.€Ø$€ØˆZÐEÐF€ð3ð $ñ	€ð €Ø€	òòò8 )òF
òò.ò"?ðD ˆzÒÙ…Fð r   