LunaRss v0.6 – modificat0 da Chiaroscuro
Codice LunaRss 0_7 – refactored by AntonioCarpentieri
Commenti
- voglio estrarre le chiamate a Http da Rss_parser.
- inizio a estrarre get_raw_data e a incapsularlo in una classe.. FeedLoader. Non HttpReader. Perchè l’intento è scaricare un feed, non connettersi al web. Connettersi al web è incidentale, non l’intento.
- get_raw_data nella classe FeedLoader diventa ‘get_feed’.
- get_raw_data nella vecchia classe delega a FeedLoader ora.
class FeedLoader def get_feed() if @http_proxy.nil? h = Net::HTTP.new(@url_http) else proxy_uri = URI.parse(@http_proxy) h = Net::HTTP::Proxy(proxy_uri.host, proxy_uri.port).new(@url_http) end resp,data = h.get(@url_pagina,nil) data.gsub!(/\0/,'') return data end end
- in FeedLoader mancano alcuni attributi.. definiamo come passarli
- FeedLoader lo si crea specificando un eventuale proxy
- chiamando get_feed invece si specifica la url da scaricare
- ora ritocco anche Rss_parser (che rinomino a RssParser) per adattarlo alla nuova situazione.
- c’è tanto refactoring da fare qui… ma lo lascio a altri :-)
- al momento la signature del costruttore di RssParser è:
def initialize(url, proxy=nil) @feed_loader = FeedLoader.new(proxy) @url = url end
- aggiungo un metodo per passare il loader da fuori. questo mi permetterà di passare un finto loader che legge un file da locale invece che dalla rete, permettendomi quindi di fare test ripetibili.
def inject_loader! feed_loader @feed_loader = feed_loader end
ecco il codice finale:
require 'net/http'
FeedData = Struct.new :channel,
:titles,
:descriptions,
:links
class FeedLoader
def initialize(proxy=nil)
@http_proxy = proxy
end
def get_feed url
url_no_http = url.gsub(/http\:\/\//,'')
url_http = url_no_http.gsub(/\/.*/,'')
url_pagina = "/" + url.gsub(%r{http:\/\/.*?\/},'')
if @http_proxy.nil?
h = Net::HTTP.new(url_http)
else
proxy_uri = URI.parse(@http_proxy)
h = Net::HTTP::Proxy(proxy_uri.host, proxy_uri.port).new(url_http)
end
resp,data = h.get(url_pagina,nil)
data.gsub!(/\0/,'')
return data
end
end
class RssParser
def initialize(url, proxy=nil)
@feed_loader = FeedLoader.new(proxy)
@url = url
end
def inject_loader! feed_loader
@feed_loader = feed_loader
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 get_raw_data
@feed_loader.get_feed @url
end
def rss_data
@data ||= get_raw_data
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
##############################
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