Ë
    A¥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	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  ee«      j(                  j+                  «       Z eedz  «      ZdZdZd	Z ej8                  «       Zd
diZdd„Zd„ Z g d¢Z!dd„Z"	 	 dd„Z#d„ Z$d„ Z%d„ Z&dd„Z'd„ Z(d„ Z)d d„Z*dd„Z+	 	 d!d„Z,d„ Z- G d„ d«      Z.y)"u6  
base_crawler â€” æ”¿åºœçˆ¬è™«å…¬å…±æ¨¡å�—ï¼ˆä½›å†ˆæ¨¡å¼� v3ï¼‰
==============================================
æ‰€æœ‰æ–°ç«™çˆ¬è™«ä»Žæ­¤æ¨¡å�— importï¼ŒæŒ‰ä½›å†ˆæ¨¡å¼�è‡ªåŠ¨å¤„ç�†ï¼š
  - content = åŽŸå§‹HTMLï¼ˆä¿�ç•™ <a><img> ç­‰è¯­ä¹‰æ ‡ç­¾ï¼‰
  - summary = extract_plain_text(content) çº¯æ–‡æœ¬ + å™ªå£°è¿‡æ»¤
  - å†…ç½® 4 ç§�åˆ—è¡¨é¡µæŠ“å�–æ¨¡å¼� + åˆ†é¡µ
  - å†…ç½® 4 ç§�è¯¦æƒ…é¡µæ­£æ–‡å®¹å™¨è‡ªåŠ¨å°�è¯•
  - å†…ç½®æ—¥æœŸæ��å�–ï¼ˆURL/æ–‡æœ¬/åˆ—è¡¨ï¼‰
  - å†…ç½®é™„ä»¶é“¾æŽ¥æ��å�–ä¸Žæ‘˜è¦�è¿½åŠ 
  - å†…ç½®å¢žé‡�å�Œæ­¥åˆ°æœ�åŠ¡å™¨ + search_app é‡�å�¯

ç”¨æ³•:
    from base_crawler import GovCrawler

    class MyCrawler(GovCrawler):
        def do_crawl(self):
            # æ¨¡å¼�A: APIåˆ—è¡¨
            raw = self.fetch_list_via_api(API_URL, page=1, dept_id=90)
            for item in raw['data']['list']:
                html = self.http_get(item['pub_url'])
                detail = self.extract_detail(html)
                self.store_item(item['title'], item['pub_url'],
                                detail['content'], item.get('rel_time','')[:10])

            # æ¨¡å¼�B: HTMLåˆ—è¡¨
            items = self.fetch_list_via_html(LIST_URL,
                r'<a href="(/detail/\d+\.html)">(.*?)</a>')
            for item in items:
                html = self.http_get(item['url'])
                detail = self.extract_detail(html)
                self.store_item(item['title'], item['url'],
                                detail['content'], detail.get('date',''))

    MyCrawler(site_name='ç«™ç‚¹å��', domain='www.example.com',
              db_name='site_results.db').run()
é    N)Údatetime)ÚPath)Úurljoinzcrawler_results.dbzroot@1.94.217.116z/root/crawler_results.dbz/root/search.dbz
User-Agentz[Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/125.0.0.0 Safari/537.36c                 óp  — d}t        d|dz   «      D ]p  }	 t        j                  j                  | t        ¬«      }t        j                  j                  ||t        ¬«      }|j                  «       j                  dd¬«      c S  y# t        $ r&}|}||k  rt        j                  d«       Y d}~Œžd}~ww xY w)	u   é€šç”¨ HTTP GETï¼Œè‡ªåŠ¨é‡�è¯•Né   é   )Úheaders©ÚtimeoutÚcontextúutf-8Úreplace)Úerrors)ÚrangeÚurllibÚrequestÚRequestÚHEADERSÚurlopenÚCTXÚreadÚdecodeÚ	ExceptionÚtimeÚsleep)Úurlr   ÚretryÚlast_errÚattemptÚreqÚrespÚes           ú!/root/gov_crawler/base_crawler.pyÚhttp_getr$   ?   s¦   € à€HÜ˜˜E A™IÓ&ò ˆð	Ü—.‘.×(Ñ(¨´gÐ(Ó>ˆCÜ—>‘>×)Ñ)¨#°wÌÐ)ÓLˆDØ—9‘9“;×%Ñ% g°iÐ%Ó@Ò@ð	ð øô	 ò 	ØˆHØ˜%ÒÜ—
‘
˜1”ÿøð	ús   –A+BÂ	B5ÂB0Â0B5c                 ó6  — | s| S dD ]a  }d|d   › d�}d|d   › d�}|| v sŒ|| v sŒt        j                  t        j                  |«      dz   t        j                  |«      z   d| «      } Œc t        j                  d	d| «      } t        j                  d
d| «      } | S )uH  
    ç§»é™¤é¡µé�¢ä¸­å¸¸è§�çš„CSSè£…é¥°åŒºå�—ï¼ˆbanner/headerï¼‰ï¼Œ
    é˜²æ­¢è£…é¥°æ€§å†…å®¹ï¼ˆbannerå›¾ã€�é�¢åŒ…å±‘å¯¼èˆªç­‰ï¼‰æ··å…¥æ­£æ–‡æ��å�–ã€‚

    æ”¯æŒ�çš„æ¨¡å¼�ï¼š
      <!--bannerå¼€å§‹-->...<!--bannerç»“æ�Ÿ-->   (Jcms1 CMS)
      <!--headerå¼€å§‹-->...<!--headerç»“æ�Ÿ-->
      <div class="lmy_banner">...</div>
    ))Úbannerr&   )Úheaderr'   )õ   ä¸»ä½“r(   z<!--r   u	   å¼€å§‹-->r   u	   ç»“æ�Ÿ-->z[\s\S]*?Ú z8<div[^>]*class="lmy_banner"[^>]*>[\s\S]*?</div>\s*</div>z/<div[^>]*class="lmy_banner"[^>]*>[\s\S]*?</div>)ÚreÚsubÚescape)ÚhtmlÚpairÚ	start_tagÚend_tags       r#   Ústrip_banner_sectionr1   R   s­   € ñ ØˆàRò ]ˆØ˜4 ™7˜) 9Ð-ˆ	Ø˜˜a™˜	 Ð+ˆØ˜Ò ¨D¢Ü—6‘6œ"Ÿ)™) IÓ.°Ñ<¼r¿y¹yÈÓ?QÑQÐSUÐW[Ó\‰Dð	]ô �6‰6ÐMÈrÐSWÓX€DÜ�6‰6ÐDÀbÈ$ÓO€DØ€Kó    )z˜<div[^>]*class="article-content\s+article-content-body"[^>]*id="zoomcon"[^>]*>(.*?)</div>\s*<div[^>]*class="article-(?:reldocuments|auxiliary|extended)"z\id="zoomcon"[^>]*>(.*?)</div>\s*<div[^>]*class="article-(?:reldocuments|auxiliary|extended)"u%   <!--æ­£æ–‡å†…å®¹-->(.*?)<!--ç»“æ�Ÿ-->z'<font[^>]*id="?Zoom"?[^>]*>(.*?)</font>z@<div[^>]*class="article[^"]*"[^>]*>(.*?)</div>\s*</div>\s*</div>z:<div class="text-center mb-3">(.*?)<div class="footer_contz.<div[^>]*class="wzcon"[^>]*>(.*?)</div>\s*<divz<<div[^>]*class="[^"]*content[^"]*"[^>]*>(.*?)</div>\s*</div>zAid="postmessage_\d+"[^>]*>(.*?)</div>\s*<div[^>]*id="postmessage_z#<td[^>]*class="t_f"[^>]*>(.*?)</td>z=class="t_fsz"[^>]*>(.*?)<div[^>]*class="(?:sign|pstatus|ptg)"zB<div[^>]*class="v_news_content"[^>]*>(.*?)</div>\s*</div>\s*</div>c                 ó¶   — |xs t         }|D ]J  }t        j                  || t        j                  «      }|sŒ+|j	                  d«      j                  «       c S  y)u?   å°�è¯•æ‰€æœ‰å·²çŸ¥çš„æ­£æ–‡å®¹å™¨æ¨¡å¼�ï¼Œè¿”å›žæœ€å…ˆåŒ¹é…�çš„r   N)ÚCONTENT_PATTERNSr*   ÚsearchÚDOTALLÚgroupÚstrip)r-   Úextra_patternsÚpatternsÚpatÚcms        r#   Ú_extract_detail_via_patternsr=   Š   sQ   € àÒ1Ô!1€HØò 'ˆÜ�Y‰Y�s˜D¤"§)¡)Ó,ˆÚØ—8‘8˜A“;×$Ñ$Ó&Ò&ð'ð r2   c                 ó0  — | syd}|rFt        j                  || t         j                  «      }|r|j                  d«      j	                  «       }|�sAt        j                  d| t         j
                  «      }|s%t        j                  d| t         j
                  «      }|s%t        j                  d| t         j                  «      }|s%t        j                  d| t         j                  «      }|s%t        j                  d| t         j                  «      }|r~t        j                  d	d|j                  d«      «      j	                  «       }t        j                  d
