Skip to content

Commit a2b63f9

Browse files
committed
Refine verification code detection with boundary distance
The improved algorithm calculates distance between code and keyword boundaries instead of using center points, providing more accurate matches for verification codes.
1 parent 5f0a8c0 commit a2b63f9

1 file changed

Lines changed: 29 additions & 15 deletions

File tree

src/parser.rs

Lines changed: 29 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@ use fancy_regex::Regex;
44
pub 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

Comments
 (0)