zoukankan      html  css  js  c++  java
  • 微信快速开发框架(五)-- 利用快速开发框架,快速搭建微信浏览博客园首页文章

    这几天接连发布了《快速开发微信公众平台框架---简介》和《体验微信公众平台快速开发框架》几篇关于微信平台的文章,不过反响一般,可能需求不是很多吧。闲来无事,还是继续改造一下这个框架。

    今天更新了框架代码,听取了 @RMay 的建议,加入了一个信息中间件,用来处理xelement,避免了重复解析,所以所有接口都更改了下。此次更新如下:

    1、增加信息中间件MiddleMessage

    2、更改了接口参数类型,把原来的XElement都改成了MiddleMessage

    3、删除了Demo项目,以后都用WebDemo进行演示。

    所有代码都已经更新到我的Gibhub

    介绍了更新内容,下面继续打造我们的Demo项目。

    之前我们写的,都是返回文本信息,今天上午,我加入了一个CnblogsArticleNewsMessageHandler,主要是返回一个ResponseNewsMessage(图文信息),只要发消息:博客园文章,就能获取在首页前5的文章列表,但为了避免给博客园造成鸭梨,我把信息缓存了下,10分钟更新一次。这次主要采用了webclient+正则的方式,采集的方式无所谓,大家都可以自由发挥。

    先看下CnblogsArticleNewsMessageHandler:

    public class CnblogsArticleNewsMessageHandler : IMessageHandler
        {
            public ResponseMessage HandlerRequestMessage(MiddleMessage msg)
            {
                //var request = new RequestTextMessage(xml);
                var response = new ResponseNewsMessage(msg.RequestMessage);
                var cnblogsFeed = new CnBlogsFeed(5);
                var articles = cnblogsFeed.GetTopCnblogsFeed();
                response.ArticleCount = articles.Count;
                response.CreateTime = DateTime.Now.Ticks;
                response.Articles = articles;
    
                return response;
            }
        }

    大家可以看到,接口参数已经改成了MiddleMessage,这样就避免了原先我再new一个RequestMessage了, 直接用了MiddleMessage.RequestMessage。

    CnBlogsFeed是一个自己写的采集类,目的是采集博客园首页数据,数字类型的构造函数,是一个提取数量,因为微信平台的限制,这个值必须在1-10之间。

    因为是图文消息,而博客园呢只在Description中提供了用户的头像,而微信多图文消息会把第一篇文章的图片作为主图,大小为:320*200,所以我把第一张图片做成了默认图片,小图的话如果用户有头像就用用户的头像,如果没有则会显示一个默认小图,大小为:200*200。

    看下CnBlogsFeed类,写的不好,将就看看吧:

    public class CnBlogsFeed
        {
            private int m_topNum = 5;
    
            //缓存过期时间,这里是10分钟
            private static int s_timeout = 10 * 60 * 1000;
            //缓存过期时间
            private static DateTime s_outDate = DateTime.Now;
            //博客园文章列表正则表达式
            private static Regex s_cnblogsIndexRegex = new Regex("<div\s*class="post_item">\s*.*\s*.*\s*.*\s*.*\s*.*\s*.*\s*.*\s*<div\s*class="post_item_body">\s*<h3><a\s*class="titlelnk"\s*href="(?<href>.*)"\s*target="_blank">(?<title>.*)</a>.*\s*<p\s*class="post_item_summary">\s*(?<content>.*)\s*</p>");
            //内容中,用户头像正则表达式
            private static Regex s_picUrlRegex = new Regex("src="(?<picurl>.*)"\s");
            //博客园文章列表uri
            private static string s_cnblogsIndexUri = "http://www.cnblogs.com/mvc/AggSite/PostList.aspx?CategoryId=808&PageIndex=1";
            //默认的一个大图,一个小图的图片地址
            private static string s_defaultBigPicUri = "http://wx.jamesying.com/images/default_title.jpg";
            private static string s_defaultSmallPicUri = "http://wx.jamesying.com/images/default_small.jpg";
    
            //用来缓存请求过来的数据,不高兴用Cache了。
            private static List<Article> s_articles = null;
    
            public CnBlogsFeed(int topNum)
            {
                m_topNum = topNum;
            }
    
            public List<Article> GetTopCnblogsFeed()
            {
                if (s_articles == null)
                {
                    GetTopCnblogsFeed(m_topNum);
                }
                else
                {
                    if (DateTime.Now > s_outDate)
                    {
                        GetTopCnblogsFeed(m_topNum);
                    }
                }
    
                return s_articles;
            }
    
            private void GetTopCnblogsFeed(int m_topNum)
            {
                try
                {
                    var html = GetRemoteUri(s_cnblogsIndexUri, Encoding.UTF8);
                    var matchs = s_cnblogsIndexRegex.Matches(html);
                    var i = 0;
                    s_articles = new List<Article>();
                    foreach (Match match in matchs)
                    {
                        if (i >= m_topNum)
                            break;
                        var article = new Article
                        {
                            Title = match.Groups[2].Value,
                            Url = match.Groups[1].Value,
                            Description = match.Groups[3].Value
                        };
    
                        if (i == 0)
                        {
                            article.PicUrl = s_defaultBigPicUri;
                        }
                        else
                        {
                            var matchPic = s_picUrlRegex.Match(article.Description);
                            if (matchPic.Success)
                            {
                                article.PicUrl = matchPic.Groups[1].Value;
                            }
                            else
                            {
                                article.PicUrl = s_defaultSmallPicUri;
                            }
                        }
    
                        s_articles.Add(article);
    
                        i += 1;
                    }
    
                    s_outDate = DateTime.Now.AddMilliseconds(s_timeout);
                }
                catch(Exception ex)
                {
                    s_articles = null;
                    s_outDate = DateTime.Now;
    #if DEBUG
                    throw ex;
    #endif
                }
    
                //return s_articles;
            }
    
            private string GetRemoteUri(string uri, Encoding encoding)
            {
                var client = new WebClient();
                client.Encoding = encoding;
    
                return client.DownloadString(uri);
            }
        }

    基本工作完成,只要更改之前的TextMessageRole:

    public IMessageHandler MessageRole(MiddleMessage msg)
            {
                var request = (RequestTextMessage)msg.RequestMessage;
    
                if (request.Content.IndexOf("博客园文章") > -1)
                {
                    return new CnblogsArticleNewsMessageHandler();
                }
    
                if (request.Content.IndexOf("博客园") > -1)
                {
                    return new CnblogsTextMessageHandler();
                }
    
                return new DefaultMessageHandler();
            }

    这个规则简陋了点,之后会考虑下,打造一个文本命令的规范,因为Demo还不涉及到数据库,暂时都是手工判断。

    接下来上传代码,测试一下:

    输入博客园:

    image

    输入博客园文章:

    image

    测试完成,还能凑活用用,后续会用一个统一的文本命令方式,但有点纠结,不知道用什么方式,大家可以提供下意见。目前想到的是:

    关键字+命令+参数(可选)

    博客园+inday+5(博客园,用户为inday,前5文章)

    天气+上海(获取上海今天的天气)

    天气+上海+3(获取上海未来3天的天气)

    后面会写一系列教程,尽量把常用的消息类型都用到。

    PS:求职下吧,上海地区+电子商务类型公司,最好有旅游行业,职位的话无所谓,一个抬头而已,有发展前景,因本人30+了,不太想经常换工作了,薪资12k+就行,对于自我评价,还算是个负责的人,项目也好,学习也好,都会投入进去,对于C#比较精通点,也可以其他语言。需要的Email给我:james#taogame.com(#->@)

    PS2:今天收到宝宝的台历了,哈,真嗲

  • 相关阅读:
    给出一个单向链表的头指针,输出该链表中倒数第K个节点的指针
    把二元查找树转变成排序的双向链表
    动态规划0/1背包问题
    判断一字符串是不是对称的
    动态链接库dll,静态链接库lib, 导入库lib(转载)
    基于格点数据分析和表达
    Silverlight Wcf 获取集合数据并绑定(DataContract,DataMember)
    让你学会使用WCF服务端配置
    数据契约(DataContract)
    symbol详解
  • 原文地址:https://www.cnblogs.com/inday/p/weixin-publicf-platform-cnblogs.html
Copyright © 2011-2022 走看看