新足迹

 找回密码
 注册

精华好帖回顾

· 悉尼港游船 - Captain Cook Cruise - Sydney Harbour (2009-1-20) patrickzhu · 简单又好吃的零食--牛肉干 (2006-3-4) moth
· 冬日里,那一碗的温暖 --盲螬豆腐汤 (2007-6-24) astina · 搭配参考宝典,不定期更新~~(电梯见1楼) (2007-7-17) 飞行
Advertisement
Advertisement
查看: 1926|回复: 11

有没有什么办法可以监控一个网页中内容的变化 [复制链接]

发表于 2023-10-17 16:09 |显示全部楼层
此文章由 ozsuccess 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 ozsuccess 所有!转贴必须注明作者、出处和本声明,并保持内容完整
有没有什么办法或软件可以监控一个网页中内容的变化啊,而不用每天到那个网页去看
Advertisement
Advertisement

发表于 2023-10-17 16:14 |显示全部楼层
此文章由 让子弹飞 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 让子弹飞 所有!转贴必须注明作者、出处和本声明,并保持内容完整

发表于 2023-10-18 06:19 |显示全部楼层
此文章由 euroblue 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 euroblue 所有!转贴必须注明作者、出处和本声明,并保持内容完整
一直在用一个叫 Distill Web Monitor 的插件

发表于 2023-10-18 06:46 来自手机 |显示全部楼层
此文章由 swe 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 swe 所有!转贴必须注明作者、出处和本声明,并保持内容完整
需要登录后看页面的吗

发表于 2023-10-18 06:59 |显示全部楼层
此文章由 ozsuccess 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 ozsuccess 所有!转贴必须注明作者、出处和本声明,并保持内容完整
euroblue 发表于 2023-10-18 07:19
一直在用一个叫 Distill Web Monitor 的插件

这个怎么收费的

发表于 2023-10-18 07:08 |显示全部楼层
此文章由 DDD888 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 DDD888 所有!转贴必须注明作者、出处和本声明,并保持内容完整
可以用rust language自己写一个,称为爬虫
Advertisement
Advertisement

发表于 2023-10-18 07:09 |显示全部楼层
此文章由 ozsuccess 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 ozsuccess 所有!转贴必须注明作者、出处和本声明,并保持内容完整
DDD888 发表于 2023-10-18 08:08
可以用rust language自己写一个,称为爬虫

有具体教程吗

发表于 2023-10-18 07:16 |显示全部楼层
此文章由 DDD888 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 DDD888 所有!转贴必须注明作者、出处和本声明,并保持内容完整

这是我过去写的项目里的一部分代码

fn main() -> Result<(), ApplicationError> {
    let (path, config) = read_config()?;
    info!("version 1.0.0.0 config file path {:?}", path);

    let start_time = Instant::now();
    let (sender_string, receiver_string) = unbounded();
    let lines = BufReader::new(
        File::open(config.code_file_name.clone())
            .report_context(ApplicationError::FileOpen(config.code_file_name.clone()))?,
    )
    .lines()
    .filter_map(|line| {
        let trimmed = line.ok()?.trim().to_owned();
        if !trimmed.is_empty() && !trimmed.starts_with('#') {
            Some(trimmed)
        } else {
            None
        }
    })
    .collect::<Vec<_>>();
    for symbol in lines {
        sender_string.send(symbol.to_owned()).unwrap();
    }

    let runtime = Builder::new_multi_thread()
        .enable_all()
        .thread_name("multi-thread")
        .worker_threads(config.worker_threads)
        .build()
        .report_context(ApplicationError::TokioRuntime)?;

    let _ = runtime.block_on(run_tasks(&config, &receiver_string));

    info!(
        "Time elapsed: {} milliseconds",
        Instant::now().duration_since(start_time).as_millis()
    );

    Ok(())
}


pub async fn run_tasks(config: &ApplicationConfig, receiver_string: &Receiver<String>) {
    let tasks: Vec<_> = (0..config.task_count)
        .map(|_| tokio::spawn(my_async_task(config.clone(), receiver_string.clone())))
        .collect();

    for task in tasks {
        let _ = task.await;
    }
}

pub async fn my_async_task(config: ApplicationConfig, the_receiver: Receiver<String>) {
    while let Ok(symbol) = the_receiver.try_recv() {
        match handle_product(&config, &symbol).await {
            Ok(_) => {}
            Err(the_error) => error!("{}", the_error),
        }
    }
}