d|«      j	                  «       }t        j                  dd|«      j	                  «       }t        | |«      }d}|r4t        |«      }|r't        j                  dd|t         j                  ¬«      }|s%t        | «      }|rt        |«      dkD  r|dd dz   }|}d}	t        j                  d| «      }
|
r|
j                  d«      }	g }|rjt        j                  d|t         j
                  «      D ]B  }|j                  |j                  d«      j	                  «       |j                  d«      dœ«       ŒD |sÊt        j                  d| t         j
                  «      D ]¢  }|j                  d«      j	                  «       }|j                  d«      j	                  «       }|j                  d«      r'ddj                  |j                  d«      dd «      z   }n|j                  d«      r|dd }|j                  ||dœ«       Œ¤ t!        ||«      }|r |D ]  }|d   |vsŒ|d|d   › d|d   › �z  }Œ |||	||dœS )uY  
    ä»Žè¯¦æƒ…é¡µHTMLä¸­æ��å�–ï¼šæ ‡é¢˜ã€�æ­£æ–‡HTMLã€�æ—¥æœŸã€‚
    
    å�‚æ•°:
        html: è¯¦æƒ…é¡µHTMLæº�ç �
        title_pattern: è‡ªå®šä¹‰æ ‡é¢˜æ­£åˆ™ï¼ˆå�¯é€‰ï¼‰ï¼Œé»˜è®¤ä»Ž <title> æˆ– <h1>
        content_patterns: è‡ªå®šä¹‰æ­£æ–‡å®¹å™¨æ­£åˆ™åˆ—è¡¨ï¼ˆå�¯é€‰ï¼‰
        strip_metadata: æ˜¯å�¦åŽ»æŽ‰å¼€å¤´çš„<h3>é‡�å¤�æ ‡é¢˜å’Œ<p class="text-muted">å…ƒæ•°æ�®
        noise_lines: è‡ªå®šä¹‰å™ªå£°è¡Œåˆ—è¡¨ï¼ˆä¼ ç»™extract_plain_textï¼‰
    
    è¿”å›ž:
        {'title': str, 'content': str (åŽŸå§‹HTML), 'date': str,
         'attachments': [{'name': str, 'url': str}], 'summary': str}
    Nr)   r   z3<meta[^>]*name="ArticleTitle"[^>]*content="([^"]+)"z0<meta[^>]*name="pageTitle"[^>]*content="([^"]+)"z.<h1[^>]*class="big_title[^"]*"[^>]*>(.*?)</h1>z<title>(.*?)</title>z<h1[^>]*>(.*?)</h1>ú<[^>]+>u   \s*[â€”]\s*.*$z\s*-\s+[^-]+$z9^<h3>.*?</h3>\s*<p class="text-muted">.*?</p>\s*</div>\s*©Úflagsé˜:  ú...z(\d{4})-(\d{2})-(\d{2})r   zI<a[^>]*href="([^"]+\.(?:pdf|doc|docx|xls|xlsx|zip|rar))"[^>]*>([^<]+)</a>r   )Únamer   zDhref="([^"]*virtual_attach_file[^"]*)"[^>]*>[^<]*<[^>]+>([^<]+\.pdf)z../../ú/z../r   u   
ðŸ“Ž rD   z: )ÚtitleÚcontentÚdateÚattachmentsÚsummary)r*   r5   r6   r7   r8   ÚIr+   r=   Úclean_contentÚextract_body_via_p_tagsÚlenÚfinditerÚappendÚ
startswithÚjoinÚsplitÚextract_plain_text)r-   Útitle_patternÚcontent_patternsÚstrip_metadataÚnoise_linesrF   ÚtmÚrawrG   rH   ÚdmrI   ÚamrD   r   rJ   Úas                    r#   Úextract_detailr^   ”   s;  € ñ  Øð €EÙÜ�Y‰Y�} d¬B¯I©IÓ6ˆÙØ—H‘H˜Q“K×%Ñ%Ó'ˆEÚô �Y‰YÐMÈtÔUW×UYÑUYÓZˆÙÜ—‘ÐNÐPTÔVX×VZÑVZÓ[ˆBÙÜ—‘ÐLÈdÔTV×T]ÑT]Ó^ˆBÙÜ—‘Ð2°D¼"¿)¹)ÓDˆBÙÜ—‘Ð1°4¼¿¹ÓCˆBÙÜ—F‘F˜: r¨2¯8©8°A«;Ó7×=Ñ=Ó?ˆEä—F‘FÐ,¨b°%Ó8×>Ñ>Ó@ˆEÜ—F‘FÐ+¨R°Ó7×=Ñ=Ó?ˆEô ' tÐ-=Ó
>€CØ€GÙ
Ü Ó$ˆáÜ—f‘fØLØ�G¤2§9¡9ôˆGñ
 Ü% dÓ+ˆÙÜ�3‹x˜%ÒØ˜&˜5�k EÑ)�ØˆGð €DÜ	�‰Ð-¨tÓ	4€BÙ	Ø�x‰x˜‹{ˆð €KáÜ—+‘+ÐjØ&¬¯©ó.ò 	RˆBà×Ñ¨¯©°«×(9Ñ(9Ó(;ÀBÇHÁHÈQÃKÑPÕQð	Rñ
 Ü—+‘+ØSØ”"—$‘$ó
ò 	;ˆBð —8‘8˜A“;×$Ñ$Ó&ˆDØ—(‘(˜1“+×#Ñ#Ó%ˆCà�~‰~˜hÔ'Ø˜CŸH™H S§Y¡Y¨s£^°A°BÐ%7Ó8Ñ8‘Ø—‘ Ô&Ø˜!˜"�g�Ø×Ñ¨°SÑ9Õ:ð	;ô ! ¨+Ó6€GÙØò 	=ˆAØ�‰x˜wÒ&Ø˜W Q v¡Y K¨r°!°E±(°Ð<Ñ<‘ð	=ð
 ØØØ"Øñð r2   c                 óL  ‡— | syt        j                  dd| t         j                  t         j                  z  ¬«      }t        j                  dd|t         j                  t         j                  z  ¬«      }t        j                  dd|«      }t	        |«      dkD  r|dd dz   }i Št        j
                  d	|«      D ]$  }|j                  d
«      ‰|j                  «       <   Œ& t        j                  dd|«      }‰rˆfd„}t        j                  d||«      }|j                  «       S )u�   
    æ¸…æ´—åŽŸå§‹HTMLï¼šä¿�ç•™è¯­ä¹‰æ ‡ç­¾ï¼ˆ<a> <img> <p> <table> ç­‰ï¼‰ï¼Œå�ªåŽ» script/styleã€‚
    è¿™æ˜¯å­˜åˆ° content åˆ—çš„æ ¼å¼�ã€‚
    r)   z<script[^>]*>.*?</script>r@   z<style[^>]*>.*?</style>z<p>\s*<br\s*/?>\s*</p>rB   NrC   z((<img[^>]+)style="([^"]*max-width[^"]*)"r   ú\s+style="[^"]*"c                 ó,  •— | j                  d«      }‰j                  «       D ]n  \  }}t        || j                  «       z
  «      dk  sŒ&d|d d j	                  «       v sŒ<|j                  d«      d|› d�z   |j                  d«      rdz   c S dz   c S  |S )	Nr   éÈ   Úimgé
   z/>z style="ú"ú>)r7   ÚitemsÚabsÚstartÚlowerÚrstripÚendswith)ÚmÚtagÚposÚstyleÚ
