随笔-18  评论-104  文章-8  trackbacks-0

在虚拟主机中用ASP.NET1.1服务器端TIMER定时读取RSS信息到数据库〔原创〕

前段时间作了个博客推广方面的网站:中文博客群(http://www.bokequn.cn),里边有个功能就是可以定时读取博客们的文章信息到数据库中,再显示出来供用户查询和处理TAG.因为是虚拟主机,所以只想到了用服务器端的timer来解决。

当时比较匆忙没来得及优化,水平也很有限,如果大家觉得某些地方不对或者有更好的方式来解决,还请不吝赐教。

我觉得整个过程两个重点:

  1. 如何处理timer
  2. 将读取rss模块化,更方便调用

1.关于timer,当然是写在了Global.asax中,首先建立变量:

System.Timers.Timer t=new System.Timers.Timer(1000*Convert.ToInt16(System.Configuration.ConfigurationSettings.AppSettings["do_time"]));

其中在web.config 中用do_time来存取多久执行一次

接下来在Application_Start中处理:

t.AutoReset=true;
t.Enabled
=true;
if(common.func.get_key("can_do")=="1")//也是在web.config中存取是否进行定时处理,其中common.func.get_key是自定义的获取设置的函数
t.Elapsed +=new System.Timers.ElapsedEventHandler(fun);

函数fun的代码:

private void fun(object sender, System.Timers.ElapsedEventArgs e)

try
{
System.DateTime dt
=System.DateTime.Now;
common.func.write_log(
"开始读取远程XML");//写入日志

rss2sql rl
=new rss2sql();
rl.readall();
System.DateTime dt2
=System.DateTime.Now;
common.func.write_log(
"XML文件导入到数据库成功"+Convert.ToString(dt2-dt));//将本次执行时间写入日志,
}

catch(Exception ex)
{
common.func.write_log(
"读取远程xml文件出现错误:"+ex.Message);//写入日志
}

}


Global.asax中代码完毕

2.接下来就是在rss2sql类中从数据库获取rss列表,根据上次读取rss时间和rss文件的修改时间来读取rss文件并写到数据库中,因为用到了太多自定义的类和方法,所以不列出所有的代码,有兴趣的朋友可以到最后下载,其中比较重要的函数:

/// <summary>
/// 读取指定链接的rss内容到数据库
/// </summary>
/// <param name="id">对应博客的id</param>
/// <param name="url">rss地址</param>
/// <param name="dt">上次读取时间</param>

public void read_from_url(string id,string url,System.DateTime dt)
{
op_db.db_class db1
=new op_db.db_class();
try
{
rssFeed feed 
= new rssFeed(url,dt);//建立一个rss读取类实例
feed.read();//开始读取
if(feed.Channel.Items.Count>0)//如果文章数大于0,开始读取到数据库
{
for(int i=0;i<feed.Channel.Items.Count;i++)
{

write_artical(id,feed.Channel.Items[i].title,feed.Channel.Items[i].link,feed.Channel.Items[i].description,feed.Channel.Items[i].pubDate);
}

db1.sql
="update bokequn set last_rss_date='"+feed.lastModified.ToString()+"' where id="+id;
db1.executesql();
}

}

catch(Exception ex)
{
common.func.write_log(id
+":url:"+url+"错误"+ex.Message+ex.Source+ex.StackTrace);
}

finally
{
db1.db_close();

}

}


其中rssFeed 就是自己写的处理rss的类,对于这个类,以前曾经用过一段时间开源的rss.net,但是实际过程中因为各种rss地址都有,甚至很多不太符合标准,所以会遇到很多问题,而且看了一下源代码,他想处理的东西太多了,代码量也非常庞大,我这点水平估计一时半会是改不好的,于是就自己作了个控件,也算不上控件了,就几个类,当然我处理的内容也相对简单了很多,只处理rss的标题和简介,item的标题,简介,时间,链接。

代码贴过来太多了,有兴趣的朋友可以到最后下载

用法相当简单了,把编译后的dll引用过来就可以如下使用:

rssFeed feed = new rssFeed(url,dt);//建立一个rss读取类实例
feed.read();//开始读取
feed.Channel.title
feed.Channel.description
feed.Channel.Items.Count
feed.Channel.Items[i].title
feed.Channel.Items[i].description
feed.Channel.Items[i].link
feed.Channel.Items[i].pubDate

构造函数中的dt表示上次读取时间,因为在类中会获得rss文件的修改时间,如果大于上次读取时间才去读取,否则就不处理了,别的相信大家一看就能明白了

