Ë
    €Ûµ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 ddl	m
Z
 ddlmZ dZdZdZd	Zd
ZdZdZdZdddedœZd„ Zd„ Zd„ Zd„ Zdd„Zd„ Zd„ Zd„ Zedk(  r e«        yy)u1  
Crawler for ç¥�åŽ¿äººæ°‘æ”¿åºœ - é€šçŸ¥å…¬å‘Š (qixian.gov.cn)
CMS: è‡ªå®šä¹‰ ASP.NET MVC
WAF: Baidu Yunjiasu - bypass using IP + Host header
List: ul.newsList > li > a[href] + span (date)
Pagination: /xwzx/tzgs_N (N=1-47), 20/page, 924 total
Detail: div.printArea > div.conTxt > p (paragraphs)
         Title: <title> (strip suffix)
         Date: div.property > span "å�‘å¸ƒæ—¶é—´ï¼šYYYY-MM-DD"

Usage:
    python3 /root/gov_crawler/crawl_qixian_tzgs.py             # Full crawl
    python3 /root/gov_crawler/crawl_qixian_tzgs.py --max-pages 1  # Incremental
é    N)Údatetime)ÚBeautifulSoup)Úurljoinz/root/search.dbu   ç¥�åŽ¿äººæ°‘æ”¿åºœ-é€šçŸ¥å…¬å‘Šu   é€šçŸ¥å…¬å‘Šu   å±±è¥¿zwww.qixian.gov.cnz218.26.234.201z
/xwzx/tzgsé/   zoMozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36z?text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8zzh-CN,zh;q=0.9,en;q=0.8)z
User-AgentÚAcceptzAccept-LanguageÚHostc                 ó   — dt         › | › �S )z!Build URL using IP bypass for WAFúhttp://)ÚBASE_IP)Úpaths    ú&/root/gov_crawler/crawl_qixian_tzgs.pyÚ	build_urlr   (   s   € à”W�I˜d˜VÐ$Ð$ó    c                 óÒ   — t        | «      }	 t        j                  |t        d¬«      }d|_        |S # t
        $ r+}t        d| › d|› �t        j                  ¬«       Y d}~yd}~ww xY w)zFetch a URL with WAF bypassé   ©ÚheadersÚtimeoutúutf-8z  Error fetching ú: ©ÚfileN)	r   ÚrequestsÚgetÚHEADERSÚencodingÚ	ExceptionÚprintÚsysÚstderr)r   ÚurlÚrÚes       r   Ú	fetch_urlr$   -   s]   € ä
�D‹/€CðÜ�L‰L˜¤g°rÔ:ˆØˆŒ
ØˆøÜò ÜÐ! $  r¨!¨Ð-´C·J±JÕ?Üûðús   �$2 ²	A&»!A!Á!A&c                 óR  — t        | «      }	 t        j                  |t        d¬«      }d|_        t        |j                  d«      }d}|j                  d	«      }|r)|j                  d
¬«      }t        j                  dd|«      }d}|j                  dd¬«      }|rS|j                  d«      D ]?  }	|	j                  d
¬«      }
t        j                   d|
«      }|sŒ.|j#                  d«      } n |j                  dd¬«      }d}g }|rŒ|j                  ddg«      D ]  }|j%                  «        Œ |j                  dd¬«      }|rOg }|j                  d«      D ](  }|j                  d
¬«      }|sŒ|j'                  |«       Œ* dj)                  |«      }t+        «       }|j                  dd
¬«      D ]³  }|d   }t        j                   d|t        j,                  «      sŒ.t/        dt0        › �|«      }|j                  d
¬«      xs& |j3                  d«      d   j3                  d «      d!   }||vsŒ€|j5                  |«       |j'                  ||d"œ«       |sŒ¨|d#|› d$|› d%�z  }Œµ ||||fS # t
        $ r1}t        d| › d|› �t        j                  ¬«       d d d g fcY d }~S d }~ww xY w)&Nr   r   r   z  fetch_detail error r   r   úhtml.parserÚ ÚtitleT©Ústripz_[^_]+_[^_]+_[^_]+$ÚdivÚproperty©Úclass_Úspanz(\d{4}-\d{2}-\d{2})é   Ú	printAreaÚscriptÚstyleÚconTxtÚpz

