让ruby简化你的工作之blog阅读器

   阅读专家和牛人的blog已经是我学习的一种主要方法之一,我每天的必做的就是关注下dreamhead、gigix、江南白衣、robbin、李锟等牛人的blog是不是有什么新文章。不过我非常讨厌安装商业公司的rss阅读器,我害怕他们是流氓软件!而且很多阅读器的文章格式与原文有较大差异从而导致重要信息的丢失,我还是喜欢用firefox畅游网络,这导致我不得不一次一次地在各个blog间跳转,打开n个网页查找我关注的信息,一次两次也就罢了,天天这样实在是太麻烦了,那么,有没有什么工具来简化我的工作,他能自动每天把我关注的所有blog的文章放在一个页面里,我每天早上需要做的只是运行下这个工具,然后打开生成的网页就可以看到牛人们的blog。甚至,我可以在windows下做个计划任务或者linux下使用cron让这个工具每天在夜深人静的时候自动运行下,那我每天早上就可以看到牛人们新鲜出炉的好文章了。这个工具生成的网页应该类似下面这样:

然后,当我点击某个blog标题的时候会自动展开文章列表:

   
    点击文章标题就会跳转到相应的文章网页。OK,想好了需求,怎么做?写这样的东西当然是脚本语言最快了,我们用ruby来完成这个工具脚本。稍微思考下就可以知道大概的思路,应该是通过某个方法连接到各个blog站点,然后抓取我们需要的信息集中显示在这个页面里。也许你还想到要用正则表达式去解析网页内容等等,可想象一下这个工作量将多大,再说现在的blog都有替换模板功能,如果哪天换了模板,正则匹配就失效了,还得重新再来,这也太麻烦了。幸好,blog都有提供RSS啊,我们根本没必要那么麻烦,直接读RSS不就可以了?那么ruby有没有提供读rss的API?还是要我们自己去解析xml?这件事问下《ruby cookbook》就OK。ruby有提供一个解析rss的库,支持rss0.9,1.0和2.0标准,权衡之下,我使用了rss2.0,后来发现也可以正常读取rss1.0的blog。开始写我们的脚本,先建立一个Blog类用于存放信息:

class Blog
  attr_accessor:title,:url,:items
  def initialize(title,url,items=[])
    @title=title
    @url=url
    @items=items
  end
end

    title、url和items分别是blog的标题、地址和文章列表,我们将文章存储在一个数组里,默认是空的。然后再定义一个解析blog信息的方法blog_info,根据地址连接rss源并返回一个Blog对象:

def blog_info(url)
  feed = RSS::Parser.parse(open(url).read, false) 
  blog=Blog.new(feed.channel.title,url,feed.items)
end

    注意,ruby方法默认返回的最后一行的运行结果,这里就是new的Blog对象,我们通过open-uri库的open方法连接地址并读取内容,然后使用RSS模块的Parser类解析信息,最后将这些信息组织成一个Blog对象并返回。我同时关注好几个blog,那么将这些blog的rss地址放在一个数组里,然后遍历数组分别调用blog_info得到Blog对象,最后需要考虑的就是怎么将Blog对象显示在网页里。

def rss_read
  urls=['http://www.blogjava.net/canonical/rss','http://dreamhead.blogbus.com/index.rdf',
        'http://michael.nona.name/rss','http://blog.csdn.net/mozilla/Rss.aspx','http://blog.csdn.net/g9yuayon/Rss.aspx']
  urls.collect do |blog_url|
    blogs<<blog_info(blog_url)
  end  
end

    rss_read方法最后返回Blog对象组成的数组,剩下的任务就是将这个数组里信息显示在生成的网页里。这个问题很类似生成静态html文件的需求,那么ruby是否有类似freemark的模板语言?答案当然是yes,ruby on rails使用了ERb将ruby代码嵌入模板当中,我们当然也可以这样做。ERb类似jsp的语法,<%=name%>就是输出变量name,<% %>中的代码就是一般的ruby代码,因此,首先定义我们的模板文件blogs.html

