讓ruby簡化你的工作之blog閱讀器
Posted on 2007-07-09 15:14 dennis 閱讀(1426) 評論(3) 編輯 收藏 所屬分類: 動態(tài)語言 、my open-source 閱讀專家和牛人的blog已經(jīng)是我學(xué)習(xí)的一種主要方法之一,我每天的必做的就是關(guān)注下dreamhead、gigix、江南白衣、robbin、李錕等牛人的blog是不是有什么新文章。不過我非常討厭安裝商業(yè)公司的rss閱讀器,我害怕他們是流氓軟件!而且很多閱讀器的文章格式與原文有較大差異從而導(dǎo)致重要信息的丟失,我還是喜歡用firefox暢游網(wǎng)絡(luò),這導(dǎo)致我不得不一次一次地在各個blog間跳轉(zhuǎn),打開n個網(wǎng)頁查找我關(guān)注的信息,一次兩次也就罷了,天天這樣實在是太麻煩了,那么,有沒有什么工具來簡化我的工作,他能自動每天把我關(guān)注的所有blog的文章放在一個頁面里,我每天早上需要做的只是運行下這個工具,然后打開生成的網(wǎng)頁就可以看到牛人們的blog。甚至,我可以在windows下做個計劃任務(wù)或者linux下使用cron讓這個工具每天在夜深人靜的時候自動運行下,那我每天早上就可以看到牛人們新鮮出爐的好文章了。這個工具生成的網(wǎng)頁應(yīng)該類似下面這樣:

然后,當(dāng)我點擊某個blog標題的時候會自動展開文章列表:

點擊文章標題就會跳轉(zhuǎn)到相應(yīng)的文章網(wǎng)頁。OK,想好了需求,怎么做?寫這樣的東西當(dāng)然是腳本語言最快了,我們用ruby來完成這個工具腳本。稍微思考下就可以知道大概的思路,應(yīng)該是通過某個方法連接到各個blog站點,然后抓取我們需要的信息集中顯示在這個頁面里。也許你還想到要用正則表達式去解析網(wǎng)頁內(nèi)容等等,可想象一下這個工作量將多大,再說現(xiàn)在的blog都有替換模板功能,如果哪天換了模板,正則匹配就失效了,還得重新再來,這也太麻煩了。幸好,blog都有提供RSS啊,我們根本沒必要那么麻煩,直接讀RSS不就可以了?那么ruby有沒有提供讀rss的API?還是要我們自己去解析xml?這件事問下《ruby cookbook》就OK。ruby有提供一個解析rss的庫,支持rss0.9,1.0和2.0標準,權(quán)衡之下,我使用了rss2.0,后來發(fā)現(xiàn)也可以正常讀取rss1.0的blog。開始寫我們的腳本,先建立一個Blog類用于存放信息:
<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>您關(guān)注的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>
<% num=num+1 %>
<%
rescue StandardError=>e
puts "錯誤信息"+e
end %>
<% end %>
</body>
</html>
遍歷blogs數(shù)組,然后將blog的title輸出到網(wǎng)頁,接著就是blog.items文章列表循環(huán)輸出,將文章列表放在一個div層中以便隱藏,javascript函數(shù)change用于隱藏或者顯示文章列表。模板文件有了,現(xiàn)在需要的是讀取模板文件并render,輸出到結(jié)果文件:
完整的rss-reader.rb如下:

然后,當(dāng)我點擊某個blog標題的時候會自動展開文章列表:

點擊文章標題就會跳轉(zhuǎn)到相應(yīng)的文章網(wǎng)頁。OK,想好了需求,怎么做?寫這樣的東西當(dāng)然是腳本語言最快了,我們用ruby來完成這個工具腳本。稍微思考下就可以知道大概的思路,應(yīng)該是通過某個方法連接到各個blog站點,然后抓取我們需要的信息集中顯示在這個頁面里。也許你還想到要用正則表達式去解析網(wǎng)頁內(nèi)容等等,可想象一下這個工作量將多大,再說現(xiàn)在的blog都有替換模板功能,如果哪天換了模板,正則匹配就失效了,還得重新再來,這也太麻煩了。幸好,blog都有提供RSS啊,我們根本沒必要那么麻煩,直接讀RSS不就可以了?那么ruby有沒有提供讀rss的API?還是要我們自己去解析xml?這件事問下《ruby cookbook》就OK。ruby有提供一個解析rss的庫,支持rss0.9,1.0和2.0標準,權(quán)衡之下,我使用了rss2.0,后來發(fā)現(xiàn)也可以正常讀取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的標題、地址和文章列表,我們將文章存儲在一個數(shù)組里,默認是空的。然后再定義一個解析blog信息的方法blog_info,根據(jù)地址連接rss源并返回一個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
注意,ruby方法默認返回的最后一行的運行結(jié)果,這里就是new的Blog對象,我們通過open-uri庫的open方法連接地址并讀取內(nèi)容,然后使用RSS模塊的Parser類解析信息,最后將這些信息組織成一個Blog對象并返回。我同時關(guān)注好幾個blog,那么將這些blog的rss地址放在一個數(shù)組里,然后遍歷數(shù)組分別調(diào)用blog_info得到Blog對象,最后需要考慮的就是怎么將Blog對象顯示在網(wǎng)頁里。feed = RSS::Parser.parse(open(url).read, false)
blog=Blog.new(feed.channel.title,url,feed.items)
end
def rss_read
urls=['http://www.aygfsteel.com/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對象組成的數(shù)組,剩下的任務(wù)就是將這個數(shù)組里信息顯示在生成的網(wǎng)頁里。這個問題很類似生成靜態(tài)html文件的需求,那么ruby是否有類似freemark的模板語言?答案當(dāng)然是yes,ruby on rails使用了ERb將ruby代碼嵌入模板當(dāng)中,我們當(dāng)然也可以這樣做。ERb類似jsp的語法,<%=name%>就是輸出變量name,<% %>中的代碼就是一般的ruby代碼,因此,首先定義我們的模板文件blogs.htmlurls=['http://www.aygfsteel.com/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
<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>您關(guān)注的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>
<% num=num+1 %>
<%
rescue StandardError=>e
puts "錯誤信息"+e
end %>
<% end %>
</body>
</html>
blogs=rss_read()
#讀取模板文件
template=IO.read(File.dirname(__FILE__)+"/blogs.html")
message=ERB.new(template)
#輸出結(jié)果文件
File.open("today.html","w+"){|file| file.puts message.result}
最后,我們生成的是一個today.html文件,這個網(wǎng)頁就是我們就是我們在文章開頭處展示的。message.result就是經(jīng)過render后,將blogs變量傳入模板文件后得到結(jié)果,我們將它寫入today.html。#讀取模板文件
template=IO.read(File.dirname(__FILE__)+"/blogs.html")
message=ERB.new(template)
#輸出結(jié)果文件
File.open("today.html","w+"){|file| file.puts message.result}
完整的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.aygfsteel.com/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)
#輸出結(jié)果文件
File.open("today.html","w+"){|file| file.puts message.result}
end
使用小竅門:最好將today.html加入FireFox的標簽或者IE的收藏夾,windows下建立一個計劃任務(wù)每天凌晨自動運行rss-reader.rb生成toady.html(linux可以使用cron),那么你每天早上打開瀏覽器就可以看到牛人們的新鮮文章了^_^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.aygfsteel.com/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)
#輸出結(jié)果文件
File.open("today.html","w+"){|file| file.puts message.result}
end