質問: スクレイピングしMYSQLに書き込む方法を聞きたいです。 続き。 スクレイピングに関して、ご回答が大変参考になりました。 phpも捨てきれていませんが、a-kuma3さんのご回答でrubyを考えています。 a-kuma3さんのご回答の続きで、 1.MYSQLに書き込むこと、 2.新たに更新されたデータを書き込むこと、 を知りたいです。 問題は2.で、書き込まれたデータベースのデータとリンク先で新たに変更されたデータを追加で書き込む方法はどうしようかと。 イメージがわかないのですが、見比べる方法が必要なのでしょうか。
回答: > イメージがわかないのですが、見比べる方法が必要なのでしょうか。 > > なければ登録、という時はどうしても既にあるかどうかというチェックは必要になります。 もっとも厳密であろう方法はすべての項目を比較というか、一致するレコードが存在するか確認する方法です。 上記はPHPですがざっくりとはこんな感じかなと。ただ、値は直じゃなくプレースホルダを使います。 rubyで詳しくだとこんな感じ? ``` SELECT * FROM テーブル名 WHERE カラム1=? AND カラム2=? AND ... ``` これで有無を判定して、なければinsertで追加。 ただ、これ1秒に何度も呼ばれる可能性のあるWebアプリとかだと重いのでどうにかして避ける事を考えます。 今回はレコード数も何万とあるわけではないし、cronでたまに回すだけだから、負荷は上がっても多分大きな問題は起きない気がします。 とはいえせっかくだし、DBには便利に使える仕組みがあるのでそれ使う方法も考えてみます。 この辺でa-kuma3さんが書いてますが「プライマリキー」というのが何度か出てきます。 これはDBに登録された1件1件の記録(レコード)を特定するための項目を差します。 > 質問データは、質問番号がプライマリキーなんですけど > > このばあい、1434818671とか1436077068とかが質問番号で、これさえあれば人力検索での質問が特定出来ます。 つまり、全ての項目を見なくても同じ質問か分かるし、この番号が既に登録されていれば質問データが登録されている事が分かる、ということです。 ただ、更新がないとか常に最新に更新とかの場合は簡単なんですが、そうでない場合はコメントにあるように工夫が必要になったりします。 さて、今回の場合は、更新があった場合、更新前のデータはそのままに、新たに1件記録するわけですね。 で、問題は何をもって新規とか更新とかを判断するかですが、一番それっぽいのは更新日時ですね。 前提としてまったく同じ日時での更新はないと仮定します。 するとこの日時で登録あれば既に登録されているし、内容が変わったなら別の日時になる、という事になります。 ただ、それは「まったく同じ日時での更新はないと仮定」した場合です。もしこれがあると同じ日時の記録は同じ内容と判断されどれか一つだけ記録される事になります。 それを回避するには更新日時に加えて他の項目も加えます。といっても今回の場合、確実にそう保証出来るものはないというか、結局は全部比較して......みたいな話になってしまいますので、妥協点として発生日時+更新日時もしくは発生日時+都県名+更新日時でどうかな?って思います。 これらの項目をプライマリキーにしてやることで、それらが重複したものは記録で着なくなる=単純にinsertしてプライマリキーによるエラーは無視すればOKになります。 プライマリキーについては以下とかでどうでしょう。 複数カラムにも設定出来ます。 というような所でどうでしょうか。 以下予談 上記で妥協があったり、スクレイピングとかの場合、書式が変わったりエラーになったりで記録できていない事はよくあります。 恒久的な事もありますが、例外的な記述のために数日間だけごっそりない、元データは既に更新済みとか、cronで回してるとありがちです。 なので、容量に余裕があれば、取ってきたページ内容をhtmlのまま、それ様テーブルに記録しておくとかするといざと言うとき助かります。 #その時は取得日時も記録して90日とか容量にあわせ一定期間で消しておいたほうが良いです。 #それで容量食いつぶして本来の記録がエラーになるとか本末転倒なんで。 あと、最初のうちは何件登録したとか概要を標準出力に出すようにして、メールで確認しとくとか。