977
技術社區[雲棲]
讓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對象: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方法默認返回的最後一行的運行結果,這裏就是new的Blog對象,我們通過open-uri庫的open方法連接地址並讀取內容,然後使用RSS模塊的Parser類解析信息,最後將這些信息組織成一個Blog對象並返回。我同時關注好幾個blog,那麼將這些blog的rss地址放在一個數組裏,然後遍曆數組分別調用blog_info得到Blog對象,最後需要考慮的就是怎麼將Blog對象顯示在網頁裏。feed = RSS::Parser.parse(open(url).read, false)
blog=Blog.new(feed.channel.title,url,feed.items)
end
def rss_read
urls=['https://www.blogjava.net/canonical/rss','https://dreamhead.blogbus.com/index.rdf',
'https://michael.nona.name/rss','https://blog.csdn.net/mozilla/Rss.aspx','https://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.htmlurls=['https://www.blogjava.net/canonical/rss','https://dreamhead.blogbus.com/index.rdf',
'https://michael.nona.name/rss','https://blog.csdn.net/mozilla/Rss.aspx','https://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>您關注的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)
#輸出結果文件
File.open("today.html","w+"){|file| file.puts message.result}
最後,我們生成的是一個today.html文件,這個網頁就是我們就是我們在文章開頭處展示的。message.result就是經過render後,將blogs變量傳入模板文件後得到結果,我們將它寫入today.html。#讀取模板文件
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如下:
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=['https://www.blogjava.net/canonical/rss','https://dreamhead.blogbus.com/index.rdf',
'https://michael.nona.name/rss','https://blog.csdn.net/mozilla/Rss.aspx','https://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
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=['https://www.blogjava.net/canonical/rss','https://dreamhead.blogbus.com/index.rdf',
'https://michael.nona.name/rss','https://blog.csdn.net/mozilla/Rss.aspx','https://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
最後更新:2017-05-17 15:31:22