@@ -4,11 +4,11 @@ use fancy_regex::Regex;
44pub fn extract_verification_code ( content : & str ) -> Option < String > {
55 let config = Config :: load ( ) . unwrap_or_default ( ) ;
66
7- let keyword_pos = find_first_keyword_position ( content, & config. verification_keywords ) ;
8- if keyword_pos . is_none ( ) {
7+ let keyword_bounds = find_first_keyword_position ( content, & config. verification_keywords ) ;
8+ if keyword_bounds . is_none ( ) {
99 return None ;
1010 }
11- let keyword_pos = keyword_pos . unwrap ( ) ;
11+ let keyword_bounds = keyword_bounds . unwrap ( ) ;
1212
1313 let candidates = extract_candidate_codes ( content, & config. verification_regex ) ;
1414 if candidates. is_empty ( ) {
@@ -20,18 +20,20 @@ pub fn extract_verification_code(content: &str) -> Option<String> {
2020 return None ;
2121 }
2222
23- let result = find_closest_candidate ( filtered_candidates, keyword_pos ) ;
23+ let result = find_closest_candidate ( filtered_candidates, keyword_bounds ) ;
2424
2525 result
2626}
2727
28- fn find_first_keyword_position ( text : & str , keywords : & [ String ] ) -> Option < usize > {
29- // 找到第一个关键词的位置(保留原有的小写匹配逻辑)
28+ fn find_first_keyword_position ( text : & str , keywords : & [ String ] ) -> Option < ( usize , usize ) > {
29+ // 找到第一个关键词的位置,返回(开始位置,结束位置)
3030 let text_lower = text. to_lowercase ( ) ;
3131 for keyword in keywords {
3232 let keyword_lower = keyword. to_lowercase ( ) ;
3333 if let Some ( pos) = text_lower. find ( & keyword_lower) {
34- return Some ( pos) ;
34+ // 示例:[验证][码]534571
35+ // start=0, end=2
36+ return Some ( ( pos, pos + keyword. len ( ) ) ) ;
3537 }
3638 }
3739 None
@@ -72,18 +74,26 @@ fn filter_candidates_step1(candidates: Vec<(String, usize)>, _text: &str) -> Vec
7274 filtered
7375}
7476
75- fn find_closest_candidate ( candidates : Vec < ( String , usize ) > , keyword_pos : usize ) -> Option < String > {
76- // 找到距离关键词最近的候选码,距离不超过100
77+ fn find_closest_candidate ( candidates : Vec < ( String , usize ) > , keyword_bounds : ( usize , usize ) ) -> Option < String > {
78+ // 使用边界距离计算找到最近的候选码
79+ let ( keyword_start, keyword_end) = keyword_bounds;
7780 let mut closest_code: Option < String > = None ;
7881 let mut min_distance = usize:: MAX ;
7982
8083 for ( code, code_pos) in candidates {
81- // 计算距离 (候选码中心到关键词位置的距离)
82- let code_center = code_pos + code. len ( ) / 2 ;
83- let distance = if code_center > keyword_pos {
84- code_center - keyword_pos
84+ let code_start = code_pos;
85+ let code_end = code_pos + code. len ( ) ;
86+
87+ // 根据相对位置计算边界距离
88+ let distance = if code_start >= keyword_end {
89+ // 验证码在关键词右侧:code_start - keyword_end
90+ code_start - keyword_end
91+ } else if code_end <= keyword_start {
92+ // 验证码在关键词左侧:keyword_start - code_end
93+ keyword_start - code_end
8594 } else {
86- keyword_pos - code_center
95+ // 验证码与关键词有重叠,设为0
96+ 0
8797 } ;
8898
8999 if distance < min_distance && distance <= 100 {
@@ -203,7 +213,11 @@ mod tests {
203213 (
204214 "【倒三角】易支撑(登录)——您的账号W8406772本次登录验证码为666684,请勿泄露,有效时间5分钟,如非本人操作请忽略本短信。" ,
205215 Some ( "666684" . to_string( ) )
206- )
216+ ) ,
217+ (
218+ "您好, 请确认是您本人操作,用户15670006000登录验证码为:809198,有效期5分钟。[XXX统一门户]" ,
219+ Some ( "809198" . to_string( ) )
220+ ) ,
207221 ] ;
208222
209223 let mut total_tests = 0 ;
0 commit comments