Ë
    §&˜jØ)  ã                   ó8  — 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mZ ddlm	Z	 ej                  j                  dd«      ZdZdZd	Zd
ZdZddddœZ ej&                  «       Zej*                  j-                  e«       dd„Zd„ Zd„ Zd„ Zd„ Zd„ Zedk(  r e«        yy)u[   
èŒ‚å��è®ºå�›-ã€ŠèŒ‚å��çŽ¯ä¿�ã€‹ä¸“æ � (bbs.gdmm.com/forum-912)
Discuz! forum, GBK charset
é    N)ÚBeautifulSoup)ÚurljoinÚDB_PATHz/root/search.dbzhttps://bbs.gdmm.com/z*https://bbs.gdmm.com/forum-912-{page}.htmlu%   èŒ‚å��è®ºå�›-ã€ŠèŒ‚å��çŽ¯ä¿�ã€‹ä¸“æ �u   è®ºå�›é   zoMozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36z`text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8zzh-CN,zh;q=0.9,en;q=0.8)z
User-AgentÚAcceptzAccept-Languagec                 ó    — 	 t         j                  | d¬«      }||_        |j                  S # t        $ r}t        d|› �«       Y d}~yd}~ww xY w)zFetch and decode HTML.é   ©Útimeoutz  FETCH ERROR: NÚ )ÚsessionÚgetÚencodingÚtextÚ	ExceptionÚprint)Úurlr   ÚrÚes       ú/root/gov_crawler/crawl_gdmm.pyÚ
fetch_htmlr      sK   € ðÜ�K‰K˜ RˆKÓ(ˆØˆŒ
Ø�v‰vˆøÜò Ü� ˜sÐ#Ô$Üûðús   ‚), ¬	AµAÁAc                 ó  — g }d}t        j                  || t         j                  «      D ]_  }|j                  d«      }|j                  d«      }t        j                  dd|«      j                  «       }|sŒM|j                  ||f«       Œa |S )z*Extract (tid, title) from forum list page.zˆ(?:normalthread|stickthread)_(\d+).*?<a[^>]*href="(?:https://bbs\.gdmm\.com/)?thread-\d+-\d+-\d+\.html"[^>]*class="s xst"[^>]*>(.*?)</a>é   é   ú<[^>]+>r   )ÚreÚfinditerÚDOTALLÚgroupÚsubÚstripÚappend)ÚhtmlÚthreadsÚpatternÚmÚtidÚ
title_htmlÚtitles          r   Úextract_threads_from_listr*   *   s~   € à€Gð Z€GÜ�[‰[˜ $¬¯	©	Ó2ò )ˆØ�g‰g�a‹jˆØ—W‘W˜Q“Zˆ
Ü—‘�z 2 zÓ2×8Ñ8Ó:ˆÚØ�N‰N˜C ˜<Õ(ð)ð €Nó    c           
      ó‚	  — ddddg dœ}t        j                  d| «      }|r9t        j                  dd|j                  d«      «      j	                  «       }||d<   t        j                  d| t         j
                  «      }|�rÎ|j                  d«      }t        |d	«      }g }|j                  D �]G  }|j                  d
k(  r(|j                  dd¬«      }	|	sŒ)|j                  |	«       Œ;|j                  dk(  r�|j                  d«      }
g }|
D ]T  }|j                  ddg«      }|D �cg c]  }|j                  d¬«      ‘Œ }}|j                  dj                  |«      «       ŒV |sŒ¹|j                  dj                  |«      «       ŒÚ|j                  dk(  r(|sŒì|d   j                  d«      r�Œ|dxx   dz  cc<   �Œt        |t        «      s�Œ#|j	                  «       }|s�Œ7|j                  |«       �ŒJ dj                  |«      }t        j                  dd|«      }|j	                  «       |d<   |d   s|j                  dd¬«      }||d<   t        j                  d| «      }|r"|j                  d«      j	                  «       |d<   t        j                  d| «      }|rÑ|j                  d«      j!                  dd«      }|j!                  dd«      j!                  dd«      j#                  «       }t%        |«      d k\  rm|d!   |d   j'                  d«      |d   j'                  d«      |d"   j'                  d«      |d    j'                  d«      f\  }}}}}|› d|› d|› d|› d|› d#�
|d$<   n||d$<   t        j(                  d%| t         j
                  «      }|D ]U  \  }}t        j                  dd|«      j	                  «       }t+        t,        |«      }|d&   j                  d'|› d(|› d)�«       ŒW t        j(                  d*| t         j
                  «      }|D ]U  \  }}t        j                  dd|«      j	                  «       }t+        t,        |«      }|d&   j                  d'|› d(|› d)�«       ŒW t        j(                  d+| «      }|d,d- D ]+  }|t        |d&   «      vsŒ|d&   j                  d.|› d)�«       Œ- |S c c}w )/zDExtract subject, content, date, attachments from thread detail page.r   )ÚsubjectÚcontentÚdateÚauthorÚattachmentsz/<span[^>]*id="thread_subject"[^>]*>(.*?)</span>r   r   r-   z.<td[^>]*id="postmessage_(\d+)"[^>]*>(.*?)</td>r   zhtml.parserÚdivú T)Ú	separatorr!   ÚtableÚtrÚtdÚth)r!   z | ú
