Hatena::Grouprubyist

Rubyで遊ぶよ

 | 

2009-01-25

praggerでLDRFullFeedのSITEINFOを使って全文配信化

18:52

これの続き。


praggerのオレオレプラグインを書くのは楽しい。

今回は (今回も) Yahoo ブログ検索の結果を全文配信させてみる。今回は人力でインデックスを作っている LDRFullFeed の SITEINFO を使う。

うちの pragger のディレクトリ構造はこんな感じで、標準プラグイン以外は全部 plungin/My ディレクトリ以下にある。

pragger/
  cache/
  output/
  lib/
    simple-json.rb
  misc/
    LDRFullFeedSITEINFO.json
  plugin/
    My/
      Filter/
        full_feed.rb
        remove_redirect.rb
      Feed/
        backup.rb

今回はこちらの JSON パーサーを使うことにしたので、lib ディレクトリを作った。

lib の中に、ここから最新版 (現在は1.5) を入れて、simple-json.rb と名付けた。

LDRFullFeedSITEINFO.json は Wedata からダウンロードしてくる。

次に、メインのプラグインをこんな感じで用意する。

  • full_feed.rb
#!/usr/bin/ruby
## fetch full text using LDRFullFeed SITEINFO -- edvakf
## ex.
## - module: Filter::full_feed
##  config:
##    SITEINFO: path/to/json
##    get_title: true (optional)
require 'lib/simple-json'
require 'open-uri'
require 'kconv'
require 'rubygems'
require 'nokogiri'

def full_feed(config,data)
  begin
    json = open(config['SITEINFO']).read
    _siteinfo = JsonParser.new.parse(json)
  rescue
    puts "invalid SITEINFO"
  end

  data.each do |item|
    siteinfo = _siteinfo.dup
    url = item.link
    puts "scanning siteinfo for : #{url}"
    siteinfo.map! do |info|
      begin
        re = info['data']['url']
        if url.match(re)
          info = info['data']
          enc = info['enc']
          if enc == nil || enc.empty? || enc =~ /utf.?8/i
            info['enc'] = 'UTF-8'
          elsif enc =~ /euc.?jp/i
            info['enc'] = 'EUC-JP'
          elsif enc =~ /shift.?jis/i
            info['enc'] = 'SHIFT-JIS'
          else
            info = nil
          end
          info
        else
          info = nil
        end
      rescue
        info = nil
      end
    end
    siteinfo.compact!
    puts "siteinfo matched #{siteinfo.length} items"
  
    next if siteinfo.empty?
    html = open(url).read
    siteinfo.each do |info|
      begin
        xpath = info['xpath']
        puts "xpath : #{xpath}"
        doc = Nokogiri::HTML.parse(html,nil,info['enc'])
        if config['get_title']
          title = doc.search('title').inner_text()
          item.title = title unless title.empty?
        end
        description = doc.xpath(xpath).to_html
        unless description.empty?
          item.description = description
          break
        end
      rescue
        next
      end
    end
  end
  return data
end

Nokogiri が必要なのでインストールしておく。

gem install nokogiri

面倒になりそうなところは全部 JSON パーサーと Nokogiri に投げてあるのだけど、一つだけ気になるのは、urlxpathJavaScript 用にエスケープしてある点。

info['data']['url'].gsub('\\\\','\\')
info['xpath'].gsub!('\\','')

こんなふうにして一応エスケープは取り除いてあるけど、一般的に通用するものではまったくないので、もしかしたらもっといい方法が必要かもしれない。

よく見たらちゃんと SimpleJson のほうで処理してくれてあった。あほらし。


get_title を true にすると、この2行

        title = doc.search('title').inner_text()
        item.title = title unless title.empty?

が有効になり、ドキュメントの中からタイトル要素を探してきて、フィードのアイテムのタイトルにする。Yahoo ブログ検索のような雑多なフィードを読むときは、記事の見出しだけではなくブログのタイトルなどもあったほうが見やすくなる。

次に、周辺の小さなプラグインを用意する。

  • backup.rb
## concatinate data with backup data and keep the number of items constant -- edvakf
## ex.
## -module: RSS::backup
##  config:
##    path: path/to/backup
##    number: 30

def backup(config,data)
  path = config["path"]
  number = config["number"] || 15
  FileUtils.touch(path)
  old_data = eval_pragger([{"module"=>"RSS::load","config"=>{"url"=>path}}],[])
  data.concat(old_data)
  data.slice!(number,data.length-1) if data.length > number
  return data
end

これは前回のやつから切り出したものなので、説明は省略。

## extract URL-like substring from link
## Filter::remove_redirect
require 'uri'
def remove_redirect(config,data)
  data.each do |item|
    item.link.sub!(/^http.*?(http.*)$/){URI.unescape($1)}
  end
  return data
end

これは例えば http://rd.yahoo.co.jp/rss/l/blogsearch/search/S=2078379537/P=RSS/Q=opera/O=ALL/SIG=11ojvskh3/*-http%3A//rubyist.g.hatena.ne.jp/edvakf/20090110/1231539234 のようなリンクの途中から出てくる http〜という部分から、リダイレクト先の URL を推測して変換している。

- module: RSS::load
  config:
    url: http://blog-search.yahoo.co.jp/rss?p=pragger&sq=M&ei=UTF-8&so=dd
- module: My::Filter::remove_redirect
- module: Filter::deduped
  config:
    path: blog_search_pragger
- module: My::Filter::full_feed
  config:
    SITEINFO: misc/LDRFullFeedSITEINFO.json
- module: My::RSS::backup
  config:
    path: output/yahoo_pragger.rss
    number: 30
- module: RSS::save
  config:
    filename: output/yahoo_pragger.rss
    about: Yahooブログ検索を全文配信化
    link: http://blog-search.yahoo.co.jp/search?p=pragger&cop=&ei=UTF-8
    title: 「pragger」の検索結果 - Yahoo!ブログ検索
    description: Yahooブログ検索を全文配信化

これで、output ディレクトリ内に yahoo_pragger.rss というファイルができて、フィードアイテム数は常に30に保たれるはず。

これの難点は、LDRFullFeed が「全文配信をしていないRSS」のためのものであるため、元々全文配信しているところの SITEINFO は (汎用的なものを除き) 少ないと思われるところである。


require 'lib/simple-json' とやるためには pragger.rb の頭に $:.unshift(File.dirname(__FILE__)) を付けないといけないなあ。こういうときはどうやるのか分からない。。

JnpeterblexJnpeterblex2012/05/23 11:01That's an expert awensr to an interesting question

skbekktlftqskbekktlftq2012/05/23 15:07aXhSgw <a href="http://sfdnugwfaqvb.com/">sfdnugwfaqvb</a>

hxflqegmxthxflqegmxt2012/05/23 19:06WX7Uwm , [url=http://wxuztelizjyb.com/]wxuztelizjyb[/url], [link=http://apztlxswwbuw.com/]apztlxswwbuw[/link], http://remfnvwbsnal.com/

kuuctxkuuctx2012/05/25 21:12EhBwgd <a href="http://kqazjtshoowk.com/">kqazjtshoowk</a>

nqyasgluinqyasglui2012/05/26 20:42mqSMrf , [url=http://apzeaxpxyptu.com/]apzeaxpxyptu[/url], [link=http://qdbkpmssxckt.com/]qdbkpmssxckt[/link], http://gyijvowausmi.com/

トラックバック - http://rubyist.g.hatena.ne.jp/edvakf/20090125
 |