Ë
    Z�vjH&  ã                   ó†  — 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
 ddlmZ  ej                  dd«      Z ej                  dd«      Zd	Zd
ZdZdZdZdddœZd„ Zd„ Zd„ Zd„ Zdd„Zedk(  rI eej:                  «      dkD  rej:                  d   ndZedk(  r e«        yedk(  r e«        y ed«       yy)u  
é‡‘å¡”åŽ¿äººæ°‘æ”¿åºœ - æ°‘æ„�å¾�é›† (å»ºè®¾é¡¹ç›®ç”¨åœ°é¢„é€‰/è®¾è®¡æ–¹æ¡ˆæ‰¹å‰�å…¬ç¤º)
API: /common/search/{channelId}?_isAgg=false&_isJson=true&_pageSize=15
Detail: div.pages_content#UCAP-CONTENT
ç›´æŽ¥å†™å…¥ search.db gov_raw è¡¨ (2026-08-08 ä»Žtempåº“æ–¹æ¡ˆæ”¹å›ž)
é    N)ÚdatetimeÚ	timedelta)ÚBeautifulSoup)ÚurljoinÚ	SEARCH_DBz/root/search.dbÚTEMP_SEARCH_DBu   jtxzf.gov.cn-æ°‘æ„�å¾�é›†úhttps://www.jtxzf.gov.cnÚ 3730d74518314de4bbb641b2add0f85aé   z
2023-06-16zoMozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36z=https://www.jtxzf.gov.cn/jintaxian/c101622/common_list1.shtml)z
User-AgentÚRefererc                 ó´   — | j                  «       }|j                  d«      r	d|dd z   }n|j                  d«      rd|z   }t        j                  dd|«      }|S )	z6API returns http:// with double slash, fix to https://zhttp://zhttps://é   Nú/r	   zhttps://([^/]+)//zhttps://\1/)ÚstripÚ
startswithÚreÚsub)Úraw_urlÚurls     ú /root/gov_crawler/crawl_jtxzf.pyÚfix_urlr      sW   € à
�-‰-‹/€CØ
‡~�~�iÔ Ø˜3˜q˜r˜7Ñ"‰Ø	�‰˜Ô	Ø(¨3Ñ.ˆÜ
�&‰&Ð% ~°sÓ
;€CØ€Jó    c                 ó¦  — 	 t        | «      }t        j                  |t        d¬«      }d|_        |j
                  dk7  ryt        |j                  d«      }|j                  d«      }|r|j                  d¬	«      nd
}|j                  dd¬«      }|s|j                  dd¬«      }|s|j                  dd¬«      }|rè|j                  dd«      d   dz   }|j                  dd¬«      D ]L  }|d   }	|	j                  d«      rŒ|	j                  d«      rŒ,|	j                  d«      rŒ>t        ||	«      |d<   ŒN |j                  dd¬«      D ]L  }
|
d   }|j                  d«      rŒ|j                  d«      rŒ,|j                  d«      rŒ>t        ||«      |
d<   ŒN t        |«      }nd
}||fS # t        $ r}t!        d| › d|› �d¬«       Y d }~yd }~ww xY w)!z&Fetch detail page and extract content.r   ©ÚheadersÚtimeoutzutf-8éÈ   )NNzhtml.parserÚh1T)r   Ú ÚdivzUCAP-CONTENT)ÚidÚpages_content)Úclass_Ú	detailconr   é   r   Úa)Úhrefr'   Úhttpz//zdata:Úimg)Úsrcr*   u   [jtxzf] è¯¦æƒ…é¡µè¯·æ±‚å¤±è´¥ ú: ©ÚflushN)r   ÚrequestsÚgetÚHEADERSÚencodingÚstatus_coder   ÚtextÚfindÚget_textÚrsplitÚfind_allr   r   ÚstrÚ	ExceptionÚprint)r   Úfull_urlÚrespÚsoupÚtitle_elÚtitleÚcontent_divÚbase_for_attachmentsr&   r'   r)   r*   ÚcontentÚes                 r   Ú
get_detailrD   '   sÖ  € ð$Ü˜3“<ˆÜ�|‰|˜H¬g¸rÔBˆØˆŒØ×Ñ˜sÒ"ØÜ˜TŸY™Y¨Ó6ˆð —9‘9˜T“?ˆÙ19�×!Ñ!¨Ð!Ô-¸rˆð —i‘i ¨.�iÓ9ˆÙØŸ)™) E°/˜)ÓBˆKÙØŸ)™) E°+˜)Ó>ˆKáØ#+§?¡?°3¸Ó#:¸1Ñ#=ÀÑ#CÐ Ø ×)Ñ)¨#°DÐ)Ó9ò D�Ø˜‘y�Ø—‘ vÕ.°t·±ÀtÕ7LÐUY×UdÑUdÐelÕUmÜ 'Ð(<¸dÓ C�A�f’IðDð #×+Ñ+¨E°tÐ+Ó<ò D�Ø˜%‘j�Ø—~‘~ fÕ-°c·n±nÀTÕ6JÐSV×SaÑSaÐbiÕSjÜ!(Ð)=¸sÓ!C�C˜’JðDô ˜+Ó&‰GàˆGà�gˆ~ÐøÜò ÜÐ.¨s¨e°2°a°SÐ9ÀÕFÜûðúsB   ‚=F* Á C F* ÄF* ÄF* Ä%=F* Å#F* Å5F* Æ"F* Æ*	GÆ3GÇGc                 ó  — | j                  «       }|j                  d«       	 |j                  d«       dD ]  \  }}	 |j                  d|› d|› d�«       Œ  | j                  «        y# t        $ r Y Œ?w xY w# t        $ r Y ŒLw xY w)zCCreate gov_raw table matching sync_temp_to_main.py expected schema.aS  CREATE TABLE IF NOT EXISTS gov_raw (
        id INTEGER PRIMARY KEY, site_name TEXT, source_url TEXT,
        page_url TEXT, title TEXT, publish_date TEXT,
        date_rank INTEGER DEFAULT 0, summary TEXT, status TEXT,
        category TEXT DEFAULT '', visits INTEGER DEFAULT 0,
        content TEXT DEFAULT '', tags TEXT DEFAULT ''
    )zHCREATE UNIQUE INDEX IF NOT EXISTS idx_temp_page_url ON gov_raw(page_url)))Úidx_temp_snÚ	site_name)Úidx_temp_pubdateÚpublish_datezCREATE INDEX IF NOT EXISTS z ON gov_raw(ú)N)ÚcursorÚexecuter9   Úcommit)ÚconnÚcÚidx_nameÚcolss       r   Úensure_gov_raw_tablerR   P   s™   € à�‰‹€AØ‡I�Ið 	ô 