img_styless       €r#   Úrestore_img_stylez(clean_content.<locals>.restore_img_style  s—   ø€ Ø—'‘'˜!“*ˆCØ(×.Ñ.Ó0ò j‘
��UÜ�s˜QŸW™W›Y‘Ó'¨#Ó-°%¸3¸sÀ¸8¿>¹>Ó;KÒ2KØŸ:™: dÓ+°¸¸¸qÐ.AÑAÈSÏ\É\ÐZ^ÔM_ÀTÑiÒiÐehÑiÒiðjð ˆJr2   z<img[^>]*/?>)	r*   r+   r6   rK   rN   rO   r7   ri   r8   )Úraw_htmlÚcleanedrm   rr   rq   s       @r#   rL   rL   ÿ   só   ø€ ñ
 ØÜ�f‰fÐ1°2°xÄrÇyÁyÔQS×QUÑQUÁ~ÔV€GÜ�f‰fÐ/°°WÄBÇIÁIÌbÏdÉdÁNÔS€GÜ�f‰fÐ.°°GÓ<€GÜ
ˆ7ƒ|�eÒØ˜&˜5�/ EÑ)ˆà€JÜ�[‰[ÐDÀgÓNò +ˆØ !§¡¨£
ˆ
�1—7‘7“9Òð+ä�f‰fÐ(¨"¨gÓ6€Gáô	ô —&‘&˜Ð*;¸WÓEˆØ�=‰=‹?Ðr2   c                 óØ  — | syt        j                  dd| «      } t        j                  dd| t         j                  ¬«      } t        j                  dd| t         j                  ¬«      } t        j                  dd| «      } t        j                  d	d
| «      } t        j                  dd| «      } t        j                  dd| «      } t        j                  dd| «      } | j                  «       S )uF  
    æ¸…æ´—è®ºå�›/å¯Œæ–‡æœ¬ç¼–è¾‘å™¨çš„å†—ä½™ HTMLã€‚
    ä¸“é—¨å¤„ç�† Discuz!ã€�CKEditor ç­‰äº§ç”Ÿçš„å™ªéŸ³æ ‡ç­¾å¦‚ï¼š
      <font face="å®‹ä½“">å­—ç¬¦</font>
      <div align="center">...</div>
      <font color="#333">...</font>

    ä¿�ç•™è¯­ä¹‰æ ‡ç­¾ï¼š<a> <img> <p> <table> <br> <strong> <em> <h1-6> <ul> <ol> <li>
    r)   z<font[^>]*>\s*</font>z<font[^>]*>(.*?)</font>z\1r@   z.<strong>\s*<font[^>]*>(.*?)</font>\s*</strong>z<strong>\1</strong>z<div[^>]*align="[^"]*"[^>]*>z</div>ú