<html>
    <head>
        <title>simple rss reader</title>
            <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <style rel="stylesheet" type="text/css" media="all" />body {
    margin: 80px;
    text-align:left;
    font:normal 12px Verdana, Arial;
    background:#FFF
  }
  a:link,a:visited{
    text-decoration:none;
    color:#333333;
  }
  a:hover{
    text-decoration:none;
    color:#FF6600
  }
  .dotline {
    BORDER-BOTTOM-STYLE: dotted; BORDER-LEFT-STYLE: dotted; BORDER-RIGHT-STYLE: dotted; BORDER-TOP-STYLE: dotted
  }
        </style>
  <script language="javascript">
           function change(name){
              var div=eval("document.all."+name);
              div.style.display=="none"?(div.style.display=""):(div.style.display="none");
           }
  </script>
  </head>
        <body>
            <p align="center"><strong>您关注的blog列表:</strong></p>
                    <% num=1 %>
                    <% for blog in blogs %>
                      <% begin %>
                        <div>
                            <a href="#" onclick="change('blog<%=num%>');"><%= blog.title %></a>
                            <div id="blog<%=num%>" style="display:none">
                                <% for item in blog.items %>
                                    &nbsp;&nbsp;&nbsp;&nbsp;
                                    <a href="<%=item.link%>" target="_blank"><%= item.title %></a>
                                    <br>
                                <% end %>
                            </div>
                        </div>
                        <hr class=dotline color=#000000 size=1>
                        <% num=num+1 %>
                      <% 
                      rescue StandardError=>e
                         puts "错误信息"+e
                      end %>  
                  <% end %>
        </body>
</html>

    遍历blogs数组,然后将blog的title输出到网页,接着就是blog.items文章列表循环输出,将文章列表放在一个div层中以便隐藏,javascript函数change用于隐藏或者显示文章列表。模板文件有了,现在需要的是读取模板文件并render,输出到结果文件:

  blogs=rss_read()
  #读取模板文件
  template=IO.read(File.dirname(__FILE__)+"/blogs.html")
  message=ERB.new(template)
  #输出结果文件
  File.open("today.html","w+"){|file| file.puts message.result}

最后,我们生成的是一个today.html文件,这个网页就是我们就是我们在文章开头处展示的。message.result就是经过render后,将blogs变量传入模板文件后得到结果,我们将它写入today.html。
    完整的rss-reader.rb如下:

require 'rss/2.0'
require 'open-uri'
require 'erb'
# author dennis
# email killme2008@gmail.com

class Blog
  attr_accessor:title,:url,:items
  def initialize(title,url,items=[])
    @title=title
    @url=url
    @items=items
  end
end
def blog_info(url)
  feed = RSS::Parser.parse(open(url).read, false) 
  blog=Blog.new(feed.channel.title,url,feed.items)
end
def rss_read
  urls=['http://www.blogjava.net/canonical/rss','http://dreamhead.blogbus.com/index.rdf',
        'http://michael.nona.name/rss','http://blog.csdn.net/mozilla/Rss.aspx','http://blog.csdn.net/g9yuayon/Rss.aspx']
  blogs=[]
  urls.each do |blog_url|
    blogs<<blog_info(blog_url)
  end  
  blogs
end
if $0==__FILE__
  blogs=rss_read()
  #读取模板文件
  template=IO.read(File.dirname(__FILE__)+"/blogs.html")
  message=ERB.new(template)
  #输出结果文件
  File.open("today.html","w+"){|file| file.puts message.result}
end

    使用小窍门:最好将today.html加入FireFox的标签或者IE的收藏夹,windows下建立一个计划任务每天凌晨自动运行rss-reader.rb生成toady.html(linux可以使用cron),那么你每天早上打开浏览器就可以看到牛人们的新鲜文章了^_^

文章转自庄周梦蝶  ,原文发布时间2007-07-09

时间: 2024-10-01 19:54:04

让ruby简化你的工作之blog阅读器的相关文章

利用Ruby简化你的Java测试(进阶篇)

本文是Productive Java with Ruby系列文章的第二篇,通过上一篇的介绍,我想大家对如何利用Ruby进行单元测试有了一个基本的了解,从这里开始,我将和大家一起讨论一些利用Ruby进行单元测试时的高级话题. 通常,新技术的引入只能降低解决问题的难度,而不是消除问题本身! 在"依赖"的原始丛林中挣扎... 通过Ruby我们可以更高效的处理数据准备的问题,但是真实的世界并不那么简单!随着测试的深入,我们会越发的感觉一不小心就挣扎在"依赖"的原始丛林中!有

利用Ruby简化你的Java测试