Úa)Úhrefr7   z&\.(pdf|doc|docx|xls|xlsx|rar|zip|txt)$r
   ú/éÿÿÿÿú?r   )Únamer!   u   

é™„ä»¶ï¼š<p><a href="z">z</a></p>)r   r   r   r   r   r   r   r   r    r   ÚtextÚfindÚget_textÚreÚsubÚfind_allÚsearchÚgroupÚ	decomposeÚappendÚjoinÚsetÚIr   ÚBASE_DOMAINÚsplitÚadd)r   r!   r"   r#   Úsoupr(   ÚtÚdate_strÚpropr/   ÚtxtÚmÚpaÚcontentÚattachmentsÚsÚcon_txtÚpartsr5   Úseenr6   r7   Úfull_urlr;   s                           r   Úfetch_detailrZ   ;   s¦  € Ü
�D‹/€Cð$Ü�L‰L˜¤g°rÔ:ˆØˆŒ
ô
 ˜Ÿ™ Ó/€Dð €EØ�	‰	�'Ó€AÙØ—
‘
 �
Ó&ˆä—‘Ð-¨r°5Ó9ˆð €HØ�9‰9�U :ˆ9Ó.€DÙØ—M‘M &Ó)ò 	ˆDØ—-‘- d�-Ó+ˆCÜ—	‘	Ð0°#Ó6ˆAÚØŸ7™7 1›:�Ùð	ð 
�‰�5 ˆÓ	-€BØ€GØ€Ká	à—‘˜h¨Ð0Ó1ò 	ˆAØ�K‰K�Mð	ð —'‘'˜%¨�'Ó1ˆÙØˆEØ×%Ñ% cÓ*ò $�Ø—J‘J T�JÓ*�ÚØ—L‘L •Oð$ð —k‘k %Ó(ˆGô ‹5€DØ�]‰]˜3 Tˆ]Ó*ò 	VˆØ�‰yˆÜ�9‰9Ð>ÀÄbÇdÁdÕKÜ ¬¨Ð6¸Ó=ˆHØ—:‘: D�:Ó)ÒN¨T¯Z©Z¸«_¸RÑ-@×-FÑ-FÀsÓ-KÈAÑ-NˆDØ˜tÒ#Ø—‘˜Ô"Ø×"Ñ"¨D¸Ñ#BÔCÚØÐ!:¸8¸*ÀBÀtÀfÈHÐUÑU‘Gð	Vð �(˜G [Ð0Ð0øôs ò $ÜÐ% d V¨2¨a¨SÐ1¼¿
¹
ÕCØ�T˜4 Ð#Õ#ûð$ús   �#I, É,	J&É5&J!ÊJ&Ê!J&c                 ó®  — | dk(  rt         }nt         › d| › �}t        |«      }|r|j                  dk7  rg S t        |j                  d«      }|j                  dd¬«      }|sg S g }|j                  d«      D ]Ü  }|j                  d	«      }|j                  d
«      }|r|j                  d«      sŒ9|d   j                  «       }	|j                  dd«      j                  «       xs |j                  d¬«      }
t        dt        › �|	«      }|r|j                  d¬«      nd}t        j                  dd|«      d d }|
sŒÆ|sŒÉ|j                  |
||f«       ŒÞ |S )Nr0   Ú_éÈ   r&   ÚulÚnewsListr-   Úlir6   r/   r7   r(   r'   Tr)   r
   ú\s+é
   )Ú	LIST_PATHr$   Ústatus_coder   r<   r=   rA   r   r*   r>   r   rI   r?   r@   rE   )Úpage_numr   r"   rL   r^   Úitemsr`   r6   r/   r7   r(   Úpage_urlrN   s                r   Úextract_list_pagerh   ~   sC  € Ø�1‚}Ü‰ä�˜A˜h˜ZÐ(ˆä�$‹€AÙ�—‘ Ò$Øˆ	ä˜Ÿ™ Ó/€DØ	�‰�4 