z<font[^>]*>&quot;</font>r`   ú\n{3,}ú

)r*   r+   r6   r8   )r-   s    r#   Úclean_noisy_htmlry     s½   € ñ Øä�6‰6Ð*¨B°Ó5€Dä�6‰6Ð,¨e°TÄÇÁÔK€Dä�6‰6ÐCÐE[Ð]aÔik×irÑirÔs€Dä�6‰6Ð1°2°tÓ<€DÜ�6‰6�)˜T 4Ó(€Dä�6‰6Ð-¨r°4Ó8€Dä�6‰6Ð% r¨4Ó0€Dä�6‰6�)˜V TÓ*€DØ�:‰:‹<Ðr2   c                 óŠ  — t        | «      }g }d}t        j                  d|t        j                  «      D ]¯  }t        j                  dd|j                  d«      «      j                  «       }d|j                  d«      v }|st        |«      dk  r|sŒ]d}|sŒbt        j                  d	|«      rŒyt        j                  d
|«      rŒ�|j                  |j                  d«      «       Œ± |r[dj                  |«      }t        j                  d|t        j                  «      D ]   }|j                  d«      }	|	|vsŒ|d|	z   z  }Œ" |S y)uÌ   
    æœ€ç»ˆå�Žå¤‡æ–¹æ¡ˆï¼šå¯¹æ²¡æœ‰æ ‡å‡†æ­£æ–‡å®¹å™¨çš„CMSã€‚
    å…ˆstrip_banner_sectionåŽ»å™ªï¼Œç„¶å�Žæ‰¾æœ‰æ„�ä¹‰çš„ä¸­æ–‡<p>æ®µè�½ã€‚

    è¿”å›žï¼šæ‹¼æŽ¥çš„HTMLï¼ˆå�«<p>æ ‡ç­¾ï¼‰æˆ–ç©ºå­—ç¬¦ä¸²
    Fz<p[^>]*>(.*?)</p>r?   r)   r   z<a é   Tu;   ^(ä¸Šä¸€[ç¯‡é¡µæ�¡]|ä¸‹ä¸€[ç¯‡é¡µæ�¡]|è¿”å›ž|é¦–é¡µ|å…³é—­)u0   ^(å�‘å¸ƒæ—¶é—´|æ›´æ–°æ—¶é—´|æ�¥æº�|ä½œè€…)[ï¼š:]r   rv   zB<a[^>]*href="([^"]*.(?:pdf|docx?|xlsx?|zip|rar))"[^>]*>([^<]+)</a>)r1   r*   rO   r6   r+   r7   r8   rN   ÚmatchrP   rR   rK   )
r-   ÚbodyÚ
paragraphsÚ
in_contentrm   ÚtextÚhas_linkÚhtml_contentr\   Úa_tags
             r#   rM   rM   :  s)  € ô   Ó%€Dà€JØ€JÜ�[‰[Ð-¨t´R·Y±YÓ?ò *ˆÜ�v‰v�j " a§g¡g¨a£jÓ1×7Ñ7Ó9ˆà˜AŸG™G A›JÐ&ˆÙä�4‹y˜1Š}¡XØØˆJÚä�x‰xÐVÐX\Ô]Øä�x‰xÐKÈTÔRØØ×Ñ˜aŸg™g a›jÕ)ð!*ñ" Ø—y‘y Ó,ˆä—+‘+ÐcØ#¤R§T¡Tó+ò 	-ˆBà—H‘H˜Q“KˆEØ˜LÒ(Ø  u¡Ñ,‘ð		-ð
 ÐØr2   c                 óˆ  ‡— | syt        j                  dd| «      }t        j                  dd|«      }t        j                  dd|«      }t        j                  |«      }t        j                  dd|«      }t        j                  d	d|«      }|j	                  «       d
d }g d¢}|xs |}g }|j                  d«      D ]L  }|j	                  «       Š‰s|j                  d«       Œ't        ˆfd„|D «       «      rŒ<|j                  ‰«       ŒN dj                  |«      }t        j                  d	d|«      }|j	                  «       S )uÇ   
    ä»ŽHTMLæ��å�–çº¯æ–‡æœ¬ï¼Œä¿�ç•™æ®µè�½ç»“æž„ï¼Œè¿‡æ»¤å™ªå£°è¡Œã€‚
    
    è‡ªå®šä¹‰å™ªå£°ï¼š
        extract_plain_text(html_content, noise_lines=['æ‰«ä¸€æ‰«', 'æµ�è§ˆé‡�ï¼š', 'Copyright'])
    r)   z</(p|div|li|h[1-6]|tr|td|th)>rx   z	<br\s*/?>rv   r?   z[ \t]+ú rw   Néô  )	u	   æ‰«ä¸€æ‰«u   æ‰“å�°|u   å…³é—­u   ç›¸å…³é“¾æŽ¥u   ç›¸å…³æ–‡æ¡£u   ç›¸å…³å›¾ç‰‡u   ç›¸å…³éŸ³é¢‘u   ç›¸å…³è§†é¢‘u   ç›¸å…³é™„ä»¶c              3   ó&   •K  — | ]  }|‰v –— Œ
 y ­w©N© )Ú.0ÚnÚlss     €r#   ú	<genexpr>z%extract_plain_text.<locals>.<genexpr>~  s   øè ø€ Ò2 �Q˜"”WÑ2ùs   ƒ)	r*   r+   Úhtml_modÚunescaper8   rS   rP   ÚanyrR   )r‚   rX   r€   ÚDEFAULT_NOISEÚclean_linesÚlinerŒ   s         @r#   rT   rT   c  s  ø€ ñ ØÜ�6‰6Ð2°F¸LÓI€DÜ�6‰6�,  dÓ+€DÜ�6‰6�*˜b $Ó'€DÜ×Ñ˜TÓ"€DÜ�6‰6�)˜S $Ó'€DÜ�6‰6�)˜V TÓ*€DØ�:‰:‹<˜˜Ð€Dò€Mð Ò. €KØ€KØ—
‘
˜4Ó ò #ˆØ�Z‰Z‹\ˆÙØ×Ñ˜rÕ"ÜÓ2 kÔ2Õ2Ø×Ñ˜rÕ"ð#ð �9‰9�[Ó!€DÜ�6‰6�)˜V TÓ*€DØ�:‰:‹<Ðr2   c                 ó@  — t        j                  d| «      }|r7|j                  d«      › d|j                  d«      › d|j                  d«      › �S t        j                  d| «      }|r7|j                  d«      › d|j                  d«      › d|j                  d«      › �S y)uÆ   
    ä»ŽURLè·¯å¾„æ��å�–æ—¥æœŸã€‚
    
    æ”¯æŒ�æ¨¡å¼�:
      /2026/05/19/402155.html  â†’ 2026-05-19
      /20260519/402155.html    â†’ 2026-05-19
      _2026-05-19_             â†’ 2026-05-19
    z/(\d{4})/(\d{2})/(\d{2})/r   ú-r   é   z/(\d{4})(\d{2})(\d{2})/r)   )r*   r5   r7   )r   r[   s     r#   Úextract_date_from_urlr—   ‰  s�   € ô 
�‰Ð/°Ó	5€BÙ	Ø—(‘(˜1“+�˜a §¡¨£˜}¨A¨b¯h©h°q«k¨]Ð;Ð;Ü	�‰Ð-¨sÓ	3€BÙ	Ø—(‘(˜1“+�˜a §¡¨£˜}¨A¨b¯h©h°q«k¨]Ð;Ð;Ør2   c           	      óh  — t        j                  d| «      }|rK|j                  d«      › dt        |j                  d«      «      d›dt        |j                  d«      «      d›�S t        j                  d| «      }|r7|j                  d«      › d|j                  d«      › d|j                  d«      › �S y)	uÚ   
    ä»Žæ–‡æœ¬ä¸­æ��å�–ç¬¬ä¸€ä¸ªæ—¥æœŸã€‚
    
    æ”¯æŒ�:
      "2026å¹´5æœˆ19æ—¥"  â†’ 2026-05-19
      "2026-05-19"     â†’ 2026-05-19
      "2026/05/19"     â†’ 2026-05-19
      "2026.05.19"     â†’ 2026-05-19
    u1   (\d{4})\s*å¹´\s*(\d{1,2})\s*æœˆ\s*(\d{1,2})\s*æ—¥r   r•   r   Ú02dr–   z(\d{4})[-/.](\d{2})[-/.](\d{2})r)   )r*   r5   r7   Úint)r€   r[   s     r#   Úextract_date_from_textr›   œ  s�   € ô 
�‰ÐGÈÓ	N€BÙ	Ø—(‘(˜1“+�˜a¤ B§H¡H¨Q£KÓ 0°Ð5°Q´s¸2¿8¹8ÀA»;Ó7GÈÐ6LÐMÐMä	�‰Ð5°tÓ	<€BÙ	Ø—(‘(˜1“+�˜a §¡¨£˜}¨A¨b¯h©h°q«k¨]Ð;Ð;Ør2   c                 ó2  — i t         ¥ddi¥}||dœ|¥}t        j                  j                  | t	        j
                  |«      j                  d«      |¬«      }	 t        j                  j                  |dt        ¬«      }t	        j                  |j                  «       j                  d«      «      }	|r<|j                  d«      D ](  }
t        |	t        «      r|	j                  |
g «      }	Œ&|	c S  t        |	t         «      r|	S g S # t"        $ r
}Y d	}~y	d	}~ww xY w)
u­  
    æ¨¡å¼�Aï¼šé€šè¿‡API JSONèŽ·å�–åˆ—è¡¨é¡µã€‚
    
    ç”¨æ³•:
        data = fetch_list_via_api(API_URL, page=1, page_size=20,
                                  data_key='data.list',
                                  dept_id=90, column_id=35663)
        for item in data:
            print(item['title'], item['pub_url'])
    
    å�‚æ•°:
        data_key: ç‚¹å�·åˆ†éš”çš„JSONè·¯å¾„ï¼Œå¦‚ 'data.list' æˆ– 'data.data.list'
    zContent-Typezapplication/json;charset=UTF-8)Ú
page_indexÚ	page_sizer   )Údatar	   é   r
   ú.N)r   r   r   r   ÚjsonÚdumpsÚencoder   r   Úloadsr   r   rS   Ú
isinstanceÚdictÚgetÚlistr   )Úapi_urlÚpagerž   Údata_keyÚkwargsr	   r}   r    r!   ÚresultÚkeyr"   s               r#   Úfetch_list_via_apir°   µ  sø   € ð L”ÐK˜.Ð*JÑK€GØ¨YÑA¸&ÐA€DÜ
�.‰.×
 Ñ
  ¬t¯z©z¸$Ó/?×/FÑ/FÀwÓ/OÐY`Ð
 Ó
