Hatena::Groupperl

Perl Tech RSSフィード

2006-05-08

RSSを翻訳するウェブサービスFeedTranslator はてなブックマーク - RSSを翻訳するウェブサービスFeedTranslator - Perl Tech

FeedTranslatorはRSSを英語から日本語に翻訳するウェブサービス。WebserviceX.NETの翻訳サービスとSOAP::Lite::Simpleを使って実装している。

2007年9月追記:今ではうまく動かない様です。同様のサービスを他に探していだだく様お願いします。

#!/usr/bin/perl

# FeedTranslator (C) Toshiyuki Yamato <toshiyuki.yamato@gmail.com>

use strict;
# use KCatch;
use CGI;
use Encode qw(decode);
use LWP::Simple;
use XML::RSS;
use XML::RSS::FromAtom;
use SOAP::Lite::Simple::DotNet;
use HTML::Entities;

binmode STDOUT, ':raw :utf8';

my $uri   = 'http://www.webservicex.net';
my $proxy = 'http://www.webservicex.net/TranslateService.asmx';
my $soap  = SOAP::Lite::Simple::DotNet->new({uri => $uri, proxy => $proxy, xmlns => $uri});

my $q = CGI->new;
my $feed = get( $q->param('f') ) or die 'Feed not found';
$feed = &to_internal_encoding($feed);
my $rss = &to_rss($feed) or die "Parse failed: $@";

$rss->{channel}->{description} &&= &translate($rss->{channel}->{description});
$rss->{channel}->{language} = 'ja';
$rss->{output} = '2.0';

foreach my $item (@{$rss->{items}}) {
  $item->{title} = &translate($item->{title});
}

print $q->header(-type => 'text/xml; charset=UTF-8'), $rss->as_string;

sub translate {
  my $text = shift;

  $soap->fetch({
    method => 'Translate',
    xml    => '<LanguageMode>EnglishTOJapanese</LanguageMode><Text>' .
              encode_entities($text) . '</Text>',
  }) or die $soap->error;

  my $result = $soap->results_xml->findvalue('//TranslateResult');
  return $result =~ /^The remote server returned an error/ ? $text : $result;
}

sub to_rss {
  my $xml = shift;
  my $rss;

  if ($xml =~ m{xmlns="http://purl.org/atom/ns#"}) {
    $rss = eval { XML::RSS::FromAtom->new->parse($xml) };
  } else {
    $rss = XML::RSS->new;
    eval { $rss->parse($xml) };
  }

  return $@ ? () : $rss;
}

sub to_internal_encoding {
  my $xml = shift;
  my ($encoding) = $xml =~ /encoding="([^"]+)"/;
  $encoding ||= 'iso-8859-1';

  if ( uc($encoding) eq 'UTF-8' ) {
    utf8::decode($xml);
  } else {
    $xml = decode($encoding, $xml);
    $xml =~ s/encoding="[^"]+"/encoding="UTF-8"/;
  }

  return $xml;
}

use strict;でour宣言無しのグローバル変数を使う はてなブックマーク - use strict;でour宣言無しのグローバル変数を使う - Perl Tech

use strict;すると宣言無しのグローバル変数は使えなくなる。これを避けるためにourやuse varsを使うわけだが,使わなくても良いケースが有る。それは$VERSIONと@ISAというパッケージ変数である。これらはプログラム中で直接使われることは滅多に無く,通常はモジュールの宣言部だけに記述される。そのため,use strict;を記述する前に必要な値を入れてしまえば警告が出ることは無い。もちろん,きちんとourやuse vars宣言するに越したことは無い。

package SomePackage;

$VERSION = '1.0'; # strictの前に書けば警告が出ない
@ISA = qw(Base::Package);

use strict;

----

package SomePackage;

use strict;

our $VERSION = '1.0'; # これが正式なやりかた
our @ISA = qw(Base::Package);

データの直列化(シリアライゼーション)まとめ はてなブックマーク - データの直列化(シリアライゼーション)まとめ - Perl Tech

データの直列化とは,大雑把に言えばPerlのデータ構造(スカラー,配列,ハッシュ,リファレンスなど)を単一の文字列で表現することだ。例えば以下のようなデータをファイルに保存したいとする。

my $data = 'hoge';

これを保存するにはprintで出力するだけで良い。

open my $fh, '>data.txt' or die $!;
print $fh $data;

配列になると少し複雑になる。

my @data = ('a', 'b', 'c');
open my $fh, '>file.txt' or die $!;
print $fh join "\n", @data;
# 後で読み出す時に・・・
my @data = <$fh>;

この例のように改行が区切り文字なっていればまだマシだが,データ自体に改行文字が入っていると使えない。さらに,以下のようなデータではもう手が付けられない。

# どうやって保存すれば・・・(;´Д`)
my $data = {
  hoge => 'a',
  foo  => 'b',
  bar  => ['c', 'd', 'e'],
};

頑張って独自の保存フォーマットを考えることも出来るが,保存フォーマットがデータ構造に依存しているためにデータ構造が変わるたびにコードの書き直しになる。このような時のために,どんなデータ構造にも対応するように保存フォーマットを汎用化したのがデータ直列化モジュール(シリアライザ)である。以下に代表的なデータ直列化モジュールをまとめてみた。

Data::Dumper

Data::Dumperはデータ構造をPerlコードで表現する。データを復元するにはevalするだけでよい。evalを使うため,外部の人間のコードを実行してしまう危険をはらんでいる。Data::TreeDumperはWindowsのエクスプローラのようにツリー状のフォーマットで直列化する。

YAML,JSON

YAMLはデータ直列化に使用することを目的に考案された言語で,Perl以外のスクリプト言語でも使用できる。一方,JSONは直列化にJavaScriptコードを利用したもので,YAMLとJSONは互いに記法の互換性が有る。

Storable,FreezeThaw

Storableはバイナリデータで直列化を行うモジュールで,他のモジュールに比べて高速に動作する。FreezeThawはテキストデータだが圧縮率が高い独自フォーマットを使っている。StorableはPerlのバージョン間で互換性が無いという欠点が有る。

XML::Dumper

このモジュールはXMLでデータを直列化する。Perl以外のシステムとの相互運用に使えるかもしれない。

直列化を利用したモジュール

Tie::SaveLaterはデータの直列化,保存,復元を自動化するためのフレームワークで,AnyDBM_Fileと同じ使い勝手を実現してくれる。Data::Serializerはデータ直列化を拡張し,暗号化や圧縮ができるようにしたものだ。

まとめ

直列化モジュールを使うことにより,データベースのO/Rマッピングの様なことが簡単に実現できる。アプリケーションのデータベースや設定ファイルの保存に使ってみると便利である。

バイトコードの最適化状態を確認する はてなブックマーク - バイトコードの最適化状態を確認する - Perl Tech

バイトコードをPerlコードに戻すモジュールB::Deparseを使うことによって,コンパイル時にどのような最適化が行われているのかを見ることが出来る。

perl -MO=Deparse test.pl

---- test.pl

print 5 + 8;
print 'hoge' . 'hoge' . 'hoge';

if (0) {
  print 'hoge';
} else {
  print 'foo';
}

結果

print 13;
print 'hogehogehoge';
do {
    print 'foo'
};

いちげんさんいちげんさん2007/03/14 11:53はじめまして、以下のURLいれてみましたが、日本語ででません。
アチラ側のWEBサービスの問題でしょうか・・?
http://www.forbes.com/feeds/popstories.xml