ˆÓ	+€BÙØˆ	à€EØ�k‰k˜$Óò 6ˆØ�G‰G�C‹LˆØ�w‰w�v‹ˆÙ˜Ÿ™˜fœØà�‰y�‰Ó ˆØ—‘�g˜rÓ"×(Ñ(Ó*ÒD¨a¯j©j¸t¨jÓ.DˆÜ˜W¤[ MÐ2°DÓ9ˆÙ04�4—=‘= t�=Ô,¸"ˆä—6‘6˜& " hÓ/°°Ð4ˆâ’XØ�L‰L˜% ¨8Ð4Õ5ð6ð  €Lr   c                 ól  — t        d|dz   «      D ]  }	  | «       c S  y
# t        j                  $ r�}dt        |«      v rC||k  r>t	        d|› d|› d|› d|› d�	t
        j                  ¬«       t        j                  |«       n't	        d|› d	|› �t
        j                  ¬«       Y d }~ y
Y d }~Œžd }~ww xY w)Nr0   Úlockedz  z: locked (attempt r8   z), retry in zs...r   z	 failed: F)	ÚrangeÚsqlite3ÚOperationalErrorÚstrr   r   r    ÚtimeÚsleep)ÚfnÚdescÚmax_attemptsÚdelayÚattemptr#   s         r   Ú
with_retryrv   £   s¸   € Ü˜˜L¨1Ñ,Ó-ò 	ˆð	Ù“4ŠKð	ð øô ×'Ñ'ò 	Øœ3˜q›6Ñ! g°Ò&<Ü˜˜4˜&Ð 2°7°)¸1¸\¸NÈ,ÐW\ÐV]Ð]aÐbÔil×isÑisÕtÜ—
‘
˜5Õ!ä˜˜4˜& 	¨!¨Ð-´C·J±JÕ?Ýô "ûð	ús   ”ŸB3²A1B.Â.B3c                  ó€   — t        j                  t        d¬«      } | j                  d«       | j                  d«       | S )Né   )r   zPRAGMA journal_mode=WALzPRAGMA busy_timeout=30000)rl   ÚconnectÚDB_PATHÚexecute©Úconns    r   Úinit_dbr~   ±   s1   € Ü�?‰?œ7¨BÔ/€DØ‡L�LÐ*Ô+Ø‡L�LÐ,Ô-Ø€Kr   c                 óˆ  — |r|d d n|}t        j                  dd|«      j                  «       }|rt        j                  |d¬«      nd}	 | j                  dt        |||j                  «       |||t        |t        f
«      }|j                  dkD  S # t        $ r(}	t        d	|	› �t        j                  ¬
«       Y d }	~	yd }	~	ww xY w)Nr]   ra   ú F)Úensure_asciiz[]zÍINSERT OR IGNORE INTO gov_raw
               (site_name, source_url, page_url, title, publish_date, summary, content, category, attachments, group_name)
               VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)r   z  DB error: r   )r?   r@   r*   ÚjsonÚdumpsr{   Ú	SITE_NAMEÚCATEGORYÚGROUPÚrowcountr   r   r   r    )
r}   r(   rg   Úpublish_daterS   rT   ÚsummaryÚatt_jsonÚcurr#   s
             r   Úsave_articlerŒ   ¸   s´   € Ù&ˆg�d�s‰m¨E€GÜ�f‰f�V˜S 'Ó*×0Ñ0Ó2€GÙ>IŒt�z‰z˜+°EÕ:Èt€HðØ�l‰lð8ô ˜ (¨E¯K©K«M¸<Ø�gœx¨´5ð:ó	
ˆð �|‰|˜aÑÐøÜò Ü�˜Q˜CÐ ¤s§z¡zÕ2Üûðús   ÁAB Â	CÂB<Â<Cc            
      ó  ‡— t         } t        t        j                  «      dkD  r	 t	        t        j                  d   «      } t        dt        › d| › �t        j                  ¬«       t        «       Šd}d}ˆfd„}t        |d	t        › �¬
«       t        dt        › �t        j                  ¬«       t        d| dz   «      D �]’  }t        |«      }|s"t        d|› d�t        j                  ¬«        �nc|t        |«      z  }|D �]  \  }}}|r*|dk  r%t        d|› d|d d › �t        j                  ¬«       Œ4‰j                  d|f«      }	|	j                  «       rŒXdt        › �|v r|j!                  dt        › �d«      }
nd}
|
rt#        |
«      \  }}}}n||dg f\  }}}}|xs |}|xs |}|xs	 d|› d|› d�}|xs g }t%        ‰|||||«      r.|dz  }|dk  r$t        d|› d|d d › �t        j                  ¬«       t'        j(                  d«       �Œ t        d|› dt        |«      › d|› d�t        j                  ¬«       ‰j+                  «        �Œ• ‰j+                  «        ‰j-                  «        t        d|› d |› �t        j                  ¬«       y # t
        $ rb t        j                  d   dv rIt        t        j                  «      dkD  r-	 t	        t        j                  d   «      } n# t
        $ r Y nw xY wY �Œ¿w xY w)!Nr0   )z--max-pagesé   z	Scraping z, max pages: r   r   c                  ó&   •— ‰ j                  «        y )N)Úcommitr|   s   €r   Údo_cleanzmain.<locals>.do_cleanÞ   s   ø€ à�‰�r   zClean )rr   z  Cleaned old data for z  Page z: 0 articles (end)z
