
    <|j                        d Z ddlmZ ddlmZmZ ddlmZ ddlmZ ddl	m
Z
 ddlmZ dd	lmZ dd
lmZ ddlmZ ddlmZ  ed      Z ed       G d d             ZddZddZ	 	 d	 	 	 	 	 	 	 	 	 	 	 ddZddZy)uE   当日抓取器 - 针对指定板块抓取当日含关键字的帖子    )annotations)	dataclassfield)datetime)ZoneInfo   )config)ForumFetcher)parse_thread_posts)parse_topic_list)
get_parser)PriceRecordzAsia/ShanghaiT)slotsc                  ~    e Zd ZU dZded<   ded<   ded<   ded<   ded<   d	ed
<   ded<   ded<    ee      Zded<   y)MatchedPostu$   匹配关键字并解析后的帖子inttopic_idboard_idstrtitleurlauthor_namer   last_update_timematched_keyword	post_text)default_factoryzlist[PriceRecord]coin_recordsN)__name__
__module____qualname____doc____annotations__r   listr        &/opt/daily-market/src/daily_crawler.pyr   r      s@    .MMJ	HN&+D&AL#Ar%   r   c                >    t         j                  D ]
  }|| v s|c S  y)u8   返回命中的第一个关键字，未命中返回 NoneN)r	   KEYWORDS)textkws     r&   _match_keywordsr+   "   s&    oo :I r%   c                    d|  S )Nz/index.asp?boardid=r$   )r   s    r&   _build_board_urlr-   *   s     
++r%   c                   g }d}t        |      }||k  r| d| }	t        d| d| d       	 | j                  |	      \  }
}t        d	       t	        |
|| j
                  j                        }t        d
t        |       d       |s	 |S |D cg c]5  }|j                  j                  t              j                  d      |k(  r|7 }}t        dt        |       d       |s	 |S |D ]  }t        |j                        }|st        d| d|j                  dd         	 | j                  |j                        \  }}t!        || j
                  j                  |j"                  |j$                  |j&                        }|r|d   j(                  nd}|st        |      }|xs |}|r|j+                  |||j                  |j                  |j                  |j$                  |d       |j-                  t/        |j                  ||j                  |j                  |j$                  |j                  ||             [t1        |      }g }|r		  ||      }t
        j4                  j                  |d      }t7        j8                  t              j;                         }|D ]  }|j=                  i d|d|d|d|j                  d|j                  d|j                  d |j$                  d!|j>                  d"|j@                  d#|jB                  d$|jD                  d%|jF                  d&|jH                  d'|jJ                  d(|jL                  d)|jN                  d*|jP                  d+|i        |j-                  t/        |j                  ||j                  |j                  |j$                  |j                  |||,	              |dz  }||k  r|S # t        $ r}t        d| d| d|        Y d}~|S d}~ww xY wc c}w # t        $ r&}t        d|j                   d|        Y d}~Ud}~ww xY w# t2        $ r&}t        d|j                   d|        Y d}~d}~ww xY w)-uy   抓取指定板块当天的匹配帖子。

    sample_mode=True 时仅存原始帖子正文，不做价格解析。
    r   z&page=u   [crawl] 抓取板块u   第u   页...u   [warn] 板块u   页抓取失败: Nu   [crawl] 解析主题列表...u   [crawl] 发现u	   个主题z%Y-%m-%du   [crawl] 当日主题: u   个u   [crawl] 命中标题关键字 'z': (   u#   [warn] 主题抓取失败 topic_id=: )htmlbase_urldefault_author_keydefault_author_namedefault_profile_urlr    )
trade_dater   r   r   r   r   r   )r   r   r   r   r   r   r   r   u   [warn] 解析失败 topic_id=r7   r   
board_typer   topic_title	topic_urlr   name	ref_priceprice_detailsunitquantityquantity_unitpackage_reqquality_reqother_notesraw_text
fetched_at)	r   r   r   r   r   r   r   r   r   ))r-   printgetRuntimeErrorr   r	   r2   lenr   
astimezoneASIA_SHANGHAIstrftimer+   r   r   r   r   
author_keyr   profile_urlr)   save_raw_postappendr   r   	Exception
BOARD_TYPEr   now	isoformatsave_price_recordr;   r<   r=   r>   r?   r@   rA   rB   rC   rD   )fetcherdbr   r7   sample_mode	max_pagesmatched_postspage	board_urlpage_urlr1   _exctopicsttoday_topicstopictitle_kw
topic_htmlpostsr   
content_kw
matched_kwparser_funcrecordsr8   rE   recs                               r&   crawl_board_todayrl   .   s    (*MD *I
)
[tf-$XJc$v>?	kk(+GD!
 	-/!$'..2I2IJs6{m956b [ 
!!,,];DDZPT^^ 
 
 	&s<'8&9=>P M " b	E&u{{3H3H:SSbAQ@RST 'EII 6
A
 ' 00#(#3#3$)$5$5$)$5$5E */aBI )3J#/xJ  ", ( %"[[ 99#(#4#4!*"  $$["^^%++		 % 1 1%*%;%;$.'	& 	  %X.K)+GS))4G
  **..x<J!m4>>@J $$ & *&& !*& 	&
 "5;;&  & "5#4#4& CHH&  & $S%6%6& CHH& & $S%6%6& "3??& "3??&  "3??!&" #&$ !*%& ,   !kkII!--!&!7!7 *#$
" 
qb	H 		y )
| s  	M(3tf4EcUKLn s	
$   ;ENN;K2cUSTd ! S9%..9IC5QRRSsM   O' :P'PQ	'	P0P

P	Q QQ		Q8Q33Q8c           	        ddl }|j                  |d       |j                  j                  |d| d      }t	        |dd	      5 }t        | d
      D ]  \  }}|j                  d d       |j                  d| d|j                   d       |j                  d|j                   d       |j                  d|j                   d       |j                  d|j                   d       |j                  d|j                   d       |j                  d d       |j                  |j                  dz           	 ddd       |S # 1 sw Y   |S xY w)uB   将匹配帖子正文写入样本文件，供设计解析器参考r   NT)exist_okboardz_samples.txtwzutf-8)encodingr   z<============================================================
u   样本 r0   zURL: u   作者: u   命中关键字: u   更新时间: z<------------------------------------------------------------z

)osmakedirspathjoinopen	enumeratewriter   r   r   r   r   r   )rZ   r   
sample_dirrs   ru   fiposts           r&   save_sample_filer~      s>   KK
TK*77<<
eH:\$BCD	dC'	* 	-a 2 	-GAtGGxjO$GGgaS4::,b12GGeDHH:R()GGht//034GG'(<(<'=R@AGGnT%:%:$;2>?GGxjO$GGDNNV+,	-	- K	- Ks   C9E

EN)r)   r   returnz
str | None)r   r   r   r   )F
   )rV   r
   r   r   r7   r   rX   boolrY   r   r   list[MatchedPost])rZ   r   r   r   rz   r   r   r   )r!   
__future__r   dataclassesr   r   r   zoneinfor   r6   r	   rV   r
   forum_threadr   forum_topicsr   parsersr   parsers.baser   rK   r   r+   r-   rl   r~   r$   r%   r&   <module>r      s    K " (    ! , *  %) 
B 
B 
B, NN N 	N
 N N Nbr%   