a€CðÜ�~‰~×%Ñ% c°2¼sÐ%ÓCˆÜ—‘˜DŸI™I›K×.Ñ.¨wÓ7Ó8ˆáØ—~‘~ cÓ*ò "�Ü˜f¤dÔ+Ø#ŸZ™Z¨¨RÓ0‘Fà!’Mð	"ô
 $ F¬DÔ1ˆvÐ9°rÐ9øÜò Üûðús   ÁBD Ã.D ÄD Ä	DÄDc                 óè  — t        | «      }|sg S |xs g d¢}g }t        «       }t        j                  ||t        j                  «      D ]¦  }|j                  d«      j                  «       }t        j                  dd|j                  d«      «      j                  «       }|r|sŒ[||v rŒ`|j                  d«      st        | |«      }||v rŒ‚|j                  |«       |j                  ||dœ«       Œ¨ |S )u  
    æ¨¡å¼�Bï¼šé€šè¿‡HTMLè§£æž�åˆ—è¡¨é¡µé“¾æŽ¥ã€‚
    
    ç”¨æ³•:
        items = fetch_list_via_html(
            'https://www.example.com/list',
            r'<a href="(/detail/\d+\.html)">(.*?)</a>',
            exclude_titles=['æ³•å¾‹å£°æ˜Ž', 'éš�ç§�ä¿�æŠ¤'],
        )
    )u   æ³•å¾‹å£°æ˜Žu   éš�ç§�ä¿�æŠ¤u   ç½‘ç«™å£°æ˜Žu   å…³äºŽæˆ‘ä»¬u   è�”ç³»æˆ‘ä»¬r   r?   r)   r   Úhttp)rF   r   )r$   Úsetr*   rO   r6   r7   r8   r+   rQ   r   ÚaddrP   )	Úlist_urlÚlink_patternÚexclude_titlesr-   rg   Úseenrm   ÚhrefrF   s	            r#   Úfetch_list_via_htmlrº   Õ  sÞ   € ô �HÓ€DÙØˆ	Ø#ÒwÒ'w€NØ€EÜ‹5€DÜ�[‰[˜ t¬R¯Y©YÓ7ò 4ˆØ�w‰w�q‹z×ÑÓ!ˆÜ—‘�z 2 q§w¡w¨q£zÓ2×8Ñ8Ó:ˆÙ™DØØ�NÑ"ØØ�‰˜vÔ&Ü˜8 TÓ*ˆDØ�4‰<ØØ�‰�ŒØ�‰˜u¨TÑ2Õ3ð4ð €Lr2   c              +   ó¾  K  — d}d}||k  rÉg }	|rPi |¥}
|
j                  |xs d|«       |
j                  d|«       t        |fi |
¤Ž}|€nŠt        |t        «      r|ng }	nL| rId| v r| j	                  |¬«      n!d| vr|dkD  r| j                  d	«      › d
|› d�n| }|rt        ||«      ng }	nn)|	sn&d}|	–— |dz  }t        j                  d«       ||k  rŒÉ|sg –— yy­w)u`  
    æ¨¡å¼�Cï¼šåˆ†é¡µæŠ“å�–ï¼ˆè‡ªåŠ¨ç¿»é¡µï¼‰ã€‚
    
    HTMLåˆ†é¡µç”¨æ³•:
        for items in fetch_list_paginated(
            list_url='https://example.com/list_{page}.html',
            link_pattern=r'<a href="(/detail/\d+\.html)">(.*?)</a>',
            max_pages=20
        ):
            for item in items:
                ...

    APIåˆ†é¡µç”¨æ³•:
        for items in fetch_list_paginated(
            api_url='https://example.com/api/list',
            page_param='page_index', page_size=20,
            max_pages=100, dept_id=90
        ):
            for item in items:
                ...
    r   Fr«   rž   Nz{page})r«   ú{rE   Ú_z.htmlTç333333Ó?)	Ú