ðØ	�	‰	Ð\Ô]ð _ò ‰ˆ�$ð	Ø�I‰IÐ3°H°:¸\È$ÈÈqÐQÕRðð
 	‡K�K…Møô ò Ùðûô
 ò 	Ùð	ús"   £A( ½A7Á(	A4Á3A4Á7	BÂBc                  óD  — t        dt        › �d¬«       t        d«      j                  t        «      } | j                  d«       | j                  d«       t        | «       | j                  «       }d}d}d}d}	 t        › d	t        › d
t        › d|› �}	 t        j                  |t        d¬«      }|j                  «       }|j                  di «      j                  dg «      }	|j                  di «      j                  dd«      }
|	s�n‘|
t        z   dz
  t        z  }t        d|› dt!        |	«      › d|› d�d¬«       |	D �]Q  }|j                  dd«      }|j                  dd«      }|j                  d«      xs ddd }|sŒC|t        k  rMt        dt        › d�d¬«       | j#                  «        t        d|› d |› d!|› �d¬«       | j%                  «         yt'        |«      }|j                  d"|f«       |j)                  «       r|dz  }ŒÍt+        |«      \  }}|s|}|rt!        |j-                  «       «      d#k  r|dz  }|dz  }�Œ		 |j                  d$t.        |||||d%d&f«       |j0                  dkD  r|dz  }| j#                  «        n|dz  }�ŒT |dz  }�Œ| j#                  «        | j%                  «        t        d|› d |› d!|› �d¬«       y# t        $ r}t        d|› d|› �d¬«       Y d}~ŒXd}~ww xY w# t        $ r}t        d'|› d|› �d¬«       Y d}~�ŒÞd}~ww xY w)(zFull crawl - all pages.u   [jtxzf] å…¨é‡�æ¨¡å¼�ï¼Œæˆªæ­¢ Tr,   Úsqlite3úPRAGMA journal_mode=WALúPRAGMA busy_timeout=30000r   r%   ú/common/search/ú%?_isAgg=false&_isJson=true&_pageSize=ú3&_template=index&_rangeTimeGte=&_channelName=&page=r   r   ÚdataÚresultsÚtotalõ   [jtxzf] APIè¯·æ±‚å¤±è´¥ page=r+   Nu   [jtxzf] ç¬¬u   é¡µ (u   æ�¡, å…±u   é¡µ)r   r   r?   ÚpublishedTimeStré
   u   [jtxzf] è¾¾åˆ°æˆªæ­¢æ—¥æœŸ u	   ï¼Œå�œæ­¢u   [jtxzf] å®Œæˆ�ï¼�æ–°å¢ž u	   , è·³è¿‡ u   , æ— å†…å®¹ ú)SELECT id FROM gov_raw WHERE page_url = ?r   ú¸INSERT OR IGNORE INTO gov_raw 
                    (site_name, source_url, page_url, title, publish_date, content, status, category)
                    VALUES (?, ?, ?, ?, ?, ?, ?, ?)Ú	publishedõ   çŽ¯è¯„å…¬ç¤ºõ   [jtxzf] æ�’å…¥å¤±è´¥ )r:   ÚCUTOFF_DATEÚ