目前rss读取还存在着一个问题,就是有的xml文件中如果有16进制字符(当然这个出现的可能性不大)就读取不了,哪位仁兄知道怎么解决,还请告知。

说的有些乱,还是希望对需要此功能的朋友有所帮助。

 相关下载:http://files.cnblogs.com/guanvee/code.rar

posted on 2006-06-17 15:47 迷途小猪儿 阅读(1962) 评论(28)  编辑 收藏 网摘 所属分类: 01 .NET/ASP

评论:
#1楼  2006-06-17 15:57 | Junstyle      
听说timer不稳定,容易出错,不知道你用起来如何?
  回复  引用  查看    
#2楼 [楼主] 2006-06-17 16:05 | 迷途小猪儿      
@Junstyle

根据我获得的日志信息来判断,启动间隔时间有时不对,但基本差不多,对于我来说只要他不停止运行就可以。

  回复  引用  查看    
#3楼  2006-06-17 16:31 | fuyude.net      
timer 一定要写在globa 中吗?
能不能写在一个httpmodule中?

  回复  引用  查看    
#4楼 [楼主] 2006-06-17 16:41 | 迷途小猪儿      
@fuyude.net
httpmodule没怎么接触过,我觉得这个timer是在应用程序级别的,程序一启动就要执行,不知道httpmodule里有没有对应的类似的事件,如果有的话应该也可以。

  回复  引用  查看    
#5楼  2006-06-17 16:50 | Junstyle      
timer可能运行一段时间就停了
  回复  引用  查看    
#6楼 [楼主] 2006-06-17 17:08 | 迷途小猪儿      
@Junstyle
从我用的来看,没有停止过

  回复  引用  查看    
#7楼  2006-06-17 19:29 | maz [未注册用户]
是不大稳定。不过好像和系统有关系。
  回复  引用    
#8楼  2006-06-17 20:22 | pwqzc [未注册用户]
严重支持
  回复  引用    
#9楼  2006-06-17 20:28 | 一帆(老鼠粮仓之路)      
为什么要读到数据库
直接读到本地成XML文件不更好吗?

  回复  引用  查看    
#10楼 [楼主] 2006-06-17 20:36 | 迷途小猪儿      
@一帆(老鼠粮仓之路)

以后可能要对所有文章进行检索,如果是xml文件不管是单个还是多个,加起来都得上百兆,我没怎么用过xml,感觉他的检索应该比sqlserver慢吧,现在我在sqlserver中建了相关的索引感觉速度还是可以的。
而且这个操作过程花的大部分时间都在读rss文件,写数据库只占很少的部分。

  回复  引用  查看    
#11楼  2006-06-17 22:01 | alcohol [未注册用户]
timer早期做过
但是发现极不稳定。

后来改用当用户访问的时候检查application里面的time做更新了。

  回复  引用    
#12楼  2006-06-18 13:41 | 波→ONLINE      
timer 是否稳定,我想应该跟服务器的负载有很大的关系吧。
  回复  引用  查看    
#13楼  2006-06-18 13:52 | AlphaWu      
如果是自己的服务器就好了
可以做一个服务.呵呵
我在自己的服务器上做了测试
晚上流量小的时候开始工作
去抓取一些内容.效果挺好.

  回复  引用  查看    
#14楼  2006-06-18 13:54 | AlphaWu      
另外问一下楼主、博客群的BBS是你自己开发的么?
  回复  引用  查看    
#15楼 [楼主] 2006-06-18 14:43 | 迷途小猪儿      
@AlphaWu
BBS?呵呵,其实就是个留言本罢了,当时也是为了方便,整个网站除了验证码之外都是自己写的代码

  回复  引用  查看    
#16楼  2006-06-18 14:51 | pwqzc [未注册用户]
迷途小猪儿:
读外部RSS到数据库比读到本地成XML文件稍微复杂点
你只要XmlDocument.Load()再 Save就可以拉
取的时候我想直接发送xmlhttp给那个xml再客户端解吸

  回复  引用    
#17楼 [楼主] 2006-06-18 15:00 | 迷途小猪儿      
@pwqzc
刚开始曾经有一段时间就直接写到服务器的xml中,但是为了以后的查询,又从xml到数据库,所以后来就直接读到数据库了

我其实没怎么用过xml,包括某些地方用的ajax,其实都是ajah,不知道xml在查询速度方面如何?而且还要和数据库有关系,怎么能更好的处理,这里的xml的记录数会超过10万以上

  回复  引用  查看    
#18楼  2006-06-19 07:40 | 一帆(老鼠粮仓之路)      
你如果知道xml文件的名字打入直接用xmlhttp发请求就可以了,这样的话不需要服务器做任何处理,当然速度就快了
可以看看http://www.99scj.com
99收藏夹

  回复  引用  查看    