setdefaultr°   r¦   r©   Úformatrk   rº   r   r   )rµ   rª   Ú
page_paramr¶   Ú	max_pagesrž   Ú
api_kwargsr«   Úyielded_anyrg   ÚparamsrZ   r   s                r#   Úfetch_list_paginatedrÆ   ö  s  è ø€ ð0 €DØ€KØ
�)Ò
ØˆÙØ#˜
�^ˆFØ×Ñ˜jÒ2¨F°DÔ9Ø×Ñ˜k¨9Ô5Ü$ WÑ7°Ñ7ˆCØˆ{ØÜ% c¬4Ô0‘C°b‰EÙØ08¸HÑ0D�(—/‘/ t�/Ô,Ø;>ÀhÑ;NÐSWÐZ[ÒS[�X—_‘_ SÓ)Ð*¨!¨D¨6°Ñ7Øð ñ ?KÔ'¨¨\Ô:ÐPR‰EàáØØˆØŠØ�‰	ˆÜ�
‰
�3Œð/ �)Ó
ñ2 Ø‹ð ùs   ‚CCÃCc                 ó²   — t        j                  | «      }|j                  d«       |j                  d«       |j	                  «        |j                  «        y)u   ç¡®ä¿� DB æœ‰æ‰€éœ€çš„è¡¨ç»“æž„úPRAGMA journal_mode=WALuT  
        CREATE TABLE IF NOT EXISTS crawl_results (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            site_id INTEGER NOT NULL,
            title TEXT NOT NULL,
            url TEXT UNIQUE NOT NULL,
            content TEXT,
            publish_date TEXT,
            summary TEXT,
            domain TEXT,
            category TEXT DEFAULT 'gov',
            crawled_at TEXT DEFAULT (datetime('now','localtime')),
            content_hash TEXT
        );
        CREATE INDEX IF NOT EXISTS idx_results_url ON crawl_results(url);
        CREATE INDEX IF NOT EXISTS idx_results_domain ON crawl_results(domain);
        CREATE INDEX IF NOT EXISTS idx_results_date ON crawl_results(publish_date);
        CREATE INDEX IF NOT EXISTS idx_results_site ON crawl_results(site_id);

        CREATE TABLE IF NOT EXISTS crawl_sites (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            name TEXT NOT NULL,
            url TEXT NOT NULL,
            domain TEXT,
            crawl_method TEXT DEFAULT 'py_script',
            crawl_script TEXT,
            status TEXT DEFAULT 'å¾…çˆ¬å�–',
            last_crawl_at TEXT,
            total_crawled INTEGER DEFAULT 0,
            enabled INTEGER DEFAULT 1,
            created_at TEXT DEFAULT (datetime('now','localtime')),
            updated_at TEXT DEFAULT (datetime('now','localtime'))
        );
    N)Úsqlite3ÚconnectÚexecuteÚexecutescriptÚcommitÚclose)Údb_pathÚconns     r#   Úinit_dbrÑ   1  sE   € ä�?‰?˜7Ó#€DØ‡L�LÐ*Ô+Ø×Ñð !ô !	ðD 	‡K�K„MØ‡J�J…Lr2   c                   ó
  — e Zd ZdZ ee«      Z ee«      Z ee«      Z ee«      Z ee	«      Z	 ee
«      Z
 ee«      Z ee«      Z ee«      Z ee«      Z ee«      Z ee«      Zdd„Zd„ Zd„ Zd„ Zd„ Zdd„Zd	„ Zd
„ Zd„ Zy)Ú
GovCrawleru½  
    æ”¿åºœç«™ç‚¹çˆ¬è™«åŸºç±»ï¼ˆä½›å†ˆæ¨¡å¼� v3ï¼‰ã€‚
    
    æ‰€æœ‰å­�ç±»è‡ªåŠ¨èŽ·å¾—ä»¥ä¸‹èƒ½åŠ›ï¼š
    
    # è¯¦æƒ…é¡µ
    extract_detail()         â€” 4ç§�æ­£æ–‡å®¹å™¨è‡ªåŠ¨å°�è¯• + æ ‡é¢˜/æ—¥æœŸ/é™„ä»¶æ��å�–
    clean_content()          â€” HTMLæ¸…æ´—ï¼ˆåŽ»script/styleï¼‰
    extract_plain_text()     â€” HTMLâ†’çº¯æ–‡æœ¬ + å™ªå£°è¿‡æ»¤
    clean_noisy_html()       â€” æ¸…æ´—è®ºå�›HTMLï¼ˆfont/div alignå™ªéŸ³ï¼‰
    
    # åˆ—è¡¨é¡µ
    fetch_list_via_api()     â€” API JSON æ¨¡å¼�
    fetch_list_via_html()    â€” HTML é“¾æŽ¥æ��å�–æ¨¡å¼�
    fetch_list_paginated()   â€” åˆ†é¡µè‡ªåŠ¨ç¿»é¡µï¼ˆç”Ÿæˆ�å™¨ï¼‰
    
    # æ—¥æœŸ
    extract_date_from_url()  â€” ä»ŽURLè·¯å¾„æ��å�–
    extract_date_from_text() â€” ä»Žæ–‡æœ¬ä¸­æ��å�–
    
    # æ•°æ�®å¤„ç�†
    store_item()             â€” æŒ‰ URL åŽ»é‡�å­˜å‚¨
    sync_to_server()         â€” å¢žé‡�å�Œæ­¥åˆ°æœ�åŠ¡å™¨ + é‡�å�¯ search_app
    http_get()               â€” HTTP GETï¼ˆè‡ªåŠ¨é‡�è¯•ï¼‰
    Nc                 ó8  — || _         || _        || _        || _        d | _        ddddœ| _        t        t        j                  d   «      j                  | _
        || _        |r-t        t        |z  «      | _        t        | j                  «       y t         | _        y )Nr   )ÚnewÚskipr   )Ú	site_nameÚdomainr   Úsite_idÚsessionÚ_statsr   ÚsysÚargvÚstemÚ_crawler_nameÚ
sync_delayÚstrÚBASE_DIRrÏ   rÑ   Ú
DEFAULT_DB)Úselfr×   rØ   r   rÙ   Údb_namerà   s          r#   Ú__init__zGovCrawler.__init__‡  s|   € Ø"ˆŒØˆŒØˆŒØˆŒØˆŒØ¨°aÑ8ˆŒÜ!¤#§(¡(¨1¡+Ó.×3Ñ3ˆÔØ$ˆŒáÜœx¨'Ñ1Ó2ˆDŒLÜ�D—L‘LÕ!ä%ˆD�Lr2   c                 ó�   — t        j                  | j                  «      }t         j                  |_        |j                  d«       |S )NrÈ   )rÉ   rÊ   rÏ   ÚRowÚrow_factoryrË   )rä   rÐ   s     r#   Ú_get_dbzGovCrawler._get_db™  s2   € Ü�‰˜tŸ|™|Ó,ˆÜ"Ÿ;™;ˆÔØ�‰Ð.Ô/Øˆr2   c           	      óŠ  — | j                  «       }	 | j                  rB|j                  d| j                  f«      j                  «       }|r|d   |j	                  «        S |j                  d| j
                  f«      j                  «       }|r&|d   | _        | j                  |j	                  «        S |j                  d| j                  | j                  | j
                  d| j                  df«      }|j                  «        |j                  | _        | j                  |j	                  «        S # |j	                  «        w xY w)Nz%SELECT id FROM crawl_sites WHERE id=?Úidz=SELECT id FROM crawl_sites WHERE domain=? ORDER BY id LIMIT 1zdINSERT INTO crawl_sites (name, url, domain, crawl_method, crawl_script, status) VALUES (?,?,?,?,?,?)Ú	py_scriptu	   å¾…çˆ¬å�–)rê   rÙ   rË   ÚfetchonerÎ   rØ   r×   r   rß   rÍ   Ú	lastrowid)rä   ÚdbÚrowÚcurs       r#   Úensure_sitezGovCrawler.ensure_site¡  sþ   € Ø�\‰\‹^ˆð	Ø�|Š|Ø—j‘jÐ!HÈ4Ï<É<È/ÓZ×cÑcÓe�ÙØ˜t™9ð  �H‰H�Jð —*‘*ØOØ—‘�ó÷ ‰h‹jð ñ Ø" 4™y�”Ø—|‘|ð �H‰H�Jð —*‘*ØvØ—‘ §¡¨4¯;©;¸ÀT×EWÑEWÐYdÐeóˆCð �I‰IŒKØŸ=™=ˆDŒLØ—<‘<à�H‰H�JøˆB�H‰H�Jús   ’=D0 Á AD0 Â3A,D0 Ä0Ec                 óæ   — | j                   sy | j                  «       }	 |j                  d|| j                   f«       |j                  «        |j	                  «        y # |j	                  «        w xY w)NzRUPDATE crawl_sites SET status=?, updated_at=datetime('now','localtime') WHERE id=?)rÙ   rê   rË   rÍ   rÎ   )rä   Ústatusrð   s      r#   Ú
