既に投稿した質問との関連性について
本質問は、既に投稿した質問に関係する内容ですが、元の質問が「ファイルを伴うクローリングデータのトランザクション性について2通りの方法が存在して迷っている」というものでしたが、問題をもう少し細分化してから再編集して質問し直すべきと考えました。
そして、自分は本質問のプログラムをオブジェクト指向で実現するため、多少データベース処理が重くなろうと、書きやすいプログラムで書くために、ファイルもすべてデータベースに保存する方針にしました。
勿論、元の質問において、外部ストレージを利用するトランザクションの管理が面倒な方法も破棄した訳ではないです。
とりあえず、ここで質問をして元の質問を再編集できるようにします。
(元の質問が丸投げ的になっている思って、このようにしました。)
投稿者のスキル
プログラムを初めて1年くらいで、オブジェクト指向自体に挑戦したことはあります。
クローラーを書いて分析をしようと頑張っていますが、煩雑で抜け漏れが多く管理しづらいので、オブジェクト指向によりマシなコードを書きたいと思っています。
前提・実現したいこと
タイトルにもあるとおり、一連の流れである
「クローリング・スクレピング・データベース保存・データ解析」
を管理性や見通しがよくなるようにオブジェクト指向で設計したいです。
対象サイトはAPIを持たないサイトで、画像とそれに対応する項目が時々変化し、その変化を監視・分析・通知するプログラムを構築したいです。
現在自分が下手でも構築しているものは、データベース保存までです。
・要件
クローリング・スクレイピングについて
・並列化
・WEBアクセス時のその他の制御パラメータの容易な変更(UAなど)
データベース保存
・データ解析(グラフ化など)がしやすくなるようなDB設計
発生している問題・エラーメッセージ
まず、そもそもどのようにクラス設計をすればいいのかということです。
よく「こういうクローリング・スクレピングをするシステムを構築しました」みたいな会社のサイトがありますが、オブジェクト指向による設計方法としてはどう実現しているのかは紹介されなかったり、自分自身が読み取れない場合があります。
そのため、みなさんがどうしているか意見を伺いたい次第です。
(その会社に直接メールを送りつけて質問してよいのかと・・・)
一応、オブジェクト指向についての書籍・文献はいくつか目を通した事があります。
ここで、書籍よりもリンク先の「クラスにしてはいけないもの」という項目がとても良かったです。数あるOOPの文献では「カプセル化」などの3大ワードの説明の論争が多く、具体的なクラス設計方法と、それをなるべくわかりやすく一般化して説明してくれません。
そこで、自分は基本的に「クラスにするべき情報は何か」という観点で見ていきます。
今、自分が考えているクラス設計としては、以下のようになります。
・「取得・解析クラス」(クローリング・スクレピングを担当)
・「保存・読出クラス」(取得・解析クラスからのデータを元に、DB問い合わせと更新必要性確認、更新処理を実施する。)
・「通知クラス」(保存・読出クラスが更新必要性確認をした結果、特定のカラムの変更を、メールなどで通知する)
「取得・解析クラス」
システム構成としてクローリングとスクレイピングを分離している文献も多くありますが、自分がそうしない理由は以下です。
・テキストだけでなく、それに対応する画像等のファイルも取得する場合、スクレピング後に対象ファイルのリンクに対し再びクローリングするため。
(ここらへんをヘッドレスブラウザならプログラム上の一行の処理で複数の画像へのリクエストをしてくれそうだが、結局、取得してきた画像がどのテキストに対応するのかを解析する行為がスクレイピングと同様なので、それならヘッドレスブラウザはいらない)
・一度クローリングした生のデータを別ストレージに保存して、スクレピング処理させるのは、余計なアクセスが生じさせそうであり管理が面倒(ただし、生データが残る恩恵はあるが捨てることにする)、それなら一括処理させるべきという考え
「保存・読出クラス」
取得・解析クラスから、「スクレピング後の整形データ」や、「画像等の項目の存在確認した情報を保持した状態」を合わせ持つ特定のデータ構造(これをどうするかも悩み中で後ほど説明)を受取り、それをもとにDB問い合わせを行う。
・対象データが変化していれば、更新処理
・特定の変更があれば、通知クラスに知らせる、もしくは、特定の変更の通知必要性の確認自体を通知クラスに担当させるべきであり、更新処理後、毎回通知クラスへ更新処理のレコードの差分を送信する
・対象データが消えていれば、その存在確認をするために、DB内の過去の取得データから、対象データに関係する元の特定項目などの情報をDBから取得(これを取得・解析クラスに送信し、取得・解析クラスは対象データの取得をリトライする)
通知クラス
保存・読出クラスから送信されたDB変更の差分についての情報を解析し、通知必要性を確認する。
取得データクラス
取得データも、特定の構造を持つので、これを整形するメソッドなどを持たせても良いかもしれません(すると、スクレピングの処理がこちらに移る?)
クラス設計に関する問題点
以上のようなクラス設計をしていますが、これはオブジェクト指向や管理性からどう評価されるのでしょうか?
各クラスの役割を見ると、これ以上は分離できないように思えます。また、文献のリンク先の「クラスにするべき情報は何か」という観点で見ると、どちらかというと動詞をクラス化してしまっています。それでも、何かの情報(データ取得状況などの管理状況)を保持しているならクラス化しても問題ないようにも思えます。
対象サイトについて
・特定のデータ群(アカウントのような)を持ち、その中の各項目が時々変化する。
・このデータ群は特定urlで指定できるが、urlは変更、データ群は削除される可能性もある
このようなデータ群に対し、
・特定のデータ群に関するテーブルを作成し、そのデータ群の各項目の変化を時系列的にDB保存
・特定のデータ群自体の死活監視のため、「指定urlの変更状況、データ群の削除並びに復活」等を死活監視テーブルに保存
・もし、特定データ群が削除されていたら論理削除で以後クローリングはしない。(時々復活していないか確認するので、非常に優先度の低いデータ群として登録することも)
・指定urlが変更された場合、元の指定urlを持つテーブルから、新urlを検索できそうな関連情報を引き出し、再取得を試みる。そして、再取得が可能、つまり、url変更があれば、死活監視テーブルを更新し、以後新urlでクローリングできるように自動化
・特定のデータ群について、特定の項目の変化だけをトリガーとして別の操作を行う(メール通知や別のクローリング処理)
という操作をしたい。
うまく、まとめられませんが、ご意見がほしいです。
補足情報(FW/ツールのバージョンなど)
python3,urllib3, その他の必要なツールなら何でも
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。