原文地址:http://www.cnblogs.com/inday/p/weixin-publicf-platform-cnblogs.html
这几天接连发布了《快速开发微信公众平台框架---简介》和《体验微信公众平台快速开发框架》几篇关于微信平台的文章,不过反响一般,可能需求不是很多吧。闲来无事,还是继续改造一下这个框架。
今天更新了框架代码,听取了 @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还不涉及到数据库,暂时都是手工判断。
接下来上传代码,测试一下:
输入博客园:
输入博客园文章:
测试完成,还能凑活用用,后续会用一个统一的文本命令方式,但有点纠结,不知道用什么方式,大家可以提供下意见。目前想到的是:
关键字+命令+参数(可选)
博客园+inday+5(博客园,用户为inday,前5文章)
天气+上海(获取上海今天的天气)
天气+上海+3(获取上海未来3天的天气)
后面会写一系列教程,尽量把常用的消息类型都用到。
PS:求职下吧,上海地区+电子商务类型公司,最好有旅游行业,职位的话无所谓,一个抬头而已,有发展前景,因本人30+了,不太想经常换工作了,薪资12k+就行,对于自我评价,还算是个负责的人,项目也好,学习也好,都会投入进去,对于C#比较精通点,也可以其他语言。需要的Email给我:james#taogame.com(#->@)
PS2:今天收到宝宝的台历了,哈,真嗲