2020-01-01z  Skip old: r€   é(   z)SELECT id FROM gov_raw WHERE page_url = ?r
   r'   ú[z](ú)é   z  + é2   g      à?r   z found, z totalz
Done! Found: z, New: )ÚTOTAL_PAGESÚlenr   ÚargvÚintÚ
ValueErrorr   r„   r    r~   rv   rk   rh   r{   ÚfetchonerI   ÚreplacerZ   rŒ   ro   rp   r�   Úclose)Ú	max_pagesÚ	total_newÚtotal_foundr‘   ÚpnÚarticlesr(   rg   Údater‹   Údetail_pathÚ	det_titleÚdet_dateÚdet_contentÚdet_attsÚfinal_titleÚ
final_dateÚfinal_contentÚ
final_attsr}   s                      @r   Úmainr®   Ì   sá  ø€ Ü€IÜ
Œ3�8‰8ƒ}�qÒð	ÜœCŸH™H Q™KÓ(ˆIô 
ˆI”i�[ ¨i¨[Ð
9ÄÇ
Á
ÕKÜ‹9€DØ€IØ€Kôô ˆx ¤y kÐ2Õ3Ü	Ð#¤I ;Ð
/´c·j±jÕAä�A�y 1‘}Ó%ó (ˆÜ$ RÓ(ˆÙÜ�G˜B˜4Ð1Ð2¼¿¹ÕDÚà”s˜8“}Ñ$ˆà%-ó 	Ñ!ˆE�8˜TÙ˜˜|Ò+Ü˜ T F¨!¨E°#°2¨J¨<Ð8¼s¿z¹zÕJØð —,‘,ÐJÈXÈKÓXˆCØ�|‰|Œ~Øð œ˜Ð&¨(Ñ2Ø&×.Ñ.°¼¸Ð/FÈÓK‘à �ÙÜ=IÈ+Ó=VÑ:�	˜8 [±(à=BÀDÈ"ÈbÐ=PÑ:�	˜8 [°(Ø#Ò, uˆKØ!Ò) TˆJØ'ÒI¨Q¨{¨m¸2¸h¸ZÀqÐ+IˆMØ!š RˆJä˜D +¨x¸À]ÐT^Ô_Ø˜Q‘�	Ø ’>Ü˜D  ¨A¨k¸#¸2Ð.>Ð-?Ð@ÄsÇzÁzÕRä�J‰J�sŽOð;	ô> 	�˜�t˜2œc (›m˜_¨H°Y°K¸vÐFÌSÏZÉZÕXØ�‰ŽðQ(ðT 	‡K�K„MØ‡J�J„LÜ	ˆO˜K˜=¨°	¨{Ð
;Ä#Ç*Á*ÖMøô ò 	Ü�x‰x˜‰{Ð.Ñ.´3´s·x±x³=À1Ò3DðÜ #¤C§H¡H¨Q¡KÓ 0‘IøÜ!ò Ùðýð		ús5   ¥J Ê:LËK.Ë-LË.	K:Ë7LË9K:Ë:LÌ LÚ__main__)zDB oprb   r•   )Ú__doc__r   r?   r‚   rl   ro   Úosr   r   Úbs4r   Úurllib.parser   rz   r„   r…   r†   rI   r   rc   r—   r   r   r$   rZ   rh   rv   r~   rŒ   r®   Ú__name__© r   r   ú<module>r¶      s    ðñ÷ 2× 1× 1Ó 1Ý Ý Ý  à
€Ø-€	Ø€Ø€Ø!€Ø
€Ø€	Ø€ð DØOØ0Øñ	€ò%ò
	ò>1òF óJòòò(DNðN ˆzÒÙ…Fð r   