use std::time::Duration; use log::{info, error}; use chrono::{Local, NaiveDate}; use regex::Regex; use scraper::{Html, Selector}; use sea_orm::{ColumnTrait, EntityTrait, QueryFilter}; use sea_orm::{ActiveModelTrait, ConnectOptions, Database}; use crate::model::prelude::*; use crate::model::{sd, pls, plw}; pub async fn get_data_from_500_com(issue_type: &str, db_url:&str) -> Result { // 数据库连接操作 // let db_url; // if env::var("RUST_ENV").unwrap_or_else(|_|"dev".to_string()) == "dev" { // db_url = "mysql://root:Chenweijia113!@localhost/lottery"; // } else { // db_url = "mysql://root:Chenweijia113!@mysql/lottery"; // } let mut opt = ConnectOptions::new(db_url); opt.max_connections(100) .min_connections(5) .connect_timeout(Duration::from_secs(8)) .acquire_timeout(Duration::from_secs(8)) .idle_timeout(Duration::from_secs(8)) .max_lifetime(Duration::from_secs(8)) .sqlx_logging(true) .sqlx_logging_level(log::LevelFilter::Info) .set_schema_search_path("my_schema"); let db = Database::connect(opt).await.expect("Failed to connect to database"); let url = format!("https://kaijiang.500.com/{}.shtml", issue_type); let client = reqwest::Client::new(); let res = client.get(&url).send().await.expect("Failed to send request"); println!("url: {}, status: {}", url, res.status()); if res.status().is_success() { let document = res.text_with_charset("gb2312").await.unwrap(); let html = Html::parse_document(&document); let issue_selector = Selector::parse(r#"td.td_title01 > span.span_left > a > font.cfont2 > strong"#).expect("selector error"); let issue_iter = html.select(&issue_selector).map(|x| {x.inner_html()}); let issue: String = issue_iter.collect(); let date_selector = Selector::parse(r#"td.td_title01 > span.span_right"#).expect("selector error"); let date_str = html.select(&date_selector).map(|x| {x.inner_html()}).collect::(); let re = Regex::new(r"开奖日期:(.*) 兑奖截止日期:(.*)").unwrap(); let Some(draw_date) = re.captures(date_str.as_str()) else { return Err(String::from("日期解析错误")) }; let draw_date = draw_date.get(1).unwrap().as_str(); let date = NaiveDate::parse_from_str(draw_date, "%Y年%m月%d日").expect("Failed to parse date"); let ball_selector = Selector::parse(r#"li.ball_orange"#).expect("selector error"); let ball_iter = html.select(&ball_selector).map(|x| {x.inner_html()}); let ball: String = ball_iter.collect(); let ret_val = ball.clone(); let numbers : Vec = ball.chars().map(|c| c.to_digit(10).unwrap() as i32).collect(); let mut seen = std::collections::HashSet::new(); let unique_numbers: Vec<_> = numbers.clone().into_iter().filter(|&x| seen.insert(x)).collect(); // 只有当元素被成功插入时(即它是唯一的),才包含它 // let max = numbers.iter().max().unwrap_or(&0); // let min = numbers.iter().min().unwrap_or(&0); let sum = numbers.iter().sum::(); let code_small = numbers.iter().filter(|&&x| x < 5).count() as i32; let code_big = numbers.iter().filter(|&&x| x >= 5).count() as i32; let code_single = numbers.iter().filter(|&&x| x % 2 == 1).count() as i32; let code_double = numbers.iter().filter(|&&x| x % 2 == 0).count() as i32; if issue_type == "sd" { let sd_record = Sd::find().filter(sd::Column::DrawIssue.eq(issue.clone())).one(&db).await.map_err(|e| e.to_string())?; if sd_record.is_none() { let group_type = if unique_numbers.len() == 3 { 6 } else if unique_numbers.len() == 2{ 3 } else {1}; let sd_model = sd::Model { draw_issue:issue.into(), draw_code: ball.into(), draw_date: Some(date), created_at: Some(Local::now().naive_local()), sum_num: sum.into(), code_small: code_small.into(), code_big: code_big.into(), code_single: code_single.into(), code_double: code_double.into(), hundred: numbers[0].into(), ten: numbers[1].into(), one: numbers[2].into(), sum_hundred_one: (numbers[0] + numbers[2]).into(), sum_hundred_ten: (numbers[0] + numbers[1]).into(), sum_ten_one: (numbers[1] + numbers[2]).into(), group_type: group_type.into(), ..Default::default() }; let new_model = sd::ActiveModel::from(sd_model); new_model.insert(&db).await.map_err(|_e| "福彩3D数据插入失败")?; } } else if issue_type == "pls" { let pls_record = Pls::find().filter(pls::Column::DrawIssue.eq(issue.clone())).one(&db).await.map_err(|e| e.to_string())?; if pls_record.is_none() { let group_type = if unique_numbers.len() == 3 { 6 } else if unique_numbers.len() == 2{ 3 } else {1}; let pls_model = pls::Model { draw_issue:issue.into(), draw_code: ball.into(), draw_date: Some(date), created_at: Some(Local::now().naive_local()), sum_num: sum.into(), code_small: code_small.into(), code_big: code_big.into(), code_single: code_single.into(), code_double: code_double.into(), hundred: numbers[0].into(), ten: numbers[1].into(), one: numbers[2].into(), sum_hundred_one: (numbers[0] + numbers[2]).into(), sum_hundred_ten: (numbers[0] + numbers[1]).into(), sum_ten_one: (numbers[1] + numbers[2]).into(), group_type: group_type.into(), ..Default::default() }; let new_model = pls::ActiveModel::from(pls_model); new_model.insert(&db).await.map_err(|_e| "排列3数据插入失败")?; } } else if issue_type == "plw" { let plw_record = Plw::find().filter(plw::Column::DrawIssue.eq(issue.clone())).one(&db).await.map_err(|e| e.to_string())?; if plw_record.is_none() { let plw_model = plw::Model { draw_issue:issue.into(), draw_code: ball.into(), draw_date: Some(date), created_at: Some(Local::now().naive_local()), sum_num: sum.into(), code_small: code_small.into(), code_big: code_big.into(), code_single: code_single.into(), code_double: code_double.into(), ten_thousand: numbers[0].into(), thousand: numbers[1].into(), hundred: numbers[2].into(), ten: numbers[3].into(), one: numbers[4].into(), sum_hundred_one: (numbers[2] + numbers[4]).into(), sum_hundred_ten: (numbers[2] + numbers[3]).into(), sum_ten_one: (numbers[3] + numbers[4]).into(), sum_first_3: (numbers[0] + numbers[1] + numbers[2]).into(), sum_next_3: (numbers[1] + numbers[2] + numbers[3]).into(), ..Default::default() }; let new_model = plw::ActiveModel::from(plw_model); new_model.insert(&db).await.map_err(|_e| "排列五数据插入失败")?; } } // 返回获取的数据 Ok(ret_val) } else { Err(String::from("获取数据失败")) } } pub async fn notify_msg(issue_type: &str, notify_urls: &Vec, res: Result) -> Result<(), String> { let lottery_type = match issue_type { "ssq" => "双色球", "dlt" => "大乐透", "pls" => "排列3", "plw" => "排列5", "sd" => "福彩3D", _ => "未知", }; let fmt = "%Y年%m月%d日 %H:%M:%S"; let msg = match res { Ok(val) => { let msg = format!("{}: {}数据采集完毕, 最新数据为: {}!", chrono::Local::now().format(fmt), lottery_type, val); info!("{}", msg); msg }, Err(e) => { let msg = format!("{}: {}数据采集失败: {}!", chrono::Local::now().format(fmt), lottery_type, e); error!("{}", msg); msg } }; for notify_url in notify_urls { let notify = reqwest::get(format!("{}/{}", notify_url, msg)).await.unwrap(); if notify.status().is_success() { info!("{}: {}数据采集通知发送成功", chrono::Local::now().format(fmt), lottery_type); } else { error!("{}: {}数据采集通知发送失败", chrono::Local::now().format(fmt), lottery_type); } } Ok(()) }