Note:
Testo rimosso dalla rev 5 e
Testo aggiunto nella rev6
LunaRss v0.8 – modificato da Massimiliano
Codice LunaRss 0_9 – refactored by Gabriele Renzi
Codice LunaRss 0_7 – by AntonioCarpentieri
Qualche cambiamento un po’ drastico. Sentitevi liberi di riportare qualunque parte allo stato originale. :-)
Invocazione:
parser = RssParser.new( Feed.new('http://ruby-it.org/feed.rss')) parser = RssParser.new( Feed.new('http://ruby-it.org/feed.rss', :proxy => 'http://proxy:8080'))
Modifiche a RssParser:
- il costruttore accetta qualunque oggetto che risponda a
#read(File, StringIO, etc.); magari si può disaccoppiare ulteriormente e trasferire questa responsabilità a#to_s; - rimossa conoscenza dell’URL—era solo di passaggio.
Modifiche a FeedLoader:
- rinominato in Feed;
- risponde a #read.
Non-modifiche:
- preservata l’acquisizione “lazy” dei dati, ma non so quanta differenza faccia;
- tutto il resto.
require 'net/http'
require 'uri'
class Feed
def initialize(url, opts = { })
@url = URI.parse(url)
@http =
if opts[:proxy]
proxy = URI.parse(opts[:proxy])
Net::HTTP::Proxy(proxy.host, proxy.port)
else
Net::HTTP
end
end
def read
@http.get(@url)
end
end
FeedData = Struct.new(
:channel,
:titles,
:descriptions,
:links
)
class RssParser
def initialize(feed)
@feed = feed
end
def esegui_parsing
return FeedData.new(
parse( channel_title_pattern ),
parse( item_title_pattern ),
parse( item_description_pattern ),
parse( item_links_pattern )
)
end
private
def rss_data
@data ||= @feed.read
end
def parse pattern
output_data = []
rss_data.scan pattern do |x|
output_data << x
end
return output_data
end
def channel_title_pattern
%r{<channel(?!s).*?>.*?(?:<title>(?:<!\[CDATA\[)*(.*?)(?:\]\]>)*</title>.*?)?</channel>}m
end
def item_title_pattern
%r{<item(?!s).*?>.*?(?:<title>(?:<!\[CDATA\[)*(.*?)(?:\]\]>)*</title>.*?)?</item>}m
end
def item_links_pattern
%r{<item(?!s).*?>.*?(?:<link>(?:<!\[CDATA\[)*(.*?)(?:\]\]>)*</link>.*?)?</item>}m
end
def item_description_pattern
%r{<item(?!s).*?>.*?(?:<description>(?:<!\[CDATA\[)*(.*?)(?:\]\]>)*</description>.*?)?</item>}m
end
end
##############################
def align text
text.gsub(/^\s*\./m, '')
end
##############################
class RssMaker
def header
align <<-HTML
.Content-type: text/html\r\n\r\n
.<html>
.<body>
HTML
end
def footer
align <<-HTML
.</body>
.</html>
HTML
end
def channel name
align <<-HTML
.<h3>#{name}</h3>
HTML
end
def entry titolo, descrizione, link
align <<-HTML
.<strong>
. <a href="#{link}"> #{titolo} </a>
.</strong><br/>
.
.<font size="-1"> #{descrizione} </font>
.<p/>
HTML
end
end
##############################
# Configurations
feeds=[
'http://www.repubblica.it/rss/scienza_e_tecnologia/rss2.0.xml',
'http://programmazione.it/rss.xml',
'http://www.hwupgrade.it/rss_news.xml',
'http://www.hwupgrade.it/rss_articoli.xml',
'http://www.beppegrillo.it/index.xml'
]
NEED_PROXY = false #switch this if you have a proxy
proxy_url = "http://10.0.0.2:8080" #put here your proxy, if you have one
##############################
class LunaRss
def Get_Feeds
rss_make = RssMaker.new
puts rss_make.header
feeds.each do |feed|
if NEED_PROXY
parser = RssParser.new feed, proxy_url
else
parser = RssParser.new feed
end
data = parser.esegui_parsing
puts rss_make.channel( data.channel )
0.upto data.titles.length do|i|
puts rss_make.entry(
data.titles[i],
data.descriptions[i],
data.links[i]
)
end
end
puts rss_make.footer
end
end
require 'test/unit'
require 'stringio'
class TestLunaRss < Test::Unit::TestCase
TEST_DATA = <<-HTML
<?xml version="1.0"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">
<channel>
<title>Ruby Italia</title>
<link>http://ruby-it.org/</link>
<description>Tracking all versions for Ruby Italia</description>
<language>it-it</language>
<ttl>40</ttl>
<item>
<title>Chiaroscuro</title>
<description>description too long</description>
<pubDate>Mon, 08 May 2006 13:33:54 +0200</pubDate>
<guid>http://ruby-it.org/pages/Chiaroscuro#936</guid>
<link>http://ruby-it.org/pages/Chiaroscuro#936</link>
<dc:creator>Chiaroscuro</dc:creator>
</item>
</channel>
</rss>
HTML
def test_parser
parser = RssParser.new(StringIO.new(TEST_DATA))
data = parser.esegui_parsing
assert_equal "Ruby Italia".to_s, data.channel[0].to_s
assert_equal "Chiaroscuro".to_s, data.titles[0].to_s
assert_equal "description too long".to_s, data.descriptions[0].to_s
assert_equal "http://ruby-it.org/pages/Chiaroscuro#936".to_s, data.links[0].to_s
end
end