青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

loop_in_codes

低調(diào)做技術(shù)__歡迎移步我的獨(dú)立博客 codemaro.com 微博 kevinlynx

Lisp實(shí)踐:開發(fā)RSS閱讀器

Lisp实践:开发RSS阅读器

Author:Kevin Lynx
Date:3.30.2011
Contact:kevinlynx at gmail dot com

Tip

本文简要介绍了如何使用Lisp实现一个简单的RSS阅读器,对Lisp无兴趣的TX可以 只对RSS阅读器的实现思路稍作了解即可。

一、RSS阅读器的实现

RSS Reader的实现并不像它看上去那么复杂。当初在决定写这个作为Lisp练习时,甚至觉得 没有多少内容可做。其简单程度甚至用不了你启动一个慢速IDE的时间:D。对Lisp无兴趣的 TX只需要读完这一节即可,

什么是RSS阅读器?

RSS在实现上,可以说是XML的又一次扩张式的应用。因为RSS最重要的东西就是一个XML文件 。RSS主要用于Web中的内容同步。例如我们写的博客,门户网站的新闻,都是内容。Web服 务器将这些内容组织成XML,然后我们通过一个客户端来解析这些XML,就可以在不用直接访 问网站的情况下获取信息:

imgs/rss-overview.png

RSS阅读器就是这样一个从Web服务器通过RSS(表现形式为XML)来获取信息内容的工具。它 可以被实现为一个独立的客户端程序,也可以实现为像Google Reader这种网页形式。后者 其核心功能其实是Google服务器在做,取得信息后再发给用户。

RSS文件

上已提及,RSS的实现其实就是个XML文件。这个XML文件格式非常简单,例如:

<?xml version="1.0"?>
<rss version="2.0">
   <channel>
      <title>Liftoff News</title>
      <link>http://liftoff.msfc.nasa.gov/</link>
      <description>Liftoff to Space Exploration.</description>
      <item>
         <title>Star City</title>
         <link>http://liftoff.msfc.nasa.gov/news/2003/news-starcity.asp</link>
         <description>Oh no, you wrote another blog!</description>
      </item>
    </channel>
</rss>

我们身边到处都是RSS文件,例如 http://m.shnenglu.com/rss.aspx 。RSS文件的框架大 致为:

<rss>
    <channel>
        <item>
        </item>
        <item>
        </item>
        ...
    </channel>
</rss>

对,其框架就是这样,一个channel节点,其下若干个item节点。举例来说, CPPBLOG首页就 是一个channel,该channel下有若干原创文章,每篇文章就是一个item。 无论是channel ,还是item,都会有很多属性,例如title/description/link,有些属性是RSS规范里要求 必须有的,有的是可选的。

交互过程

那么,服务器和客户端是如何交互的呢?首先,服务器上的程序针对其某个页面,生成对应 的RSS文件。这个RSS文件基本上是有固定的URL的。客户端每次获取内容时,就从这个固定 的URL获取这个RSS文件。客户端获取到这个RSS文件后,解析之,再呈现给用户。这就是整 个过程。这个过程中客户端与服务器的交互,全部是正常的HTTP请求。

而RSS阅读器,如果做得足够简单,则只需要从指定的地方获取到RSS文件,然后解析这个 XML文件,然后以相对友好的形式显示即可。

扩展

虽然RSS阅读器在核心功能上很简单,但是作为一个可以使用的工具,依然有很多功能点需 要实现。基本功能包括:

  • 记录用户关注的RSS
  • 缓存某个RSS过去一段时间更新的内容
  • 对HTTP回应的处理,最重要的就是重定向处理

我们还可以做很多扩展,例如Google Reader之类的在线RSS阅读器。这些阅读器的RSS抓取 功能做在服务器端,它们除了上面提到的基础功能外,还会包含内容分类,给内容打一些 标签,分析用户的订阅习惯然后推荐类似的内容等等。

二、Lisp实现

本节描述在Lisp中实现上文的内容。主要包括: 通过HTTP请求获取到RSS文件、解析RSS文件 。

获取RSS文件

Lisp虽然历史悠久,但其扩展库标准却做得很拙劣。偏应用级的扩展库要么由编译器实现提 供,要么就得自己在网上找。一方面使用者希望库使用起来方便,另一方面库开发者在跨编 译器实现方面也头疼不已。所幸现在有了quick lisp,安装第三方库就像Ubuntu里安装软件 一样简单(大部分)。

socket支持就是面临的第一个问题。不过我这里并不考虑跨编译器实现的问题,直接使用 SBCL里的socket接口。

要获取RSS文件,只需要连接Web服务器,发起HTTP的GET请求即可。当然,建立TCP连接,组 建HTTP请求包,就不是这里的讨论了。我们还是拿CPPBLOG首页的RSS为例,该RSS的URL为:

http://m.shnenglu.com/rss.aspx

拆分一下,得到host为m.shnenglu.com(即我们要connect的地址),rss的uri为 /rss.aspx(即HTTP请求里的文件URI),于是建立HTTP请求包:

GET /rss.aspx HTTP/1.0
Host: m.shnenglu.com

