
新年あけましておめでとうございます。今年もボチボチやっていきます。
本稿ではPHP製のWebスクレイピングライブラリGoutteを紹介します。
Goutteは必要十分な機能を持ったWebスクレイピングライブラリです。そもそもWebスクレイピングというのは、外部Webページから必要なデータを取ってくるくらいの意味です。つまり、GoutteはWebスクレイピングを簡単に行う道具だと考えればいいでしょう。
具体的には、GoutteはWebクローラとHTMLパーサを組み合わせたようなものです。Cookieやフォームの扱いなどWebブラウザとしての機能は一通り揃っていますし、CSS風の要素指定もできるなど、機能面では他のライブラリと遜色ないように感じます。
さらに僕個人がGoutteに期待している点は、安定性とロングサポートです。Goutteは主要機能をSymfony2およびZendFrameworkのコンポーネントで実現しており、Goutte自身はそれらをつなぎ合わせているだけです。実際、Goutte本体のコードは300行くらいであり、非常に「筋がいい」ハックであると感じます。
Goutte自体はまだ正式リリースはされておらず、GitHubのプロジェクトページしかありません。とはいえ、最近までPull Requestを取り込んだりしていますので、作者のFabienが飽きたわけではなさそうです。既に実用レベルだと思いますので、頃合いを見て正式リリースしてもらいたいものです。
ちなみに、Goutteというのはフランス語でしずく、または水滴といった意味のようです。
僕がGoutteで特徴的だと思うのは次の3点です。

各種プログラミング言語には、切り上げ・切り捨て・四捨五入など浮動小数点数を丸める関数が何種類もあります。こうした丸め処理を利用する際、「ceilとfloorどっちがどっちだっけ?」「マイナスの数が来た時の挙動って大丈夫なんだっけ?」などと不安になることはないでしょうか。
僕が丸め関数を使うときは、バグが無いかどうか他の場所以上に警戒します。というのも、これらの関数は境界値ピッタリだった場合の挙動とマイナスの数に対する挙動がそれぞれ違っており、勘違いや考え漏れから境界値バグを作り込みやすいためです。僕と同じ感覚の人も多いのではないでしょうか。
本稿では、こうした関数の挙動が一目でわかる便利なグラフを紹介します。このグラフは『WEB+DB PRESS Vol.57』に掲載いただいた僕の記事「PHP転ばぬ先の杖 第2回 数値の正しい扱い方 ― 浮動小数点数、巨大な整数」でも紹介したものです。以下ではPHPの関数4つについて紹介していきますが、他の多くの言語でも共通の話題になると思います。
浮動小数点数の丸め処理とは、浮動小数点数を決まったルールで整数に変換することです。つまり、切り上げ・切り捨て・四捨五入はいずれも丸め処理ということになります。浮動小数点以下第x位で四捨五入、のようなバリエーションもありますが、今回は整数への丸めに絞って説明していきます。

(2011/10/18 01:50)「他の言語で試してみる」「誰が正しいのか?」を追記しました。また、初心者への対策と強調しすぎて誤解を招いた気がしたため、少し表現を変更しました。
前回記事「PHPのround関数を読み解く (1)丸め桁数が大きすぎ・小さすぎる場合」に引き続きPHPのround関数の処理を解説していきます。今回は、PHP5.3のround関数で最も特徴的なpre-rounding処理を追いかけていきましょう。
pre-roundingとは、与えられた数の丸め処理を行う前に、与えられた数をいったん10^n倍して10^14以上10^15未満の数にして整数への丸めを行うことです。pre-rounding処理のあとで、改めて本来の丸め処理を行います。
ちなみに、pre-roundingという単語は一般的な単語ではありません。少なくとも僕はPHPのround関数でしか聞いたことが無い単語です。
pre-roundingがPHPのround関数の処理でどのように利用されているか、もう少し詳しく見てみましょう。PHPのround処理を書き下すと次のようになります。

PHP5.3.4から5.3.6のround関数に問題があるんじゃないか、と僕がバグ報告していた件(PHP :: Bug #54334)が、PHP5.3.7から修正されています。僕のバグレポには特に返事もないので、全く独立に修正されたんだと思います。PHP5.3.7のChangeLogには次のような記述があります。
Alternative fix for bug Fixed bug #52550, as applied to the round() function (signed overflow), as the old fix impacted the algorithm for numbers with magnitude smaller than 0. (Gustavo)
これはどんなバグかというと、round関数で1.0未満の数を丸める際にpre-roundingを行う桁が狂っており、丸めすぎてしまうことがあるというものです。
