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

loop_in_codes

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

Lisp實(shí)踐:開(kāi)發(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>
            性感少妇一区| 日韩网站在线看片你懂的| 在线亚洲一区| 欧美午夜激情视频| 亚洲欧美国产不卡| 久久久夜色精品亚洲| 亚洲国产合集| 欧美性事免费在线观看| 欧美三级不卡| 久久久久久久久久久久久9999| 欧美va亚洲va香蕉在线| 亚洲精品乱码久久久久久蜜桃麻豆 | 另类av导航| 亚洲美女毛片| 久久久噜噜噜久久狠狠50岁| 美国成人直播| 精品不卡在线| 欧美视频一区二区三区…| 国产精品hd| 悠悠资源网亚洲青| 国产一区二区按摩在线观看| 欧美精品www| 欧美怡红院视频一区二区三区| 欧美一区二区视频免费观看| 国产精品多人| 免费欧美日韩国产三级电影| 亚洲一区二区视频在线| 亚洲国产精品悠悠久久琪琪| 男人的天堂亚洲在线| 欧美精品一区二区三区在线播放| 久久成人18免费网站| 亚洲在线观看免费视频| 久久夜色精品国产欧美乱| 香蕉国产精品偷在线观看不卡| 亚洲精品国产精品久久清纯直播| 久久久精品国产一区二区三区| 日韩视频免费| 亚洲美女在线观看| 久久久视频精品| 一区二区三欧美| 日韩一级二级三级| 久久婷婷丁香| 国产性做久久久久久| 国产午夜精品一区二区三区视频| 亚洲精品国产精品乱码不99按摩 | 一区二区三区国产在线观看| 久久久一区二区| 亚洲一二三级电影| 欧美一级片久久久久久久 | 久久先锋影音av| 国产日韩av在线播放| 国产一区观看| 亚洲观看高清完整版在线观看| 久久国产精彩视频| 久久婷婷蜜乳一本欲蜜臀| 久久精品五月婷婷| 暖暖成人免费视频| 欧美在线观看网址综合| 国产女人精品视频| 午夜在线观看免费一区| 中文一区二区| 久久精品亚洲一区二区三区浴池| 久久久精品国产一区二区三区| 国产精品一区二区三区久久久| 国产伦精品一区二区三区在线观看 | 午夜一区二区三区在线观看| 国产精品电影观看| 午夜视频在线观看一区| 欧美在线视频日韩| 欧美在线资源| 亚洲国产精品传媒在线观看| 亚洲午夜精品久久久久久浪潮| 美女主播一区| 欧美精品123区| 夜夜嗨一区二区| 久久精品30| 欧美在线免费观看亚洲| 曰韩精品一区二区| 最新国产拍偷乱拍精品 | 亚洲精品偷拍| 欧美中文字幕第一页| 国产一区二区三区黄视频| 久热精品视频在线| 欧美伦理影院| 欧美中文日韩| 欧美成人一品| 黄色精品一区二区| 一区二区三区国产在线观看| 亚洲视频一区在线| 国产一区二区三区电影在线观看| 蜜乳av另类精品一区二区| 欧美高潮视频| 在线观看日韩欧美| 亚洲精品老司机| 国产欧美丝祙| 亚洲激情另类| 国产亚洲精品综合一区91| 亚洲国产精品999| 国产欧美精品一区| 亚洲国产精品尤物yw在线观看| 国产精品va在线播放我和闺蜜| 久久久水蜜桃| 欧美网站在线观看| 免费h精品视频在线播放| 国产精品videossex久久发布| 久久综合色综合88| 欧美色图首页| 亚洲风情亚aⅴ在线发布| 久久手机免费观看| 亚洲综合清纯丝袜自拍| 亚洲欧洲精品天堂一级| 国产精品色网| 久久激情视频久久| 欧美日韩1区2区| 亚洲综合日韩| 欧美国产日韩精品免费观看| 久久亚洲欧美国产精品乐播| 欧美三级视频在线| 亚洲黄色成人久久久| 在线成人h网| 久久国产精品99国产精| 午夜精品在线观看| 欧美午夜宅男影院在线观看| 亚洲人体一区| 99热这里只有成人精品国产| 久久青草久久| 噜噜噜躁狠狠躁狠狠精品视频| 国产欧美日韩不卡免费| 亚洲一区二区久久| 亚洲欧美日韩专区| 亚洲欧美激情视频在线观看一区二区三区| 亚洲精品日韩在线观看| 久久免费国产精品| 久热国产精品| 欧美激情第8页| 亚洲激情二区| 亚洲国产成人午夜在线一区| 韩日在线一区| 久久激情视频久久| 久久精品夜色噜噜亚洲aⅴ| 国产精品免费区二区三区观看| 久久av资源网站| 国产精品专区h在线观看| 亚洲欧美日产图| 亚洲电影中文字幕| 久久这里只有精品视频首页| 蜜臀a∨国产成人精品| 91久久一区二区| 先锋资源久久| 久久全球大尺度高清视频| 国内成人精品一区| 久久久久**毛片大全| 欧美成人激情视频免费观看| 亚洲日本免费| 国产精品va在线播放| 亚洲自拍偷拍视频| 久久久国产91| 亚洲激情成人网| 欧美三区不卡| 久久精品国产一区二区三区免费看| 老司机免费视频一区二区| 亚洲国产高清在线观看视频| 欧美日韩国产美女| 亚洲欧美日韩一区在线| 蜜桃精品久久久久久久免费影院| 亚洲三级观看| 国产精品日韩久久久| 久久久夜夜夜| 一本色道久久99精品综合| 久久久99精品免费观看不卡| 亚洲国产视频直播| 国产精品国产自产拍高清av| 欧美在线视频免费| 亚洲国产cao| 久久国产精品一区二区| 99精品视频免费全部在线| 国产伦精品一区二区三区四区免费| 久久视频一区| 亚洲自拍偷拍一区| 亚洲欧洲精品一区| 老司机久久99久久精品播放免费| 亚洲午夜久久久久久久久电影网| 欧美成黄导航| 亚洲欧美在线播放| 亚洲国产人成综合网站| 久久久久久久999| 亚洲一二区在线| 最新日韩av| 影音先锋亚洲一区| 国产区日韩欧美| 欧美午夜性色大片在线观看| 欧美www在线| 久久蜜桃精品| 欧美制服第一页| 亚洲在线视频一区| 一本久久知道综合久久| 亚洲韩国精品一区| 亚洲电影免费在线| 欧美激情久久久久久| 99re成人精品视频|