关于HTTP请求的一些基础知识,可以参考我很早前写的一篇博客:<实现自己的http服务器>。 正常情况下,Web服务器就会返回RSS的文件内容。然后我们就可以继续解析。

解析RSS

RSS本身是一个XML格式的文件。之前连接Web服务器发起HTTP请求没有用到第三方库,但是 解析XML文件不是几十来行代码能搞定的事情,所以这里需要选用一个第三方库。

我用的是s-xml,这个库在我之前的 关于Lisp的文章 中提到过。s-xml与我之前在C++ 领域见到的XML解析库最大的不同点在于,它提供的API是基于事件模式的。意思是说,你不 要去查询某个element的值是多少,当我解析到的时候会告诉你。事件模式的编程方式自然 离不开回调函数:

(s-xml:start-parse-xml
  stream
  (make-instance 's-xml:xml-parser-state
                 :new-element-hook #'decode-rss-new-element
                 :finish-element-hook #'decode-rss-finish-element
                 :text-hook #'decode-rss-text)))

与s-xml交互的也就是上面代码里提到的三个函数:new-element-hook, finish-element-hook , text-hook。这种类型的接口导致解析代码大量减少,但不利于理解。我们要在整个解析 过程中传递数据,需要通过与s-xml交互的函数参数(当然不会蠢到去用全局变量)。

解析过程中通过往函数参数指定的对象身上塞数据完成,整个解析实现也就几十行代码。 文章尾可下载代码看看。

显示出来

通过上面两步,我们得到了RSS文件、解析出了具体内容,最后一步就是呈现出来看看。RSS 文件里每个Item都是一篇文章(新闻之类),这个文章内容可直接包含HTML标记,说白了, 这些内容就是直接的HTML内容。要显示这些内容,最简单的方法就是把一个RSS转换成一种 简单的HTML文件,以供阅读。

这里就涉及到HTML generator,几乎所有的Lisper都会写一个HTML产生器(库)(虽然目前 我还没写)。这种库的作用就是方便地输出HTML文件。

Lisp相对于其他语言很大的一个特点,或者说是优点,就是其语言本身的扩展能力。这种扩 展不是简单的添加几个函数,也不是类,而是提供一些就像语言本身提供的特殊操作符一样 的东西。而HTML generator正是这种东西大放异彩的地方。这种感觉有点像在C++中通过模 板造出各种增强语言特性的东西一样(例如boost/loki)。

因为我这里只是输出简单的HTML文件,何况我对HTML的标记了解的也不多,也懒得再花经历 。所以我暂时也就将就了些土方法:

(with-output-to-string (stream)
  (let ((channel (rss-channel rss))) ;取出channel对象
   (format stream "<html><head><title>~a</title></head>"
           (get-property channel :|title|)) ;取出channel的title

最后组合一些接口,即可将整个过程联系起来,导出html文件:

(cl-rss-test:test-rss-http :uri "/news/newshot/hotnewsrss.xml"
                           :host "cd.qq.com")

然后在浏览器里查看,如图:

imgs/screenshot.png

其他

当一些代码可以工作起来的时候,就可以着手测试这批代码。然后我就用这个工具测试我 Google Reader里订阅的一些RSS。最大的问题,就是关于HTTP重定向的问题。

当服务器返回301或者302的错误信息时(HTTP回应),就标示请求的URI被移动到了其他地 方,客户端需要访问新的地址。这个其实查查 HTTP的规范 就可以轻易解决。重定向时, 新的URI被指定在Response Header里的Location域,取出来发起第二次请求即可。

下载代码

posted on 2011-03-30 09:32 Kevin Lynx 閱讀(4101) 評(píng)論(0)  編輯 收藏 引用 所屬分類: lisp

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            亚洲视频一二区| 欧美日韩免费观看一区三区| 免费成人黄色| 久久综合精品国产一区二区三区| 亚洲男人的天堂在线观看| 亚洲一区二区三区成人在线视频精品| 亚洲精品乱码久久久久| 日韩视频永久免费| 亚洲美女网站| 亚洲一区二区三区免费观看 | 欧美.日韩.国产.一区.二区| 久久米奇亚洲| 欧美激情网站在线观看| 欧美日韩高清免费| 国产精品色婷婷久久58| 国内精品久久久久久影视8| 黄色亚洲网站| 夜夜爽av福利精品导航| 午夜久久福利| 欧美激情精品久久久久| 亚洲精品视频在线看| 亚洲男人的天堂在线| 国产精品电影在线观看| 亚洲精品乱码久久久久久| 亚洲人成在线影院| 亚洲午夜久久久久久久久电影网| 午夜精品福利一区二区蜜股av| 欧美中文在线免费| 欧美激情综合色| 国产精品久久久久国产精品日日 | 亚洲精品1区2区| 亚洲欧美激情四射在线日| 久久久久久综合网天天| 最新国产乱人伦偷精品免费网站| 一区二区三区视频在线播放| 久久久国产成人精品| 欧美日韩在线观看一区二区| 国产一区清纯| 一本色道久久综合亚洲精品高清| 久久成人精品无人区| 亚洲全黄一级网站| 久久久精品五月天| 国产欧美一区二区精品仙草咪| 亚洲国产精品成人精品| 午夜在线观看欧美| 亚洲精品视频在线播放| 久久视频精品在线| 国产日韩精品一区二区| 一本一本久久a久久精品综合妖精 一本一本久久a久久精品综合麻豆 | 久久漫画官网| 在线亚洲精品福利网址导航| 久久亚洲二区| 国内精品久久久久影院薰衣草| 亚洲视频精选| 日韩视频免费看| 欧美激情综合在线| 亚洲国产日韩在线| 老司机免费视频久久| 亚洲欧美色一区| 欧美调教视频| 一区二区三区精密机械公司| 91久久精品国产91性色tv| 狂野欧美激情性xxxx欧美| 黑人中文字幕一区二区三区| 久久国产精品亚洲va麻豆| 亚洲一区二区三区在线播放| 国产精品wwwwww| 亚洲欧美日韩一区在线| 这里是久久伊人| 国产精品毛片大码女人| 亚洲免费一在线| 亚洲一区二区三区激情| 在线亚洲伦理| 国产精品理论片| 亚洲欧美亚洲| 亚洲一区二区视频| 国产精品亚洲视频| 欧美怡红院视频| 午夜精品在线观看| 国产日本亚洲高清| 久久婷婷国产综合精品青草| 久久精品中文| 在线精品观看| 亚洲精品日韩激情在线电影| 欧美日韩一区二区在线观看视频 | 久久五月激情| 另类专区欧美制服同性| 亚洲精品中文字幕女同| 99这里只有精品| 国产婷婷一区二区| 欧美成人一区二免费视频软件| 欧美成人中文字幕在线| 亚洲小说春色综合另类电影| 亚洲女与黑人做爰| 亚洲国产合集| 亚洲午夜久久久久久久久电影院| 国产欧美精品在线| 欧美成人日本| 欧美婷婷六月丁香综合色| 欧美专区日韩视频| 男男成人高潮片免费网站| 亚洲一区国产视频| 久久天堂成人| 香蕉av777xxx色综合一区| 久久影音先锋| 小嫩嫩精品导航| 欧美大尺度在线观看| 欧美在线一区二区| 欧美日韩美女在线观看| 久久久人成影片一区二区三区观看 | 一本色道久久| 久久精品一区二区三区中文字幕| 日韩亚洲在线观看| 久久九九免费视频| 午夜精彩国产免费不卡不顿大片| 久久精品官网| 亚洲综合日韩| 欧美成人蜜桃| 免费观看日韩av| 国产麻豆综合| 99精品视频免费| 亚洲精品国产精品国自产观看浪潮 | 性久久久久久久久| 亚洲最新在线视频| 久久综合九色| 久久躁狠狠躁夜夜爽| 国产精品久久看| 在线成人av.com| 久久久久九九九| 亚洲青色在线| 亚洲国产精品久久久久| 午夜精品一区二区三区电影天堂| 日韩亚洲精品在线| 欧美电影在线播放| 欧美激情第五页| 亚洲国产精品成人一区二区| 久久九九免费视频| 麻豆久久婷婷| 亚洲国产精品久久91精品| 久久国产精品免费一区| 欧美在线一级视频| 国产一区二区三区高清| 欧美一级淫片播放口| 欧美在线视频导航| 国产一区激情| 久久久久久久精| 亚洲大胆av| 亚洲视频综合| 欧美久久久久久久| 亚洲人成人一区二区三区| 日韩视频在线播放| 欧美激情综合五月色丁香| 亚洲欧洲美洲综合色网| 一个人看的www久久| 欧美日韩亚洲激情| 亚洲图片欧美午夜| 欧美一区二区三区免费视| 国产欧美日韩视频一区二区| 欧美在线视频一区| 欧美激情久久久久| 99国产精品久久久久久久成人热| 欧美激情亚洲| 亚洲性感激情| 久久亚洲一区| 亚洲精品乱码久久久久久久久| 欧美精彩视频一区二区三区| 日韩一级精品视频在线观看| 亚洲欧美日韩爽爽影院| 国产一区二区中文| 欧美国产大片| 亚洲一区在线观看视频| 久久亚洲春色中文字幕| 亚洲精一区二区三区| 国产精品美女午夜av| 久久久之久亚州精品露出| 亚洲老司机av| 久久久精品日韩欧美| 亚洲美女色禁图| 国产亚洲二区| 欧美激情中文字幕一区二区| 亚洲欧美综合一区| 亚洲国产一区视频| 欧美伊人久久大香线蕉综合69| 在线电影一区| 国产乱理伦片在线观看夜一区| 老司机免费视频久久| 国产精品99久久久久久有的能看| 久久久欧美一区二区| 一本色道久久加勒比88综合 | 极品中文字幕一区| 欧美视频一区| 免费不卡中文字幕视频| 午夜视频一区二区| 亚洲免费观看高清在线观看| 久久精彩免费视频| 亚洲一区不卡| 亚洲精品中文字幕女同| 免费观看成人www动漫视频| 亚洲欧美中文在线视频| 亚洲精品国产精品国自产观看浪潮|