set_statuszGovCrawler.set_status¹  sS   € Ø�|Š|ØØ�\‰\‹^ˆð	Ø�J‰JÐkØ §¡Ð-ô/à�I‰IŒKà�H‰H�JøˆB�H‰H�Jús   Ÿ.A ÁA0c                 ó  — | j                   sy | j                  «       }	 |j                  d| j                  d   | j                  | j                   f«       |j                  «        |j                  «        y # |j                  «        w xY w)Nu¶   UPDATE crawl_sites SET status='å·²å®Œæˆ�', last_crawl_at=datetime('now','localtime'), total_crawled=total_crawled+?, crawl_script=?, updated_at=datetime('now','localtime') WHERE id=?rÕ   )rÙ   rê   rË   rÛ   rß   rÍ   rÎ   )rä   rð   s     r#   Úupdate_statszGovCrawler.update_statsÄ  si   € Ø�|Š|ØØ�\‰\‹^ˆð	Ø�J‰Jðsà—‘˜UÑ# T×%7Ñ%7¸¿¹ÐFôð
 �I‰IŒKà�H‰H�JøˆB�H‰H�Jús   ŸAA6 Á6Bc                 óô  — | j                   st        d«      ‚|r%t        j                  dd|«      j	                  «       }|€|r| j                  |«      dd n|r|dd nd}t        j                  |xs dj                  «       «      j                  «       }| j                  «       }	 |j                  d| j                   |||xs d||| j                  d	|f	«       |j                  «        |j                  d
kD  r| j                  dxx   dz  cc<   n| j                  dxx   dz  cc<   |j#                  «        y# t         $ r!}| j                  dxx   dz  cc<   Y d}~Œ6d}~ww xY w# |j#                  «        w xY w)u•   
        å­˜å‚¨å�•æ�¡è®°å½•ã€‚
        - content = åŽŸå§‹HTML
        - summary = è‡ªåŠ¨ç”Ÿæˆ�ï¼ˆå¦‚æžœæœªæ��ä¾›ï¼‰
        - æŒ‰ URL åŽ»é‡�
        u   è¯·å…ˆè°ƒç”¨ ensure_site()rw   rx   Nr†   é,  r)   z”INSERT OR IGNORE INTO crawl_results (site_id, title, url, content, publish_date, summary, domain, category, content_hash) VALUES (?,?,?,?,?,?,?,?,?)Úgovr   rÕ   r   rÖ   r   )rÙ   ÚRuntimeErrorr*   r+   r8   rT   ÚhashlibÚmd5r¤   Ú	hexdigestrê   rË   rØ   rÍ   Útotal_changesrÛ   r   rÎ   )	rä   rF   r   rG   rH   rJ   Úchrð   r"   s	            r#   Ú
store_itemzGovCrawler.store_itemÔ  sQ  € ð �|Š|ÜÐ;Ó<Ð<ñ Ü—f‘f˜Y¨°Ó8×>Ñ>Ó@ˆGàˆ?Ù@G�d×-Ñ-¨gÓ6°t¸Ñ<Ñ]bÈeÐTXÐUXÉkÐhjˆGä�[‰[˜'š- R×/Ñ/Ó1Ó2×<Ñ<Ó>ˆØ�\‰\‹^ˆð	Ø�J‰Jð-ð —‘˜u c¨7ª=°b¸$ÀÈÏÉÐV[Ð]_Ð`ô	ð �I‰IŒKØ×Ñ !Ò#Ø—‘˜EÓ" aÑ'Ô"à—‘˜FÓ# qÑ(Ó#ð �H‰H�Jøô ò 	'Ø�K‰K˜Ó! QÑ&×!Ð!ûð	'ûð �H‰H�Jús+   Â&BD8 Ä8	E"ÅEÅE% ÅE"Å"E% Å%E7c                 óÀ  — t        dt        › d�«       | j                  «       }|j                  d| j                  f«      j                  «       }|j                  «        |st        d«       yd„ }g }|D ]j  \  }}}}}	|xs ddd }|	xs ddd	 }	|j                  d
 ||«      › d ||«      › d ||«      › d ||xs d«      › d ||	«      › d| j                  › d�«       Œl |j                  d«       dj                  |«      }