pub async fn handle_product(
    config: &ApplicationConfig,
    symbol: &str,
) -> Result<(), ApplicationError> {
    let user_agent = config.user_agent.clone();
    /*
    if Path::new(&file_path).exists() {
        contents = read_file(&file_path)?;
    } else {
        */
    let date_start = 1276948800;
    let date_stop = get_today_unixtimestamp();
    let the_url = config
        .data_url
        .replace("{date_start}", &format!("{}", date_start))
        .replace("{date_stop}", &format!("{}", date_stop))
        .replace("{symbol}", symbol);

    info!("{}", the_url);
    let contents = download_url_as_string(&user_agent, &the_url).await?;
    //save_file(&file_path, &contents)?;
    //}

    let price_tick_vec = parse_json(&contents)?;
    let mut price_tick_vec_result = PriceTickAveragesVec::new(&price_tick_vec);
    price_tick_vec_result.calculations()?;

    let mut builder = Builder::default();
    for i in 0..price_tick_vec_result.array.len() {
        builder.append(price_tick_vec_result.array.to_string()?);
    }

    let csv = builder
        .string()
        .report_context(ApplicationError::StringBuilder)?;
    let data_file_path = format!("{}/{}.csv", config.download_files_folder, symbol);
    save_file(&data_file_path, &csv)
}

pub async fn download_url_as_string(
    user_agent: &str,
    url: &str,
) -> Result<String, ApplicationError> {
    let client = Client::new();
    let request_builder = client
        .get(url.clone())
        .header("User-Agent", user_agent)
        .timeout(Duration::from_secs(6));

    let request = request_builder
        .build()
        .report_context(ApplicationError:ownloadUrl)?;

    //info!("Request Headers: {:#?}", request.headers());
    //info!("Request Body: {:#?}", request.body());

    let response = client
        .execute(request)
        .await
        .report_context(ApplicationError:ownloadUrl)?;

    response
        .text()
        .await
        .report_context(ApplicationError:ownloadUrl)
}

pub fn parse_json(contents: &str) -> Result<Vec<riceTick>, ApplicationError> {
    // Parse the JSON data into a serde_json::Value object
    let json: Value = serde_json::from_str(&contents).report_context(ApplicationError::Json)?;

    let json_result = &json["chart"]["result"];
    if let Some(value) = json_result["error"].as_str() {
        error!("{value}");
        bail!(ApplicationError::Json);
    }

    let (timestamp_array, adjclose_array) = parse_json_timestamp_value(json_result)?;

    get_price_timestamp_value_array(&timestamp_array, &adjclose_array)
}

评分

参与人数 1积分 +3 收起 理由
ozsuccess + 3 感谢分享

查看全部评分

发表于 2023-10-18 07:36 |显示全部楼层
此文章由 DDD888 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 DDD888 所有!转贴必须注明作者、出处和本声明,并保持内容完整
我让chatgpt 4给写了段csharp代码,你可以自己改改

using System;
using System.Net.Http;
using System.Timers;
class Program
{
    static HttpClient httpClient = new HttpClient();
    static string lastContent = string.Empty;
    static Timer timer;

    static async void CheckWebPage(object sender, ElapsedEventArgs e)
    {
        try
        {
            // URL of the web page to monitor
            string url = "http://example.com";

            // Download the content of the web page
            string newContent = await httpClient.GetStringAsync(url);

            // Compare with the previous version
            if (lastContent != newContent)
            {
                Console.WriteLine("The web page has changed.");
                lastContent = newContent;
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine("An error occurred: " + ex.Message);
        }
    }

    static void Main(string[] args)
    {
        // Initialize timer and set the interval to 1 minute (60000 milliseconds)
        timer = new Timer(60000);
        timer.Elapsed += CheckWebPage;
        timer.Start();

        // Keep the application running
        Console.WriteLine("Monitoring started. Press [Enter] to exit.");
        Console.ReadLine();
    }
}

发表于 2023-10-18 08:31 |显示全部楼层
此文章由 tghj01 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 tghj01 所有!转贴必须注明作者、出处和本声明,并保持内容完整

发表于 2023-10-18 12:14 |显示全部楼层
此文章由 euroblue 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 euroblue 所有!转贴必须注明作者、出处和本声明,并保持内容完整

有免费的plan
A is A
Advertisement
Advertisement

发表于 2023-10-18 21:35 |显示全部楼层
此文章由 angest 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 angest 所有!转贴必须注明作者、出处和本声明,并保持内容完整
先看内容是页面直接生成还是AJAX出来的
如果是前者再看DOM是否是固定元素
不同情况有不同的监测方式

发表回复

您需要登录后才可以回帖 登录 | 注册

本版积分规则

Advertisement
Advertisement
返回顶部