2007-07-09
让ruby简化你的工作之blog阅读器
关键字: blog rss
阅读专家和牛人的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类用于存放信息:
title、url和items分别是blog的标题、地址和文章列表,我们将文章存储在一个数组里,默认是空的。然后再定义一个解析blog信息的方法blog_info,根据地址连接rss源并返回一个Blog对象:
注意,ruby方法默认返回的最后一行的运行结果,这里就是new的Blog对象,我们通过open-uri库的open方法连接地址并读取内容,然后使 用RSS模块的Parser类解析信息,最后将这些信息组织成一个Blog对象并返回。我同时关注好几个blog,那么将这些blog的rss地址放在一 个数组里,然后遍历数组分别调用blog_info得到Blog对象,最后需要考虑的就是怎么将Blog对象显示在网页里。
rss_read方法最后返回Blog对象组成的数组,剩下的任务就是将这个数组里信息显示在生成的网页里。这个问题很类似生成静态html文件的需求, 那么ruby是否有类似freemark的模板语言?答案当然是yes,ruby on rails使用了ERb将ruby代码嵌入模板当中,我们当然也可以这样做。ERb类似jsp的语法,<%=name%>就是输出变量 name,<% %>中的代码就是一般的ruby代码,因此,首先定义我们的模板文件blogs.html
遍历blogs数组,然后将blog的title输出到网页,接着就是blog.items文章列表循环输出,将文章列表放在一个div层中以便隐藏, javascript函数change用于隐藏或者显示文章列表。模板文件有了,现在需要的是读取模板文件并render,输出到结果文件:
最后,我们生成的是一个today.html文件,这个网页就是我们就是我们在文章开头处展示的。message.result就是经过render后,将blogs变量传入模板文件后得到结果,我们将它写入today.html。
完整的rss-reader.rb如下:
使用小窍门:最好将today.html加入FireFox的标签或者IE的收藏夹,windows下建立一个计划任务每天凌晨自动运行rss- reader.rb生成toady.html(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类用于存放信息:
ruby 代码
- 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对象:
ruby 代码
- 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对象显示在网页里。
ruby 代码
- 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|
- 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
xml 代码
- <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 %>
-
- <a href="<%=item.link%>" target="_blank"><%= item.title %></a>
- <br>
- <% end %>
- </div>
- </div>
- <hr class=dotline color=#000000 size=1>
- <% numnum=num+1 %>
- <%
- rescue StandardError=>e
- puts "错误信息"+e
- end %>
- <% end %>
- </body>
- </html>
遍历blogs数组,然后将blog的title输出到网页,接着就是blog.items文章列表循环输出,将文章列表放在一个div层中以便隐藏, javascript函数change用于隐藏或者显示文章列表。模板文件有了,现在需要的是读取模板文件并render,输出到结果文件:
ruby 代码
- 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}
完整的rss-reader.rb如下:
ruby 代码
- 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']
- urls.collect do |blog_url|
- blog_info(blog_url)
- end
- 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),那么你每天早上打开浏览器就可以看到牛人们的新鲜文章了^_^,完整代码见附件.
- 15:16
- 浏览 (6337)
- 评论 (19)
- 分类: ruby & rails
- 进入论坛
- 相关推荐
评论
猫尾摆摆
2007-08-13
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}
mathsfan
2007-07-23
mathsfan
2007-07-23
我设登陆为自动登陆了啊,电脑里有cookie的也不行的?你的意思是我将其导出为xml以后再对这个文件进行分析?那不也有点麻烦的哦```
dennis_zane
2007-07-23
mathsfan 写道
呵呵,对了,如果还是用这个方法去搜索比如javaeye的blog里面全部的文章([url=http://msdn.javaeye.com/admin/rss_blog_all如我的[/url])好象有点问题```
因为我感觉有时自己以前弄的东西太久了有点忘了,想重新去找一下,那么多文章一页一页的去找很麻烦,所以想象这样去弄哈,你能不能试下的看能不能做的?谢谢了
XML (RSS::NotWellFormedError) Missing end tag for 'td' (got "div") Line: Position: Last 80 unconsumed characters:
因为我感觉有时自己以前弄的东西太久了有点忘了,想重新去找一下,那么多文章一页一页的去找很麻烦,所以想象这样去弄哈,你能不能试下的看能不能做的?谢谢了
你给的那个url是需要验证登录的,我进去就看到一个提示登录的页面了,不过javaeye有导出blog的功能,将导出的本地xml文件的地址写进去也一样。
mathsfan
2007-07-23
呵呵,对了,如果还是用这个方法去搜索比如javaeye的blog里面全部的文章([url=http://msdn.javaeye.com/admin/rss_blog_all如我的[/url])好象有点问题```
因为我感觉有时自己以前弄的东西太久了有点忘了,想重新去找一下,那么多文章一页一页的去找很麻烦,所以想象这样去弄哈,你能不能试下的看能不能做的?谢谢了
XML (RSS::NotWellFormedError) Missing end tag for 'td' (got "div") Line: Position: Last 80 unconsumed characters:
因为我感觉有时自己以前弄的东西太久了有点忘了,想重新去找一下,那么多文章一页一页的去找很麻烦,所以想象这样去弄哈,你能不能试下的看能不能做的?谢谢了
dennis_zane
2007-07-23
mathsfan 写道
呵呵,的确很不错,我又加了一个发表时间的,看起来更实用一点,觉得在你这基础上完善一个我自己用的


呵呵,我自己还增加了一个最近blog功能,收集两日内更新的blog文章,修改下也是很简单。
mathsfan
2007-07-23
呵呵,的确很不错,我又加了一个发表时间的,看起来更实用一点,觉得在你这基础上完善一个我自己用的


dennis_zane
2007-07-23
还有人关注这个帖子^_^
我修改了下,支持atom了,参见
http://www.blogjava.net/killme2008/archive/2007/07/11/129651.html
我修改了下,支持atom了,参见
http://www.blogjava.net/killme2008/archive/2007/07/11/129651.html
mathsfan
2007-07-23
很棒,最近正想做一个这方面的东西。
感谢```
感谢```
he200377
2007-07-22
思路很不错,我首先想到的是 用正则 去匹配
rainchen
2007-07-20
换个角度,当作应用示例详解,楼上诸位应该就能释怀了吧。
chenge
2007-07-19
为什么不用抓虾,google reader?
不是浪费时间吗?
不是浪费时间吗?
Suninny
2007-07-19
RSS阅读有Google Reader就够了
zeroliu
2007-07-19
Jruby没有内建iconv库。
在rexml模块的ICONV.rb文件中有一句:
require "iconv"
raise LoadError unless defined? Iconv
不知道Iconv需要如何定义?我把Ruby1.8.4中的iconv.dll和exe都拷贝过去,似乎不管用。
在rexml模块的ICONV.rb文件中有一句:
require "iconv"
raise LoadError unless defined? Iconv
不知道Iconv需要如何定义?我把Ruby1.8.4中的iconv.dll和exe都拷贝过去,似乎不管用。
dennis_zane
2007-07-10
Please install iconv.
难道Jruby没有内建iconv库?JRuby我没有测试过。
难道Jruby没有内建iconv库?JRuby我没有测试过。
edge_hh
2007-07-10
hi, lz
我试了一下你的代码,发现在读GBK encoding的rss源会出错
不知道是不是我是英文winxp的缘故
我试了一下你的代码,发现在读GBK encoding的rss源会出错
C:\temp\script>jruby rss-reader.rb
no such file to load -- rexml/encodings/GBK
C:/jruby-1.0.0RC2/lib/ruby/1.8/rexml/encoding.rb:42:in `encoding=': No decoder f
ound for encoding GBK. Please install iconv. (ArgumentError)
from C:/jruby-1.0.0RC2/lib/ruby/1.8/rexml/source.rb:47:in `encoding='
from C:/jruby-1.0.0RC2/lib/ruby/1.8/rexml/parsers/baseparser.rb:203:in `
pull'
from C:/jruby-1.0.0RC2/lib/ruby/1.8/rexml/parsers/streamparser.rb:16:in
`parse'
from C:/jruby-1.0.0RC2/lib/ruby/1.8/rexml/document.rb:185:in `parse_stre
am'
from C:/jruby-1.0.0RC2/lib/ruby/1.8/rss/rexmlparser.rb:22:in `_parse'
from C:/jruby-1.0.0RC2/lib/ruby/1.8/rss/parser.rb:163:in `parse'
from C:/jruby-1.0.0RC2/lib/ruby/1.8/rss/parser.rb:78:in `parse'
from rss-reader.rb:16:in `blog_info'
from rss-reader.rb:22:in `rss_read'
from rss-reader.rb:26:in `collect'
from rss-reader.rb:23:in `rss_read'
from rss-reader.rb:26
不知道是不是我是英文winxp的缘故
gigix
2007-07-10
dennis_zane 写道
gigix 写道
那个……Google Reader
我确实不知道这个工具,倒是多余了,多谢
PS:你的新blog好像没rss啊
http://gigix.thoughtworkers.org/xml/atom/feed.xml
用Firefox打开网站以后,看看地址栏右侧的RSS订阅图标。
dennis_zane
2007-07-10
gigix 写道
那个……Google Reader
我确实不知道这个工具,倒是多余了,多谢
PS:你的新blog好像没rss啊
gigix
2007-07-09
那个……Google Reader
- 浏览: 145404 次
- 性别:

- 来自: 广州

- 详细资料
搜索本博客
最新评论
-
最近的学习和工作
楼主住在棠下。学的一些技术我都没有做过 不过ruby 还是会一点点的
-- by penghao122 -
PL/SQL学习笔记(五)
ELSEIF不对,应该是ELSIF
-- by gmizr -
oracle table-lock的5种 ...
select for update 应该是row share mode的锁, 也 ...
-- by xiaoxiao1984 -
oracle table-lock的5种 ...
如果允许别的session查询或用select for update锁定记录,不 ...
-- by xiaoxiao1984 -
Hadoop分布式文件系统:架 ...
beijing.josh 写道dennis_zane 写道sunhengxin ...
-- by dogstar






评论排行榜