Úbréÿÿÿÿz

z\n{3,}r.   z!<a[^>]*class="xw1"[^>]*>(.*?)</a>r0   u9   å�‘è¡¨äºŽ\s+(\d{4}[-/]\d{1,2}[-/]\d{1,2}\s+\d{1,2}:\d{2})ú/ú-ú:é   r   é   z:00r/   zC<a[^>]*href="([^"]*forum\.php\?mod=attachment[^"]*)"[^>]*>(.*?)</a>r1   ú[z](ú)z9<a[^>]*href="(attachment\.php\?aid=[^"]*)"[^>]*>(.*?)</a>z!(https?://pan\.baidu\.com[^\s<]*)Nr   u   [ç™¾åº¦ç½‘ç›˜]()r   Úsearchr    r   r!   r   r   ÚchildrenÚnameÚget_textr"   Úfind_allÚjoinÚendswithÚ
isinstanceÚstrÚreplaceÚsplitÚlenÚzfillÚfindallr   ÚBASE_URL) r#   r   Úresultr&   r-   Ú	post_htmlÚsoupÚcontent_partsÚchildÚdiv_textÚrowsÚtable_linesÚrowÚcellsÚcÚ
cell_textsr   Ú	full_textÚdate_strÚpartsÚyÚmoÚdÚhÚmiÚattch_linksÚhrefÚ
clean_textÚfull_urlÚattch_links2Ú	pan_linksÚlinks                                    r   Úextract_detailrm   8   s˜  € ð ØØØØñ€Fô 	�	‰	ÐDÀdÓK€AÙÜ—&‘&˜ R¨¯©°«Ó4×:Ñ:Ó<ˆØ#ˆˆyÑô 	�	‰	ÐCÀTÌ2Ï9É9ÓU€AÚØ—G‘G˜A“Jˆ	Ü˜Y¨Ó6ˆàˆð —]‘]ó 	/ˆEØ�z‰z˜UÒ"Ø Ÿ>™>°C¸t˜>ÓD�ÚØ!×(Ñ(¨Õ2Ø—‘˜wÒ&à—~‘~ dÓ+�Ø �Øò ?�CØŸL™L¨$°¨Ó6�EØBGÖ!H¸Q !§*¡*°4 *Õ"8Ð!H�JÐ!HØ×&Ñ& u§z¡z°*Ó'=Õ>ð?ò Ø!×(Ñ(¨¯©°;Ó)?Õ@Ø—‘˜tÒ#Ú ¨°rÑ):×)CÑ)CÀDÖ)IØ! "Ó%¨Ñ-Õ%Ü˜E¤3Ö'Ø—{‘{“}�ÛØ!×(Ñ(¨Ö.ð+	/ð. —K‘K Ó.ˆ	Ü—F‘F˜9 f¨iÓ8ˆ	Ø%ŸO™OÓ-ˆˆyÑð �iÒ ØŸ™°¸4˜Ó@ˆIØ )ˆF�9Ñô 	�	‰	Ð6¸Ó=€AÙØŸ7™7 1›:×+Ñ+Ó-ˆˆxÑô 	�	‰	ÐNÐPTÓU€AÙØ—7‘7˜1“:×%Ñ% c¨3Ó/ˆØ× Ñ   cÓ*×2Ñ2°3¸Ó<×BÑBÓDˆÜˆu‹:˜Š?Ø# A™h¨¨a©¯©°qÓ(9¸5À¹8¿>¹>È!Ó;LÈeÐTUÉhÏnÉnÐ]^ÓN_ÐafÐghÑai×aoÑaoÐpqÓarÐr‰OˆAˆr�1�a˜Ø !˜s ! B 4 q¨¨¨1¨Q¨C¨q°°°CÐ8ˆF�6ŠNà%ˆF�6‰Nô —*‘*ÐcÐeiÔkm×ktÑktÓu€KØ!ò D‰
ˆˆdÜ—V‘V˜J¨¨DÓ1×7Ñ7Ó9ˆ
Üœ8 TÓ*ˆØˆ}Ñ×$Ñ$ q¨¨°B°x°jÀÐ%BÕCðDô —:‘:ÐZÐ\`Ôbd×bkÑbkÓl€LØ"ò D‰
ˆˆdÜ—V‘V˜J¨¨DÓ1×7Ñ7Ó9ˆ
Üœ8 TÓ*ˆØˆ}Ñ×$Ñ$ q¨¨°B°x°jÀÐ%BÕCðDô —
‘
Ð?ÀÓF€IØ˜"˜1�ò DˆØ”s˜6 -Ñ0Ó1Ò1Ø�=Ñ!×(Ñ(¨?¸4¸&ÀÐ)BÕCðDð €Mùòs "Is   Ä&R<c                 óÀ  — ddl }| st        d«       y|j                  t        d¬«      }|j	                  d«       |j                  «       }|j	                  d«       d}| D ]Í  }|j	                  d|d	   f«       |j                  «       rŒ*|d
   r|d
   dd n|d   }|j	                  d|d   |d
   ||j                  dt        «      |j                  dt        «      |d	   |j                  dd«      |j                  d«      r!dj                  |j                  dg «      «      ndf«       |dz  }ŒÏ |j                  «        |j                  «        t        d|› d�«       y)zSave items to originals.db.r   NzNo items to save.é<   r
   úPRAGMA busy_timeout=30000a¤  
        CREATE TABLE IF NOT EXISTS gov_raw (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            title TEXT,
            content TEXT,
            summary TEXT,
            site_name TEXT,
            group_name TEXT,
            page_url TEXT,
            publish_date TEXT,
            attachments TEXT,
            source_file TEXT,
            crawled_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
        )
    z)SELECT id FROM gov_raw WHERE page_url = ?Úpage_urlr.   éÈ   r-   z«
            INSERT INTO gov_raw (title, content, summary, site_name, group_name, page_url, publish_date, attachments)
            VALUES (?, ?, ?, ?, ?, ?, ?, ?)
        Ú	site_nameÚ
group_namer/   r   r1   r9   r   z	Inserted z new records.)Úsqlite3r   Úconnectr   ÚexecuteÚcursorÚfetchoner   Ú	SITE_NAMEÚ
GROUP_NAMErH   ÚcommitÚclose)Úitemsru   ÚconnÚcurÚ	new_countÚitemÚsummarys          r   Ú
save_to_dbr„   ˜   sT  € ãáÜÐ!Ô"Øà�?‰?œ7¨Bˆ?Ó/€DØ‡L�LÐ,Ô-Ø
�+‰+‹-€Cà‡K�Kð ô 	ð  €IØò ˆØ�‰Ð?À$ÀzÑBRÐATÔUØ�<‰<Œ>Øà+/°	ª?�$�y‘/ $ 3Ñ'ÀÀYÁˆà�‰ð ð �‰OØ�‰OØØ�H‰H�[¤)Ó,Ø�H‰H�\¤:Ó.Ø�ÑØ�H‰H�V˜RÓ Ø6:·h±h¸}Ô6MˆD�I‰I�d—h‘h˜}¨bÓ1Ô2ÐSUð	
ô	ð 	�Q‰‰	ð)ð, 	‡K�K„MØ‡J�J„LÜ	ˆI�i�[ Ð
.Õ/r+   c                  ó  — ddl } | j                  t        d¬«      }|j                  d«       |j	                  «       }|j                  d«       |j
                  }t        d|› d�«       |j                  «        |j                  «        y)	zSync FTS indexes.r   Nro   r
   rp   zì
        INSERT OR IGNORE INTO gov_search (rowid, title, site_name, summary)
        SELECT r.id, r.title, r.site_name, r.summary
        FROM gov_raw r
        LEFT JOIN gov_search f ON f.rowid = r.id
        WHERE f.rowid IS NULL
    zSynced z to gov_search.)	ru   rv   r   rw   rx   Úrowcountr   r|   r}   )ru   r   r€   Úsearch_counts       r   Úsync_ftsrˆ   Ð   sp   € ãØ�?‰?œ7¨Bˆ?Ó/€DØ‡L�LÐ,Ô-Ø
�+‰+‹-€Cà‡K�Kð ô 	ð —<‘<€LÜ	ˆG�L�> Ð
1Ô2ð 	‡K�K„MØ‡J�J…Lr+   c                  ó|  — dd l } | j                  d¬«      }|j                  dt        t        d¬«       |j                  ddd	¬
«       |j                  dt        dd¬«       |j                  ddd¬
«       |j                  «       }|j                  rdn|j                  }|j                  }g }d}t        d|dz   «      D �]µ  }t        d|› d�«       t        j                  |¬«      }t        |«      }	|	st        d|› �«       ŒEt        |	«      }
t        dt        |
«      › d|› �«       |
st        d«       Œx|
D �]*  \  }}|dkD  r||k\  r �nd|› d�}t        d|dz   › d|› d|d d › �«       t        |«      }|st        d«       ŒMt!        ||«      }|d   xs |}|d   }t        |j#                  «       «      d k  rK|j%                  d!«      r!d"j'                  |j%                  d!g «      «      nd#}|rd$|› d%|› d&|› �}n	d$|› d%|› d'�}||||j%                  d(d#«      t(        t*        |j%                  d!g «      d)œ}|j-                  |«       |dz  }t/        j0                  d*«       �Œ- |dkD  s�Œ¯||k\  s�Œ¶ n t        d+t        |«      › d,�«       |r!|j2                  st5        |«       t7        «        t        d-«       y ).Nr   u   Crawl èŒ‚å��è®ºå�›-èŒ‚å��çŽ¯ä¿�)Údescriptionz--max-pageszMax pages to crawl)ÚtypeÚdefaultÚhelpz--testÚ
store_truezTest mode: 1 page only)Úactionr�   z--max-itemszMax items to crawl (0=all)z	--skip-dbzSkip DB save (debug)r   z

=== Page z ===)Úpagez  Failed to fetch page z  Found z threads on page z  No threads found, skippingzhttps://bbs.gdmm.com/thread-z	-1-1.htmlz  [z] TID=z: ro   z    FAILED to fetch detailr-   r.   é   r1   r9   r   z<p><a href="z">u   </a></p>

é™„ä»¶ï¼š
z</a></p>r/   )r-   r.   rq   r/   rs   rt   r1   g      à?z
=== Total: z
 items ===zDone.)ÚargparseÚArgumentParserÚadd_argumentÚintÚ	MAX_PAGESÚ
parse_argsÚtestÚ	max_pagesÚ	max_itemsÚranger   Ú	FORUM_URLÚformatr   r*   rN   rm   r!   r   rH   rz   r{   r"   ÚtimeÚsleepÚskip_dbr„   rˆ   )r’   ÚparserÚargsr™   rš   Ú	all_itemsÚtotal_fetchedr�   r   r#   r$   r'   Ú
list_titleÚ
detail_urlÚdetail_htmlÚdetailr-   r.   Úattachments_textr‚   s                       r   Úmainrª   ç   sã  € ÛØ×$Ñ$Ð1RÐ$ÓS€FØ
×Ñ˜¬C¼ÐI]ÐÔ^Ø
×Ñ˜¨Ð<TÐÔUØ
×Ñ˜¬C¸ÐA]ÐÔ^Ø
×Ñ˜¨LÐ?UÐÔVØ×ÑÓ€Dà—Y’Y‘ D§N¡N€IØ—‘€Ià€IØ€Mä�a˜ Q™Ó'ó 6ˆÜ�˜D˜6 Ð&Ô'Ü×Ñ DÐÓ)ˆÜ˜#‹ˆÙÜÐ+¨D¨6Ð2Ô3Øä+¨DÓ1ˆÜ�œ˜W›˜Ð&7¸°vÐ>Ô?áÜÐ0Ô1Øà&ó $	‰OˆC�Ø˜1Š} °)Ò!;Úà7¸°u¸IÐFˆJÜ�C˜ a™Ð(¨¨s¨e°2°jÀÀ"°oÐ5FÐGÔHä$ ZÓ0ˆKÙÜÐ2Ô3Øä# K°Ó<ˆFà˜YÑ'Ò5¨:ˆGð ˜YÑ'ˆGÜ�7—=‘=“?Ó# bÒ(ØOUÏzÉzÐZgÔOh 4§9¡9¨V¯Z©Z¸ÀrÓ-JÔ#KÐnpÐ Ù#Ø ,¨Z¨L¸¸7¸)ÐCZÐ[kÐZlÐm‘Gà ,¨Z¨L¸¸7¸)À8ÐL�Gð #Ø"Ø&ØŸ
™
 6¨2Ó.Ü&Ü(Ø%Ÿz™z¨-¸Ó<ñˆDð ×Ñ˜TÔ"Ø˜QÑˆMÜ�J‰J�sŽOðI$	ðL �qŒ=˜]¨iÔ7Ùðm6ôp 
ˆMœ#˜i›.Ð)¨Ð
4Ô5á˜ŸšÜ�9ÔÜŒ
ä	ˆ'…Nr+   Ú__main__)Úgbk)Ú__doc__ÚsysÚosr   rž   ÚrequestsÚbs4r   Úurllib.parser   Úenvironr   r   rQ   rœ   rz   r{   r–   ÚHEADERSÚSessionr   ÚheadersÚupdater   r*   rm   r„   rˆ   rª   Ú__name__© r+   r   ú<module>rº      s½   ðñó Û 	Û 	Û Û Ý Ý  à
�*‰*�.‰.˜Ð$5Ó
6€Ø"€Ø8€	Ø3€	Ø€
Ø€	ð DØpØ0ñ€ð ˆ(×
Ñ
Ó
€Ø ‡�× Ñ �wÔ óòò]ò@50òpò.Mð` ˆzÒÙ…Fð r+   