ddl
}ddl}|j                  dd¬«      }t        |d«      5 }|j                  |
«       ddd«       t        j                   ddd|t        › d|› �gdd¬«       t        j                   dddddt        dt"        › d|› d �gddd!¬"«      } |j$                  |«       t        j                   dddddt        d#|› �gdd$¬«       d%|j&                  v rGt        d&t)        |«      › d'�«       t        j                   dddddt        d(gdd¬«       t        d)«       yt        d*|j*                  dd+ xs |j&                  dd+ › �«       y# 1 sw Y   �ŒxY w),uE   å¢žé‡�å�Œæ­¥æœ¬ç«™ç‚¹æ•°æ�®åˆ°æœ�åŠ¡å™¨ search.db + é‡�å�¯ search_appu   
ðŸ“¤ å�Œæ­¥åˆ°æœ�åŠ¡å™¨ (z)...z`SELECT title, url, content, publish_date, summary FROM crawl_results WHERE site_id=? ORDER BY idu!     â�­ï¸� æ— æ•°æ�®ï¼Œè·³è¿‡å�Œæ­¥Nc                 óJ   — | €ydt        | «      j                  dd«      z   dz   S )Nz''ú')rá   r   )Úvs    r#   Úescz&GovCrawler.sync_to_server.<locals>.esc  s(   € Øˆy Øœ˜Q›Ÿ™¨¨TÓ2Ñ2°SÑ8Ð8r2   r)   i@  rú   ziINSERT OR IGNORE INTO gov_raw (title, page_url, content, publish_date, summary, site_name, tags) VALUES (ú,z,'u   ','çŽ¯è¯„é˜¶æ®µ');uC   SELECT 1 /* noop: gov_search ç”±è§¦å�‘å™¨ç»´æŠ¤, æ— éœ€ rebuild */;rv   r   z.sqlz/tmp)ÚsuffixÚdirÚwÚscpz-ozStrictHostKeyChecking=noú:Té   )Úcapture_outputr   ÚsshzConnectTimeout=10zsqlite3 z < z && echo OKéx   )r  r€   r   zrm -f rd   ÚOKu     âœ… u    æ�¡å�Œæ­¥æˆ�åŠŸz`pkill -f search_app; sleep 1; cd /root && nohup python3 search_app.py > /var/log/srch.log 2>&1 &u     âœ… search_app å·²é‡�å�¯u     âœ— å�Œæ­¥å¤±è´¥: rb   )ÚprintÚ
SERVER_SSHrê   rË   rÙ   ÚfetchallrÎ   rP   r×   rR   ÚtempfileÚosÚmktempÚopenÚwriteÚ
subprocessÚrunÚSERVER_SEARCH_DBÚunlinkÚstdoutrN   Ústderr)rä   rð   Úrowsr  Ú	sql_linesrF   Úpage_urlrG   Úpub_daterJ   Úsqlr  r  ÚtmpÚfr®   s                   r#   Úsync_to_serverzGovCrawler.sync_to_serverú  s¢  € äÐ+¬J¨<°tÐ<Ô=Ø�\‰\‹^ˆØ�z‰zØnØ�\‰\ˆOó
÷ ‰(‹*ð 	ð 	�‰Œ
áÜÐ5Ô6Øò	9ð ˆ	Ø;?ò 	Ñ7ˆE�8˜W h°Ø’} " e tÐ,ˆGØ’} " d sÐ+ˆGØ×Ñðá˜u›:˜, a©¨H« °a¹¸G»°~ÀQÁsÈ8Ê>ÐWYÓGZÐF[Ð[\Ñ]`ÐahÓ]iÐ\jÐjlÐmq×m{Ñm{Ðl|ð  }OðPõð	ð 	×ÑÐ^Ô_Ø�i‰i˜	Ó"ˆ÷ 	Ø�o‰o V°ˆoÓ8ˆÜ�#�s‹^ð 	˜qØ�G‰G�CŒL÷	ô 	�‰Ø�DÐ4°c¼j¸\ÈÈ3È%Ð;PÐQØ¨õ	
ô
 —‘Ø�DÐ-¨tÐ5OÔQ[ØÔ(Ð)¨¨S¨E°Ð=ð?à d°Cô
ˆð
 	ˆ�	‰	�#ŒÜ�‰Ø�DÐ4°dÐ<OÔQ[Ø�c�Uˆ^ðà¨õ	
ð
 �6—=‘=Ñ Ü�Fœ3˜t›9˜+Ð%5Ð6Ô7Ü�N‰NØ˜Ð8¸$Ð@SÔU_Øsðuà#¨Rõô
 Ð.Õ/äÐ(¨¯©°t¸Ð)<Ò)SÀÇÁÈdÈsÐ@SÐ(TÐUÕV÷9	ñ 	ús   Ä*IÉIc           	      ó@  — t        j                   «       }t        dd› �«       t        d| j                  › d| j                  › d�«       t        d| j                  › �«       t        d› «       | j                  «       }t        d|› �«       | j                  d«       	 | j                  «        | j                  «        t        j                   «       |z
  }| j                  }t        dd› �«       t        d|d   › d|d   › d|d   › �«       t        d|d›d�«       |d   d	kD  r| j                  «        y t        d«       y # t        $ rT}d	d l	}t        d
|› �«       |j                  «        | j                  d«       | j                  dxx   dz  cc<   Y d }~y d }~ww xY w)Nrv   z2==================================================u   ðŸ�  z (ú)z   DB: u   ðŸ“‹ site_id=u	   çˆ¬å�–ä¸­r   u   
â�Œ çˆ¬å�–å¼‚å¸¸: u   å¤±è´¥r   r   uZ   â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€u   âœ… æ–°å¢ž: rÕ   u    | è·³è¿‡: rÖ   u    | é”™è¯¯: u   â�±ï¸� è€—æ—¶: z.1fÚsu$     â�­ï¸� æ— æ–°æ•°æ�®ï¼Œè·³è¿‡å�Œæ­¥)r   r  r×   rØ   rÏ   ró   rö   Údo_crawlr   Ú	tracebackÚ	print_excrÛ   rø   r(  )rä   ri   Úsidr"   r-  Úelapsedr+  s          r#   r  zGovCrawler.run;  sr  € Ü—	‘	“ˆÜ��6�(ˆmÔÜ��d—n‘nÐ% R¨¯© }°AÐ6Ô7Ü�˜Ÿ™�~Ð&Ô'Ü��Ôà×ÑÓ ˆÜ�˜c˜UÐ#Ô$à�‰˜Ô$ð	Ø�M‰MŒOð 	×ÑÔÜ—)‘)“+ Ñ%ˆØ�K‰KˆÜ��8�*ˆoÔÜ�˜Q˜u™X˜J k°!°F±)°¸KÈÈ(ÉÀ}ÐUÔVÜ� ¨˜}¨AÐ.Ô/àˆU‰8�aŠ<Ø×ÑÕ!äÐ8Õ9øô% ò 	ÛÜÐ(¨¨Ð,Ô-Ø×ÑÔ!Ø�O‰O˜HÔ%Ø�K‰K˜Ó! QÑ&Ó!Üûð	ús   ÂE  Å 	FÅ	A
FÆFc                 ó   — t        d«      ‚)Nu   å­�ç±»å¿…é¡»å®žçŽ° do_crawl())ÚNotImplementedError)rä   s    r#   r,  zGovCrawler.do_crawl\  s   € Ü!Ð"AÓBÐBr2   )r)   NNr¾   rˆ   )Ú__name__Ú
__module__Ú__qualname__Ú__doc__Ústaticmethodr^   rL   rT   ry   r1   rM   r°   rº   rÆ   r—   r›   r$   ræ   rê   ró   rö   rø   r  r(  r  r,  r‰   r2   r#   rÓ   rÓ   _  sÅ   „ ññ4 " .Ó1€NÙ  Ó/€MÙ%Ð&8Ó9ÐÙ#Ð$4Ó5ÐÙ'Ð(<Ó=ÐÙ*Ð+BÓCÐÙ%Ð&8Ó9ÐÙ&Ð':Ó;ÐÙ'Ð(<Ó=ÐÙ(Ð)>Ó?ÐÙ)Ð*@ÓAÐÙ˜HÓ%€Hó&ò$òò0	òó "òL=WòB:óBCr2   rÓ   )é   r   rˆ   )NNFN)r   r    z	data.list)NNr«   Néd   r    )/r6  r  r*   rÉ   rý   r   r¢   r-   rŽ   r  rÜ   ÚsslÚurllib.requestr   r   Úpathlibr   Úurllib.parser   Ú__file__ÚparentÚresolverâ   rá   rã   r  ÚSERVER_CRAWLER_DBr  Ú_create_unverified_contextr   r   r$   r1   r4   r=   r^   rL   ry   rM   rT   r—   r›   r°   rº   rÆ   rÑ   rÓ   r‰   r2   r#   ú<module>rC     sú   ðñ$÷L d× c× c× c× cÓ cÝ Ý Ý  á�‹>× Ñ ×(Ñ(Ó*€Ù�Ð0Ñ0Ó1€
à €
Ø.Ð Ø$Ð ð %€c×$Ñ$Ó&€àð 3ð€ó
ò&ò:Ð ó6ð ?CØ59óhòVò:ò<&óRòLò&ó2ó@ðB BHØEGó4òv'÷\~Cò ~Cr2   