查看英文原版
下面显示的是一个用Rails开发的博客程序的主页。我们想集成一些其他网站的信息来让这个网站变得更加丰富。我们打算加入一个链接列表指向另外一个Rails相关的站点,比如ASCIIcasts上最新文章的列表。
访问asciicasts.com,我们可以看到主页上最新文章的列表,但是我们如何把这些数据弄到我们的网站上来呢?我们可以通过页面抓取,抓到页面的HTML数据,通过解析得到我们想要的数据,这是一种可行的方法,不过有很多缺点。比如,如果网站的站长改变了页面的结构,那么我们的解析代码就没法正确地抽取出数据了。
现在更好的方法是使用RSS订阅点。ASCIIcasts站有一个RSS订阅点包含了所有集的列表,所以不需要抓取站点页面,我们只需要从订阅点来提取我们需要的数据就好了。
Feedzirra
Ruby里面有很多解析RSS订阅点的方法,不过最佳方案之一是一个叫Feedzirra的gem。Feedzirra最大的优势是它的速度,它可以非常快地解析订阅点,还有一个特点就是它可以解析很多不同类型的订阅点。
安装Feedzirra前,我们需要看看http://gems.github.com是不是在我们的gem源列表中。如果还没有,那我们把它先加上。
gem sources -a http://gems.github.com
现在我们就可以安装这个gem了:
sudo gem install pauldix-feedzirra
安装这个gem的时候会同时安装一些其他依赖的包。都装完了,我们还需要在程序的/config/environment.rb里面加入对这个gem的引用。
config.gem "pauldix-feedzirra", :lib => "feedzirra", :source => "http://gems.github.com"
搞定,我们可以开始在我们的程序里解析RSS订阅点了。
提起取订阅点
订阅点的内容会显示在我们站点的主页上,但是我们不想在用户每次访问这个页面的时候都去读取订阅点的内容,那样太费时费力了。最好是能把订阅点的内容缓存在本地。缓存订阅点的内容可以有各种各样的方法,我们想把它保存在数据库中,创建一个数据模型来表示订阅点中的每一个条目。我们给这个数据模型起名叫feed_entry。这个数据模型用四个属性来存储一个条目的数据,name用来保存标题,summary用来保存内容,url保存条目的链接,published_at保存条目创建的时间,还有就是guid用来保存一个条目的唯一标识符,我们用它来去除重复。
我们用下面的命令来创建数据模型
script/generate model feed_entry name:string summary:text url:string published_at:datetime guid:string
然后执行数据迁移任务来创建数据库表。
rake db:migrate
解析订阅点和更新条目的逻辑要加到FeedEntry类里面去。首先我们要定义一个方法来解析订阅点并且把新的条目添加到数据库中去。为此我们先定义一个类方法update_from_feed。
def self.update_from_feed(feed_url)
feed = Feedzirra::Feed.fetch_and_parse(feed_url)
feed.entries.each do |entry|
unless exists? :guid => entry.id
create!(
:name => entry.title,
:summary => entry.summary,
:url => entry.url,
:published_at => entry.published,
:guid => entry.id
)
end
end
end
这个方法有一个参数,是给Feedzirra用来解析的订阅点URL。Feedzirra提取订阅点,然后解析,然后循环遍历每一个条目把他们加到数据库中去。这个方法中使用了ActiveRecord中的exists?方法,通过条目的guid来判断一个条目是不是已经在数据库中了。
现在,我们可以在控制台上试试我们的新方法,从ASCIIcasts的订阅点上提取条目然后保存到数据库中去。
>> FeedEntry.update_from_feed("http://asciicasts.com/episodes.xml")
提取和解析订阅点会有几秒钟的延时,然后你可以看到返回了一个很长的FeedZilla对象的数组。都完成后,数据库中应该已经有了我们要的条目。
>> FeedEntry.count => 61
如果我们要再运行一遍刚才的命令,它只会把上次运行后才有的新条目添加到数据库中去。为了及时同步订阅点的数据,我们可以用一个计划任务来定期提取订阅点的信息。164集中讲到的叫Whenever的gem可以用来设定这样的计划任务。
数据库中有了我们要的订阅点的条目,我们就可以改一改我们的视图代码来显示最新的条目了。在文章的索引视图的最上面,我们可以加入下面的代码来显示10条最新的条目
<div id="recent_episodes">
<h3>Recent ASCIIcasts Episodes</h3>
<ul>
<% for entry in FeedEntry.all(:limit => 10, :order => "published_at desc") %>
<li><%= link_to h(entry.name), entry.url %></li>
<% end %>
</ul>
</div>
给div加一些CSS,我们让列表显示在文章页面的右上角。
#recent_episodes { float: right; border: solid 1px #666; margin: 8px 0 16px 16px; padding: 4px; background-color: #DDD; }
#recent_episodes h3 { margin: 0; font-size: 1em; }
#recent_episodes ul { list-style: none; margin-left: 8px; padding-left: 0; }
#recent_episodes a { font-size: 0.9em; }
现在我们的页面上有了一个区域,可以显示ASCIIcasts的最新文章了。
更频繁的更新
如果我们不需要很频繁地查看订阅点的内容是否有更新,那么之前我们写的代码可以工作地很好。但是如果我们要每十分钟左右就查看一次,那么现在这个方法就不是效率最高的了。每一次我们都要把整个订阅点的内容提取出来,大部分时候里面的数据都没有变化,所以提取整个订阅点的内容,既浪费时间又浪费带宽。
幸好Feedzirra提供了获取订阅点更新的方法。看一看Feedzirra的例子程序,你会发现有一个方法可以只提取订阅点中上次提取以后的更新部分。
# updating a single feed
updated_feed = Feedzirra::Feed.update(feed)
update方法使用ETags来判断一个订阅点从上次更新以后是不是有变化,如果有才会提取并解析。还有一个new_entries方法能够返回新条目的集合。
写这个例子程序的时候,我没法让它跑起来,但是我的代码应该没问题,可以让你频繁地从订阅点上提取更新的内容。和之前创建的update_from_feed一样,我们要再给FeedEntry类加上一个方法。这个方法会不断地轮询订阅点,然后把更新的条目添加到数据库中去。
我们的新方法会使用把条目写到数据库的那些代码,所以我们先把那些代码抽取到一个单独的方法中去。
class FeedEntry < ActiveRecord::Base
def self.update_from_feed(feed_url)
feed = Feedzirra::Feed.fetch_and_parse(feed_url)
add_entries(feed.entries)
end
private
def self.add_entries(entries)
entries.each do |entry|
unless exists? :guid => entry.id
create!(
:name => entry.title,
:summary => entry.summary,
:url => entry.url,
:published_at => entry.published,
:guid => entry.id
)
end
end
end
end
现在我们来写这个新方法,我们给它起名叫update_from_feed_continuously。
def self.update_from_feed_continuously(feed_url, delay_interval = 15.minutes)
feed = Feedzirra::Feed.fetch_and_parse(feed_url)
add_entries(feed.entries)
loop do
sleep delay_interval.to_i
feed = Feedzirra::Feed.update(feed)
add_entries(feed.new_entries) if feed.updated?
end
end
这个方法定义和update_from_feed很像,只是多一个参数指定轮询订阅点的频率。开始先提取整个订阅点的内容,把条目都加到数据库中,然后就进入了一个死循环,休眠一段时间后,就查看订阅点是不是有更新,如果有就把新的条目写入数据库。
那么我们现在就有了两个从RSS订阅点提取条目的方法了,一个适用于计划任务,另一个可以用守护进程来实现,适合于需要频繁查看订阅点更新的情况。
需要注意的是,在守护进程中用死循环并不是一个最好的方式。更好的方法,可以看看29集,里面讲了如何用一个守护进程gem来创建后台进程。
- 大小: 94 KB
- 大小: 117 KB
分享到:
相关推荐
2. **事件处理**:portlet可以通过发布和订阅事件来与其他portlet通信,增强了portlet间的协作。 3. **渲染模型**:portlet可以返回XML表示的视图,由portlet容器解析并转化为HTML,允许portlet动态生成内容。 4. ...
2、 订阅服务器计算机名:Subscribe_Server IP地址:192.168.20.2 由于没有域控环境,首先在两台机器的hosts文件的尾部加入: 192.168.20.1 Publish_Server 192.168.20.2 Subscribe_Server 加入的原因是没有域控和...
功能1、RedisView通过自写RESP协议解析、自写树模型、线程池实现开源、跨平台、高性能Redis界面工具2、Redis数据库视图工具,提供CURD功能3、提供基本命令运行4、支持单例、复制集、集群模式5、支持订阅发布
在给定的“GPS ROS驱动程序,python,读取GPS定位信息”主题中,我们将深入探讨如何使用Python编写ROS驱动程序来解析NMEA(Navigation Satellite Timing and Ranging/Automatic Positioning Interference)字符串,...
当控制点订阅设备的事件时,设备需要接收这些订阅请求并记录下来。SDK提供了处理订阅请求的方法,如`UpnpSubscribe`。 ##### 2.2.2、获取变量请求 控制点可能会请求获取设备的状态变量。SDK提供了处理此类请求的...
在优化来电和信息界面体验方面,这个解决方案可能包括以下几点: 1. **自动识别和匹配**:利用JavaScript处理vCard数据,识别来电或信息中的电话号码,并与已存储的联系人信息进行匹配。 2. **实时更新**:当新的...
为了确保所有必要的通信能正常进行,可以将DNS、Ping和SMTP等协议添加到ISA Server的访问规则中,以便边缘服务器能够进行域名解析和邮件传输。 5. **等待ISA Server同步**: 完成上述配置后,需要等待ISA Server...
处理解析器中的恐慌解析器的并行执行订阅样本 WS 传输字段上的指令访问者(API 在未来版本中可能会发生变化)(部分)文档入门为了在本地运行一个简单的 GraphQL 服务器,请创建一个main.go包含以下内容的文件...
本文将深入解析如何使用ME60进行网络管理,特别是如何通过命令行界面新增网管设置。 首先,我们要了解新增网管的基本步骤。在ME60设备上,新增网管通常涉及到以下几个关键环节: 1. **确定网管IP地址段**:这是...
全栈学习演示版说明: 本项目包含常用的技术点和技术栈,时间为 2020 年度最新的技术栈,大范围的包含(Vue,Vuex,SSR,vue 源码解析,vue 实战,vue 单元测试,ts,React 入门, React全家桶,react组件,react解析源码,redux,...
例如,服务器IP设为192.168.1.3,DNS服务器IP设为192.168.1.2,计算机名为"edge",DNS后缀为"winsnet.com"。在DNS服务器上创建相应的A记录,确保域名解析的准确性。在中心传输服务器和边缘服务器上,通过nslookup...
在Windows平台上,开发一个简单的RSS阅读器可能涉及到以下几个关键知识点: 1. **RSS格式理解**:首先,开发者需要熟悉RSS的结构和元素。RSS文件通常包含频道(channel)信息,如网站名称、描述和URL,以及条目...
<property name="brokerURL" value="tcp://192.168.200.128:61616"/> <!-- Spring用于管理真正的ConnectionFactory的ConnectionFactory --> <!-- 目标ConnectionFactory对应真实的可以产生JMS Connection的...
ActiveMQ支持两种消息模型:发布/订阅(Topics)和点对点(Queues)。你可以根据需求选择`createTopic`或`createQueue`创建目的地。 7. **投递模式(Delivery Mode)** 生产者可以设置消息的投递模式,通常有两种...
'MQTT_BROKER':"192.168.31.181", 'MQTT_PORT':8083 } ``` 所以你需要有MQTT的服务器,我这用的是EMQX的,用Docker直接部署了一个在局域网环境就可以用。 【备注】 1、该资源内项目代码都经过测试运行成功,功能...
它可能包含解析和创建UPnP设备广告、事件订阅、控制点操作以及数据流传输等功能。UPnP控制点可以发现、控制和监视网络上的其他UPnP设备,而cling-core则提供了这些功能的实现。 另一方面,"cling-support-2.1.1.jar...
- **优点**:Master宕机时,消息无延迟,数据和服务均无单点故障。 - **缺点**:性能略低于异步复制模式,大约降低10%左右。 #### 四、RocketMQ 部署实践 - **双Master方式部署示例** | 序号 | IP | 用户名 | ...
- `access-type layer2-subscriber`:设置端口类型为Layer 2订阅者。 - `default-domain authentication isp`:指定默认认证域为isp。 **总结:** MA5200F交换机通过配置802.1X模板、创建IP地址池、设置RADIUS...
本文档旨在解析一份关于“跌幅达股份的法规规范”的文档,并从中提取关键的技术知识点。然而,提供的内容主要聚焦于UserAPI的使用方法及其在交易系统中的集成过程,这与标题所提及的“跌幅达股份的法规规范”内容不...
以下是对这些知识点的详细解析: 1. 广义的电子商务(e-Business)包括更广泛的商业活动,如供应链管理、企业内部流程优化、企业间合作等,而e-commerce主要指的是通过互联网进行的商品和服务交易。 2. 亚马逊书店...