__import__ÚconnectÚTEMP_DBrL   rR   rK   ÚBASE_URLÚ
CHANNEL_IDÚ	PAGE_SIZEr.   r/   r0   Újsonr9   ÚlenrM   Úcloser   ÚfetchonerD   r   Ú	SITE_NAMEÚrowcount)rN   rO   Ú	new_countÚ
skip_countÚnocontent_countÚpageÚapi_urlr<   rZ   r[   r\   rC   Útotal_pagesÚitemr   r?   Údate_strÚpage_urlÚdetail_titlerB   s                       r   Ú
crawl_fullr|   g   sU  € ä	Ð*¬;¨-Ð
8ÀÕEä�iÓ ×(Ñ(¬Ó1€DØ‡L�LÐ*Ô+Ø‡L�LÐ,Ô-Ü˜ÔØ�‰‹€Aà€IØ€JØ€OØ€Dà
Ü�J˜o¬j¨\Ð9^Ô_hÐ^ið  j]ð  ^bð  ]cð  dˆð	Ü—<‘< ´À"ÔEˆDØ—9‘9“;ˆDØ—h‘h˜v rÓ*×.Ñ.¨y¸"Ó=ˆGØ—H‘H˜V RÓ(×,Ñ,¨W°aÓ8ˆEñ
 ÙàœyÑ(¨1Ñ,´Ñ:ˆÜ�˜D˜6 ¤s¨7£| n°H¸[¸MÈÐNÐVZÕ[àó /	KˆDØ—h‘h˜u bÓ)ˆGØ—H‘H˜W bÓ)ˆEØŸ™Ð!3Ó4Ò:¸¸C¸RÐ@ˆHáØàœ+Ò%ÜÐ3´K°=À	ÐJÐRVÕWØ—‘”ÜÐ0°°¸9ÀZÀLÐP\Ð]lÐ\mÐnÐvzÕ{Ø—
‘
”Ùä˜wÓ'ˆHð �I‰IÐAÀHÀ;ÔOØ�z‰zŒ|Ø˜a‘�
Øô %/¨wÓ$7Ñ!ˆL˜'ÙØ$�Ùœc '§-¡-£/Ó2°SÒ8Ø 1Ñ$�Ø˜a‘�
ÙðKØ—	‘	ð7ô  ¨(°LÀ(Ø˜k¨>ð;ô	ð —:‘: ’>Ø ‘N�IØ—K‘K•Mà !‘O�Jùð[/	Kðb 	�‰	ˆñE ðH 	‡K�K„MØ‡J�J„LÜ	Ð$ Y K¨y¸¸ÀLÐQ`ÐPaÐ
bÐjnÖoøô ò 	ÜÐ1°$°°r¸!¸Ð=ÀTÕJÜûð	ûôp ò KÜÐ-¨h¨Z°r¸!¸Ð=ÀT×JÓJûðKús2   ÂA0K ÉAK8Ë	K5ËK0Ë0K5Ë8	LÌLÌLc                 ó
  — t        j                  «       t        | ¬«      z
  j                  d«      }t	        d| › d|› d�d¬«       t        d«      j                  t        «      }|j                  d	«       |j                  d
«       t        |«       |j                  «       }d}d}	 t        › dt        › dt        › d|› �}	 t        j                  |t         d¬«      }|j#                  «       }|j                  di «      j                  dg «      }	|	snñ|	D ]å  }|j                  dd«      }|j                  dd«      }|j                  d«      xs ddd }|r||k  rŒGt'        |«      }|j                  d|f«       |j)                  «       rŒvt+        |«      \  }}|rt-        |j/                  «       «      dk  rŒ£	 |j                  dt0        |||||dd f«       |j2                  dkD  r|dz  }|j5                  «        Œç |dz  }�Œ\|j5                  «        |j7                  «        t	        d"|› �d¬«       y# t$        $ r}
t	        d|› d|
› �d¬«       Y d}
~
ŒRd}
~
ww xY w# t$        $ r}
t	        d!|› d|
› �d¬«       Y d}
~
�Œkd}
~
ww xY w)#z1Incremental crawl for daily config - last N days.)Údaysz%Y-%m-%du   [jtxzf] å¢žé‡�æ¨¡å¼�ï¼Œu   å¤© (rJ   Tr,   rT   rU   rV   r   r%   rW   rX   rY   r   r   rZ   r[   r]   r+   Nr   r   r?   r^   r_   r`   r   ra   rb   rc   rd   u   [jtxzf] å¢žé‡�å®Œæˆ�ï¼�æ–°å¢ž )r   Únowr   Ústrftimer:   rf   rg   rh   rL   rR   rK   ri   rj   rk   r.   r/   r0   rl   r9   r   ro   rD   rm   r   rp   rq   rM   rn   )r~   ÚcutoffrN   rO   rr   ru   rv   r<   rZ   r[   rC   rx   r   r?   ry   rz   Ú_rB   s                     r   Úcrawl_incrementalrƒ   ¿   s�  € ä�l‰l‹nœy¨dÔ3Ñ3×=Ñ=¸jÓI€FÜ	Ð# D 6¨¨v¨h°aÐ
8ÀÕEä�iÓ ×(Ñ(¬Ó1€DØ‡L�LÐ*Ô+Ø‡L�LÐ,Ô-Ü˜ÔØ�‰‹€Aà€IØ€Dà
Ü�J˜o¬j¨\Ð9^Ô_hÐ^ið  j]ð  ^bð  ]cð  dˆð	Ü—<‘< ´À"ÔEˆDØ—9‘9“;ˆDØ—h‘h˜v rÓ*×.Ñ.¨y¸"Ó=ˆGñ
 Øàò 	KˆDØ—h‘h˜u bÓ)ˆGØ—H‘H˜W bÓ)ˆEØŸ™Ð!3Ó4Ò:¸¸C¸RÐ@ˆHá˜h¨Ò/Øä˜wÓ'ˆHà�I‰IÐAÀHÀ;ÔOØ�z‰zŒ|Øä# GÓ,‰JˆAˆwÙœc '§-¡-£/Ó2°SÒ8ØðKØ—	‘	ð7ô  ¨(°E¸8Ø˜k¨>ð;ô	ð —:‘: ’>Ø ‘N�IØ—K‘K”Møð9	Kð@ 	�‰	ˆñ[ ð^ 	‡K�K„MØ‡J�J„LÜ	Ð*¨9¨+Ð
6¸dÖCøôW ò 	ÜÐ1°$°°r¸!¸Ð=ÀTÕJÜûð	ûôH ò KÜÐ-¨h¨Z°r¸!¸Ð=ÀT×JÓJûðKús2   Â?AH2 Æ6AIÈ2	IÈ;IÉIÉ	JÉ$I=É=JÚ__main__r%   ÚfullÚincrementalz0Usage: python3 crawl_jtxzf.py [full|incremental])r   ) Ú__doc__ÚosÚsysr   rl   Útimer.   r   r   Úbs4r   Úurllib.parser   ÚgetenvÚDB_PATHrh   rp   ri   rj   rk   re   r0   r   rD   rR   r|   rƒ   Ú__name__rm   ÚargvÚmoder:   © r   r   ú<module>r“      sÝ   ðñ÷ )× (× (ß (Ý Ý  à
ˆ"�)‰)�KÐ!2Ó
3€Ø
ˆ"�)‰)Ð$Ð&7Ó
8€Ø'€	Ø%€Ø/€
Ø€	Ø€ð DØNñ€òò&òRò.Upóp?DðD ˆzÒÙ˜cŸh™h›-¨!Ò+ˆ3�8‰8�AŠ;°€DØˆv‚~Ù�Ø	�Ò	ÙÕáÐ@ÕAð r   