Archive for 8月, 2008
VPNの設定
外部⇔下宿 間のVPNを設定。
説明どおりにやったが、何故かうまくいかなくて悩んだ。
ログを見てみると
Tue May 20 11:50:56 2008 route ADD 192.168.1.0 MASK 255.255.255.0 10.8.0.5 Tue May 20 11:50:56 2008 ROUTE: route addition failed using CreateIpForwardEntry: 間違った引数があります。 [if_index=149]
といったエラーが出ていたので調べてみたところ、以下の投稿を見つけた。
http://bbs.fedora.jp/read.php?FID=12&TID=6809
>Vistaでは、ルーティングテーブルを書き換えるAPIが変わっているようで、そのままインストール&設定&実行すると「route addition failed using CreateIpForwardEntry: 間違った引数があります。」ってエラーが出て失敗してしまう。
とのこと。
説明どおりに設定すると、うまくいくようになった。
ちなみに、管理者権限が必要な処理があるので、OpenVPN GUIは「管理者として実行」する必要がある。
ページ構造の微修正が厄介
ページの構造が微妙に変わったりすると、それだけでうまく取得できなくなるから困る。見た目はほとんど変わっていないのに。
ニコ動のランキングも、最近ちょくちょく微修正されているようで、そのたびに取得がうまくいかないようになる。
取得されないだけならまだ良いのだが、誤ったデータで更新されてしまうと面倒だ。それも、段階的に、以下のリストの下に行くほど発見・防止しにくくなる。
- HTMLの構造が変わったため、指定したDOMオブジェクト自体がなくなった
- オブジェクト内のテキストデータが別のものになった。フォーマットも異なる(例:”224,343″⇒”投稿者コメント”)
- テキストデータが別のものになったが、フォーマットは同じ(例:”2008年08月12日 05時”⇒”2008年08月11日 05時”)
これは実際に、「ランキング集計期間」のstrongタグがずれたことで起こった
1.や2.は正規表現関数などでフォーマットをチェックすることで対処できるが、3.はそれだけでは不十分で、前後の文字列も含めてそのデータの意味を推測しなければ対処できない。
HTMLをDOMDocumentに読み込み
HTMLをDOMで扱う際、HTMLスクレイピングクラスを用いてXMLに変換して使っていたが、DOMDocumentクラスのloadHTML()メソッドを用いたら普通にDOMで扱えた。処理も圧倒的に速い。考えてみれば、以前からJavaScript等でHTMLのDOMを普通に扱えていたので、PHPでも扱えて当たり前(?)である。今まで何をやってたんだろう。
先のニコニコ動画のRSSの問題も、loadHTMLを使うことで解決した。エンティティでない’&’がある場合、Warningを吐くものの、ブラウザと同じように解釈してくれるため、問題なく扱える。文字コードはHTML文書内のmetaタグの内容などから判別しているらしいので、文字コード指定のためにはmetaタグを追加してやる必要がある。
HTMLスクレイピングクラスが一体どういう使用方法のために作られたものなのか謎になってしまったので、少し調べてみようと思う。
ニコニコ動画のRSS解析
RSSを使ったバージョンのランキング取得スクリプト作成について。
まず、URL引数rssの値を1.0、2.0またはatomとすることで、それぞれRSS1.0、RSS2.0、Atom形式のRSSが出力できるようだ。
しかし、RSS1.0とAtomについては、ランキング2ページ以降でXMLパースエラーが出てしまう。IE、FireFoxで試したが、どちらもうまくいかなかった。整形式のXML文書じゃないらしい。整形式なのはRSS2.0のみなので、これを解析対象とすることにした。
HTTPRequestで取得したドキュメントからSimpleXMLオブジェクトを作成し、そこからデータを取り出して表示する。おそらく、HTMLスクレイピングクラスを用いた方法より高速に処理できる。
解析の際に苦労した点。
それぞれの動画情報のdescriptionブロックの内容はCDATA形式で、HTMLマークアップされたデータが入っているのだが、CDATAセクションは、つまりそのセクションがパーサにXMLマークアップではなくテキストとして処理されることを求めているため、その中のタグをそのままDOMで扱うことはできない。この中の要素にアクセスするためには、この文字列からDOMオブジェクトを生成しなければならない。
そこで、内容をそのままSimpleXMLオブジェクトやDOMDocumentオブジェクトに流し込んだのだが、パースエラーが出てうまくいかない。
長時間の試行錯誤の後、原因らしきものを見つけた。
まず、整形式のXML文書には、文書全体を括るタグが必要であること。<description></description>で囲うことにより解決した。というか、これはまさに基礎事項。
次に、文書内テキストの’&’がエンティティ化されていないこと。ブラウザではうまく表示されるが、XMLパーサでは許されないようだ。
これは、文書をSimpleXMLElementに流し込む前に、preg_replace(‘/&([^#])/’, ‘&$1′, 文字列)で置き換えることで対処できた。ただし、’&’の後に’#'の来ないものを置き換えるようにしているので、たとえば” ”等があると”&nbsp;”と置換され、おかしくなってしまう。
面倒だが、厳密な置き換えを行うよう改良する必要がありそうだ。それとも、HTMLとして読み込めばうまく解釈してくれるのだろうか。
PHPのHTTPRequestクラスを入れるのに一苦労
PECLに含まれているHTTPRequestクラスを使おうとしたが、無かったのでインストール。
マニュアルによるとpeclコマンドを使えば良いとのことなので早速試す。
# pecl install pecl_http
sh: phpize: command not found なるエラーが出た。ググってみたら、これはphp-develパッケージに含まれてるとの事。早速インストール。
# yum install php-devel
これでもう一度pecl_httpのインストールを試してみたが、次はconfigure: error: could not find zlib.h なるエラー発生。これはおそらくCのライブラリに含まれているだろうから調べてみたら、zlib-develなるパッケージを入れればいいらしい。
# yum install zlib-devel
同様に、curl.hも必要といわれたので、curl-develをインストール。
# yum install curl-devel
依存関係で色々なパッケージがインストールされた。
これでようやくインストールできた。
# pecl install pecl_http
途中に質問された項目は、全部デフォルトにした。
インストール完了時に You should add “extension=http.so” to php.ini なる文字列。
/etc/php.d/pecl.iniというファイルを作ってそこに記述しておいた。
これでようやく使用可能に。
なにやら随分と手間がかかった。PEARのHTTP_Requestライブラリがすでに使える状態だったし、必須というわけではなかったんだが。
ニコ動のRSS
http://d.hatena.ne.jp/hayori/20080319/1205883717
今頃になって知った。
これあったらわざわざHTMLからデータ取る必要無いじゃん・・・ずいぶん無駄な事をしてた。