#19楼  2006-06-19 08:43 | 砖头      
想知道你这个定时服务是否一定要开着页面才有效?
  回复  引用  查看    
#20楼 [楼主] 2006-06-19 08:54 | 迷途小猪儿      
@一帆(老鼠粮仓之路)

网站作的挺好的,不过你的rss信息只读当前的吧,我这个要累计起来,以后还要统一处理,我是觉得不得不放到数据库里了

  回复  引用  查看    
#21楼 [楼主] 2006-06-19 08:55 | 迷途小猪儿      
@砖头

呵呵,当然不用了,要不然怎么叫服务器端定时

  回复  引用  查看    
#22楼  2006-06-20 09:40 | peng [未注册用户]
我前段时间也做了和楼猪差不多的东西,交流一下
看了一下楼猪的代码,是用的XmlDocument,我用的是XmlTextReader.不过用XmlDocument处理起来的确是非常方便的
我的东西要读的RSS Feed特别多,而且定时检查的时间间隔特别短.需要开多线程进行读取,而且RSS Feed来自各个地方.个人感觉如果用XmlDocument的话,如果RSS Feed特别多的话,会不会太占内存了?而且一次要将RSS里的东西全部读出来,有些BT的Feed竟然一个就到了500K.....而且更新的条目可能就几条.

最后就是想问一下楼猪,RSS 标准里有提到Item必须按时间倒序排列么?我好像没有找到,看到大部份都是这样排的,看到时间上乱排的就是网易的RSS了吧




  回复  引用    
#23楼  2006-06-20 09:49 | peng [未注册用户]
还有一个问题,想问一下,看到楼猪代码中有这么一段
this._lastModified = response.LastModified;
是用来判断RSS Feed文件更新时间的,如果对方提供的是一个aspx文件动态生成的一个RSS Feed文件.这样的做法也是有效的么?我懒得去验证了....就直接问问楼猪了....

  回复  引用    
#24楼  2006-06-20 11:57 | xiao_p      
正版的彭来了

哈哈

顶下

  回复  引用  查看    
#25楼 [楼主] 2006-06-20 19:10 | 迷途小猪儿      
@peng

当时也是为了很快的验证这些功能,所以没有怎么考虑优化,曾经有段时间一直想办法用多线程处理,但一直也没搞定,还有也怕占太多资源的话被管理员发现就不好了

至于标准,对于这纷繁的网络,不符合标准的太多了,rss也是如此,看看donews博客,竟然会多加个GMT,我也没有认为item是按照时间顺序的所以我每次都要处理相应的item。

response.LastModified对于aspx等文件是取不到真实的时间,但我想这样的情况应该不会太多,因为对rss所有者每次都重新生成的话也是挺大的资源,看看donews的地址,虽然是aspx,还是能取到真实的时间,估计是有缓存的处理。

  回复  引用  查看    
#26楼  2006-06-21 09:27 | peng [未注册用户]
果然.还是这样啊3Q楼猪给我的回答.我研究一下donews的rss Feed看看.
用托管的主机果然还是有太大限制.不过这种RSS更新本来就是一个非常耗资源和带宽的一件事
我现在也在考虑使用XmlDocument来处理了,楼猪说得没有错."对于这纷繁的网络,不符合标准的太多了",不过pubDate里的GMT好像是必加的吧

总之,感觉还有太多东西要考虑.

  回复  引用    
#27楼 [楼主] 2006-06-21 09:37 | 迷途小猪儿      
@peng

对阿,RSS看起来就是一个xml文件,但真正用的时候要牵涉到很多问题

如果GMT必加的话,donews起码应该把时间转换一下,他是直接把北京时间后边加了GMT,而且我看到的大多数国内网站的pubDate都没有GMT。

  回复  引用  查看    
#28楼  2007-09-05 16:35 | lobtao [未注册用户]
经常莫名的停了,我写过这样的东西,运行几十分钟或者几个小时就完了。
  回复  引用    

发表评论



姓名 [登录] [注册] 
主页
Email (仅博主可见) 
验证码 *  验证码看不清,换一张
内容(请不要发表任何与政治相关的内容)  
  登录  使用高级评论   新用户注册   返回页首      

导航: 网站首页 社区 新闻 博问 闪存 网摘 招聘 .NET频道 知识库 找找看 Google站内搜索



China-pub 计算机图书网上专卖店!6.5万品种 2-8折!
China-Pub 计算机绝版图书按需印刷服务

相关文章:

相关链接: