zoukankan      html  css  js  c++  java
  • 股票行情短信提示软件[转]

    http://purplefans.ucoz.com/

    一个不错的移动方面的参考:

    http://haozesfx.codeplex.com/

    下面是一个网上淘的解决问题的方法:

    Reminder是我最近开发的一个股票行情短信提示软件(刚做完,还是不够稳定。。)。开发这个小东东的想法缘起前段时间在首页看到一篇介绍开放Web Service的文章,其中有个Web Service就是获取实时股票行情的,看到后突然有了做个行情短信提示软件的想法,主要也是由于个人需求驱动,接着。。。革命开始了。。

      Reminder的基础功能很简单:

      1、实时获取股票行情;

      2、根据股票行情判断是否需要进行提示;

      3、发送短信提示;

      

      可是做起来也挺花时间。。。。接下来逐一介绍吧,这里主要提供思路,代码比较简单,也完成的比较仓促,就不全发了。

      1、获取股票行情

      虽然做Reminder的想法缘起Web Service,不过最后实现的时候是调用了新浪的股票行情接口, 之所以选用后者处于两方面的原因:第一,出于稳定性的考虑,觉得新浪比较靠谱。。第二,个人感觉使用更方便一点,并且一次访问可以提取多个股票行情,配置多只股票的话,访问次数少。代码很简单:

     1         /// <summary>
     2         /// 发出http get请求 获取返回的信息
     3         /// </summary>
     4         /// <param name="url">例:http://hq.sinajs.cn/list=sh0000001</param>
     5         /// <returns></returns>
     6          public string HttpGet(string url)
     7         {
     8             string[] list = new string[2];
     9             HttpWebRequest request = null;
    10             HttpWebResponse response = null;
    11             string responseHTML = string.Empty;
    12 
    13             request = (HttpWebRequest)WebRequest.Create(url);
    14             request.Method = "GET";
    15             //返回HTML
    16             response = (HttpWebResponse)request.GetResponse();
    17             Stream dataStream = response.GetResponseStream();
    18             StreamReader reader = new StreamReader(dataStream, Encoding.GetEncoding("gb2312"));
    19             responseHTML = reader.ReadToEnd();
    20 
    21             return responseHTML;
    22         }

      得到返回的HTML之后当然就是进行处理,这里只贴出返回数据的格式,具体应用中要如何定义数据结构请自便。。

    返回的HTML
     /// <summary>
            
    /// 解析从 WebRequest返回的HTML数据,将其处理成为StockInfo对象
            
    /// </summary>
            
    /// <param name="stockHtml">       
            
    /// 返回的HTML:
            
    ///var hq_str_sh601003 = " 柳钢股份,5.04,5.05,5.24,5.50,4.96,5.24,5.25,16079772,84917716,11047,5.24,
            
    /// 53100,5.23,30300,5.22,24400,5.21,93000,5.20,54500,5.25,44600,5.26,48943,5.27,41154,5.28,40170,
            
    /// 5.29,2010-08-24,15:02:07";
            
    /// 
            
    ///0:”大秦铁路”,股票名字;
            
    ///1:”27.55″,今日开盘价;
            
    ///2:”27.25″ ,昨日收盘价;
            
    ///3:”26.91″,当前价格;
            
    ///4:”27.55″,今日最高价;
            
    ///5:”26.20″ ,今日最低价;
            
    ///6:”26.91″,竞买价,即“买一”报价;
            
    ///7:”26.92″ ,竞卖价,即“卖一”报价;
            
    ///8:”22114263″ ,成交的股票数,由于股票交易以一百股为基本单位,所以在使用时,通常把该值除以一百;
            
    ///9:”589824680″ ,成交金额,单位为“元”,为了一目了然,通常以“万元”为成交金额的单位,所以通常把该值除以一万;
            
    ///10:”4695″,“买一”申请4695 股,即47手;
            
    ///11:”26.91″,“买一”报价;
            
    ///12:”57590″ ,“买二”
            
    ///13:”26.90″,“买二”
            
    ///14:”14700″ ,“买三”
            
    ///15:”26.89″ ,“买三”
            
    ///16:”14300″,“买四”
            
    ///17:”26.88″,“买四”
            
    ///18:”15100″ , “买五”
            
    ///19:”26.87″,“买五”
            
    ///20:”3100″,“卖一”申报3100股,即31手;
            
    ///21:”26.92″,“卖一”报价
            
    ///(22, 23), (24, 25), (26,27), (28, 29) 分别为“卖二”至“卖四的情况”
            
    ///30:”2008-01-11″ ,日期;
            
    ///31:”15:05:32″,时间;</param>
            
    /// <returns></returns>
            private Dictionary<string ,StockInfo> stockHtmlDeal(string stockHtml)

      2、根据股票行情判断是否需要进行提示;

      定义一个timer对象,一段时间对新浪股票行情接口访问一次,根据自己的需要编写股票行情提示条件判断方法【判断方法不在此赘述】,每个一段时间调用一次:

     1         /// <summary>
     2         /// 定时器
     3         /// </summary>
     4         System.Timers.Timer Time = new System.Timers.Timer(30000);//1000为1秒
     5 
     6         private void TimeSet()
     7         {
     8             Time.Elapsed += new ElapsedEventHandler(ListenerToStock);
     9             Time.AutoReset = true;//设置是执行一次(false)还是一直执行(true); 
    10             Time.Enabled = true;//是否执行System.Timers.Timer.Elapsed事件;
    11         }
    12 
    13         private void ListenerToStock(object sender, ElapsedEventArgs e)
    14         {
    15              //todo:读股票行情,根据一定算法,判断是否发送提示信息。
    16         }

      3、发送短信提示;

      这个部分花费了我大量时间。。并且目前还没达到自己满意的程度,如有可能,还会在这个环节的处理继续加强。

      不过就这部分的开发来说,对我来说是挺有趣的。

      A、现实如此残酷。。。

      开发之前的想法,是以前经常看到一些Fetion的接口,觉得发短信很简单的,找个来调用就可以了,真到了要用的时候,发现网络上基本没有能发送成功的接口。。小弟不才,如果哪位大哥知道,请指点一下,不胜感激~~~~

      B、免费的午餐。。。不怎么可口

      颇费了一番周折之后,基本放弃了调用Fetion接口发短信的想法,折腾中看到免费的午餐 ——编程利用Google日历API发短信、Email,心花怒放,赶紧下了Google Data API,摸索一下Google Calendar的使用,用上了,收到短信提示的时候那叫一个开心~~

      小小Reminder终于快要见到曙光了 ~~~~

       然而,没开心多久,免费的午餐还是不那么好吃的。。。Google Calendar的SMS提示功能用起来很不稳定(可能也是我插入数据频繁),经常延迟很久甚至收不到消息,并且短信提示的内容也不够多(应该说是比较短) ,做到后期,基本感觉到如果用谷歌的提示,Reminder是没什么实用性了。。

      C、终于吃到了可口的免费的午餐

      最后我又想到了Fetion 。。。折腾阿。。想分析一些在用的飞信第三方软件,还特地跑到一个同学那里去请教请教,他做通信方面的,这方面比我强是肯定。。看到他用的139.com邮箱,里面有飞信功能,回家后自己也注册一个,居然看到还有新邮件免费短信提醒功能!!

    上图。。。

     

     

      我笑了。。。。真是踏破铁鞋无觅处,得来全不费工夫阿。。。。没那么时间去搞协议分析,真要搞怕要搞到明年了。。。我还是捡现成的吧。。。设置了短信提醒功能后,写个发邮件的方法,用发邮件触发移动的短信提示,而且提示的内容还相当全。。。搞定~出于偷懒的原因。。代码中直接写入了自己的邮箱信息,当然密码是加密了的,配置文件中配置toMailAddress,如果多个用户的话,相当于用我的邮箱往多个指定邮箱发邮件而已。

    发送邮件
     1 using System;
     
    2 using System.Collections.Generic;
     
    3 using System.Text;
     
    4 using System.Net.Mail;
     
    5 using System.Net;
     
    6 namespace ReminderService
     
    7 {
     
    8     public class ReminderExtend 
     
    9     {
    10          private static string from = "××××××@139.com";//发件人邮件地址
    11          private static string userName = "××××××@139.com";//登录smtp主机时用到的用户名,注意是邮件地址'@'以前的部分
    12          private static string password = "××××××";//登录smtp主机时用到的用户密码
    13          private static string smtpHost = "smtp.139.com";//发送邮件用到的smtp主机
    14 
    15         /// <summary>
    16         /// 发送邮件
    17         /// </summary>
    18         /// <param name="to">收件人邮件地址</param>
    19         /// <param name="from">发件人邮件地址</param>
    20         /// <param name="subject">邮件主题</param>
    21         /// <param name="body">邮件内容</param>
    22         /// <param name="username">登录smtp主机时用到的用户名,注意是邮件地址'@'以前的部分</param>
    23         /// <param name="password">登录smtp主机时用到的用户密码</param>
    24         /// <param name="smtpHost">发送邮件用到的smtp主机</param>
    25         public static void Send(string to, string subject, string body)
    26         {
    27             try
    28             {
    29                 MailAddress _from = new MailAddress(from);
    30                 MailAddress _to = new MailAddress(to);
    31                 MailMessage message = new MailMessage(_from, _to);
    32                 message.Subject = subject;//设置邮件主题
    33                 message.IsBodyHtml = true;//设置邮件正文为html格式
    34                 message.Body = body;//设置邮件内容
    35                 SmtpClient client = new SmtpClient(smtpHost);
    36                 //设置发送邮件身份验证方式
    37                 //注意如果发件人地址是abc@def.com,则用户名是abc而不是abc@def.com
    38                 client.Credentials = new NetworkCredential(userName, password);
    39                 client.Send(message);
    40             }
    41             catch
    42             { 要写日志还是干什么自己决定吧。。。}
    43         }
    44         public static void SendList(List<string> toMailList, string subject, string body)
    45         {
    46             foreach (string to in toMailList)
    47             {
    48                 Send(to, subject, body);
    49             }
    50         }
    51     }
    52 } 

      用移动的邮箱发短信,爽就一个字。。。短信世家应该也不缺这点短信吧,嘎嘎。。。邮箱刚发出去,短信就到了~~~我真有种写一篇《免费的午餐  续》来歌颂下移动的冲动。。。太贴心了~~


      为了软件的使用方便【配置股票代码,配置邮箱等】以及“安全”,还有一些附属功能

      【附:由于个人原因,我正常上班时间没有电脑可用。。。只好让小小Reminder寄生在女朋友上班用的电脑上。。太邪恶了。。】

      1、配置使用者信息;

      2、配置股票代码信息;

      3、设置开机启动;

      4、启动时即最小化到托盘;  

      1、读,写XML配置文件,惭愧的发现以前还真没怎么深入过,亲手做了一下,算是对XPath有了一定认识了。

      2、设置开机启动,就是写注册表,没有做成启动时就设置,而是在winform界面做了个 设置/取消  开机启动的按钮。。。咱不是流氓软件哈
        3、启动时即最小化到托盘花了一些时间,也和工作中主要是进行ASP.NET的开发,Winform做的比较少有关系吧。
    最后实现的方法感觉还行,定义了一个类继承ApplicationContext,然后调用Application.Run(ApplicationContext context)方法,跳过了Application.Run(Form mainForm)强制显示form的处理。【简单的在程序中设置form的visible属性解决不了这个问题,因为最后还是会被强制显示

    贴代码了。。

    代码
     1 using System;
     2 using System.Collections.Generic;
     3 
     4 using System.Windows.Forms;
     5 
     6 namespace ReminderService
     7 {
     8     static class Program
     9     {
    10         /// <summary>
    11         /// 应用程序的主入口点。
    12         /// </summary>
    13         [STAThread]
    14         static void Main()
    15         {
    16             Application.EnableVisualStyles();
    17             Application.SetCompatibleTextRenderingDefault(false);
    18             //Application.Run(new ReminderService());
    19 
    20             HideOnStartupApplicationContext context = new HideOnStartupApplicationContext(new ReminderService());
    21             Application.Run(context);
    22            
    23         }
    24     }
    25 
    26     /// <summary>
    27     /// 用于实现持续启动时候不显示,本来用Application.Run(new ReminderService()),会强制显示
    28     /// </summary>
    29     internal class HideOnStartupApplicationContext : ApplicationContext
    30     {
    31         private Form mainFormInternal;
    32 
    33         // 构造函数,主窗体被存储在mainFormInternal
    34         public HideOnStartupApplicationContext(Form mainForm)
    35         {
    36             this.mainFormInternal = mainForm;
    37 
    38             this.mainFormInternal.Closed += new EventHandler(mainFormInternal_Closed);
    39         }
    40 
    41         // 当主窗体被关闭时,退出应用程序
    42         void mainFormInternal_Closed(object sender, EventArgs e)
    43         {
    44             Application.Exit();
    45         }
    46     }
    47 }

      

    程序部署碎碎念http://www.cnblogs.com/stubman/archive/2010/08/31/1814011.html  最后,把程序打包,发给My Girl,教她安好,设置开机启动~~~今天收到了30来条短信,还算不错,不过中间有部分短信延迟。。。看来Reminder还是需要进一步加强哈~~

       期间有过一次更新程序,以为得重新做过一个安装包了,后来确定只需要替换两个文件。。。突然又有了想法, 某些软件的更新应该就是这么做的吧:网络上部署一个存放最新程序的空间,软件启动伴随启动一个update进程,比对当前软件版本与网络空间上最新版本的 版本号,如不一致,则通过这个update进程控制,下载,关闭软件程序,替换文件,重启软件程序。。。。。

      接触winform比较少,说来惭愧,之前还没完整的做过打包,部署等工作,这次算是亲身经历了一回。。My Girl环境还没有.Net Framework。。。略过无数波折。。。。亲身体会到软件部署的难易程度对于软 件生命力的影响何其巨大,要不是我要用,估计她【电脑入门水平】无论如何也不会装个还需要装.NET环境的软件,甚至还装不大来呢。。。抛开平台不说,开 发任何软件,使用(特别是上手)的 简易性永远都是值得追求的。

    文章出处:http://www.cnblogs.com/stubman/archive/2010/08/31/1814011.html

  • 相关阅读:
    JQuery选择器
    锋利的jQuery事件
    gitlab
    mac 启动台图标大小调整
    Mac显示和隐藏文件夹
    vs Code 本地服务器配置
    js获取url后带的参数
    路由守卫
    calc()
    Git 本地仓库与远程仓库链接
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/1814439.html
Copyright © 2011-2022 走看看