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