Martin Fowler:当然(愿意花掉一半的时间来写单元测试)!因为单元测试能够使你更快地完成工作.无数次的实践已经证明这一点.你的时间越是紧张,就越是要写单元测试,它看上去慢,但实际上能够帮助你更快.更舒服地达到目标. 单元测试很重要,但是-- 单元测试的重要性,我想再多做一些强调也不为过.但实际情况是我经常听到Java开发人员抱怨单元测试繁琐.难写.虽然勉强为之,却疲于奔命,并没有体会到它的好处!最终造成的结果是出现了大量只能运行一次的单元测试.是将责任简单归结于开发人员?还是开发流程或

SXNA RSS Blog 聚合器程序_XML/RSS

 更新说明1,增加LBS皮肤模板2,增加PjBlog皮肤模板3,增加Oblog皮肤模板与导入程序4,改变Z-Blog,LBS,PjBlog皮肤模板选择方式5,首页显示增加原文档RSS调用6,首页调用增加原文档RSS调用,网站名称调用,最后更新时间调用,网站描述调用.7,细微调整了皮肤结构8,修正导入导出Bug9,修正高级搜索Bug10,尝试性修正在国外网站不能访问数据库的错误SXNA1.7下载链接: http://www.sxna.cn/forum/down/core/sxna17.rarSXN

在.NET Framework中轻松处理XML数据(三)

xml|数据 带验证的阅读器XmlValidatingReader类实现了XmlReader类,它提供了支持多种类型的XML验证:DTD,XML-Data Reduced(XDR)架构,以及XSD,DTD和XSD都是W3C官方推荐的.而XDR是Microsoft早期用于处理XML构架的一种格式. 你可以用XmlVlidatingReader类去验证XML文档和XML片断.XmlValidatingReader类工作在XML阅读器上面---是一个典型的XMLTextReader类实例.XM

.NET Framework轻松处理XML数据(三)

带验证的阅读器 XMLValidatingReader类实现了XmlReader类,它提供了支持多种类型的XML验证:DTD,XML-DataReduced(XDR)架构,以及XSD,DTD和XSD都是W3C官方推荐的.而XDR是Microsoft早期用于处理XML构架的一种格式. 你可以用XmlVlidatingReader类去验证XML文档和XML片断.XmlValidatingReader类工作在XML阅读器上面---是一个典型的XMLTextReader类实例.XMLTextReade用

flex 博客阅读器 实现代码_Flex

根据由 刘刚 翻译的"flex中文帮助"整理而来 为了完成这个项目,执行的步骤如下:1. 设置项目2. 检查要访问的远程数据源    出于安全的原因,在客户端计算机上Flash Player 中运行的应用程序,只有在满足如下    条件之一的情况下,才能访问远程的数据:    a. 应用程序的SWF 文件与远程数据源位于同一个域中.    b. 使用代理,同时SWF 文件与代理位于同一个服务器中.    c. 在数据源的宿主web 服务器上安装crossdomain.xml(跨域策略)

提升Ruby on Rails性能的几个解决方案_ruby专题

简介 Ruby On Rails 框架自它提出之日起就受到广泛关注,在"不要重复自己","约定优于配置"等思想的指导下,Rails 带给 Web 开发者的是极高的开发效率. ActiveRecord 的灵活让你再也不用配置繁琐的 Hibernate 即可实现非常易用的持久化,Github 和 Rubygems 上丰富多样的 Rails 插件是 Rails 开发高效率的又一有力保障.Rails 是一个真正彻底的 MVC(Model-View-Controller) 框

《面向对象设计实践指南:Ruby语言描述》目录—导读

内容提要 面向对象设计实践指南:Ruby语言描述 本书是对"如何编写更易维护.更易管理.更讨人喜爱且功能更为强大的Ruby应用程序"的全面指导.为帮助读者解决Ruby代码难以更改和不易扩展的问题,作者在书中运用了多种功能强大和实用的面向对象设计技术,并借助大量简单实用的Ruby示例对这些技术进行全面解释. 全书共9章,主要包含的内容有:如何使用面向对象编程技术编写更易于维护和扩展的Ruby代码,单个Ruby类所应包含的内容,避免将应该保持独立的对象交织在一起,在多个对象之间定义灵活的接

浏览器的工作原理:新式网络浏览器幕后揭秘

英文原文地址:http://blog.csdn.net/wdzxl198/article/details/8992280:http://taligarsiel.com/Projects/howbrowserswork1.htm#Resources: 转载源地址:http://www.html5rocks.com/zh/tutorials/internals/howbrowserswork/: 序言 这是一篇全面介绍 Webkit 和 Gecko 内部操作的入门文章,是以色列开发人员塔利·加希尔大