フックメソッド
これらのメソッドはフックの原理で動作します。これらのメソッドを実装することで、オブジェクトの初期化から破棄まで、さまざまな段階でスクレイパーの動作を制御できます。
parse 以外のすべてのメソッドの実装は任意です。
async parse(set, results)
parse メソッドは、クエリ処理とスクレイピング結果取得のメインロジックを実装します。引数として以下が渡されます:
set- クエリに関する情報を持つオブジェクト:set.query- クエリのテキスト文字列set.lvl- クエリのレベル。デフォルトは0
results- メソッドparse()から入力して返すべき結果オブジェクト:- スクレイパーは results オブジェクト内の各キーの存在を確認し、存在する場合のみ値を入力する必要があります。これにより速度が最適化され、結果の形成に使用されるデータのみがスクレイピングされます。
resultsには、必要な flat 変数のキー(デフォルト値は結果未取得を意味するnone)と、配列変数 (arrays) のキー(入力準備が整った空の配列)が含まれています。results.successは、クエリが正常に処理された場合に1に設定する必要があります。デフォルト値は0で、クエリがエラーで処理されたことを意味します。
例で見てみましょう:
class JS_HTML_Tags extends BaseParser {
static defaultConf = {
results: {
flat: [
['title', 'Title'],
],
arrays: {
h2: ['H2 Headers List', [
['header', 'Header'],
]],
}
},
...
};
async parse(set, results) {
// クエリで渡されたアドレスのHTMLページの内容を取得します
const {success, data, headers} = await this.request('GET', set.query);
// 成功したかどうかとdataの型を確認します。HTMLページが正しく処理された場合、型は 'string' になるはずです。そうでない場合、A-ParserはBuffer型のオブジェクトを返します
if (success && typeof data == 'string') {
let matches;
// titleの収集が必要かどうかを確認し、値を保存します
if (results.title && matches = data.match(/<title[^>]*>(.*?)<\/title>/))
results.title = matches[1];
// h2の収集が必要かどうかを確認します
if (results.h2) {
let count = 0;
const re = /<h2[^>]*>(.*?)<\/h2>/g;
while(matches = re.exec(data)) {
// ループ内で見つかったすべてのh2タグを保存します
results.h2.push(matches[1]);
}
}
// スクレイピングの成功を通知します
results.success = 1;
}
// 処理された結果を返します
return results;
}
};
コードをより良く整理するために、独自の関数やメソッドを作成できることに注意してください:
function Answer() {
return 42;
}
class JS_HTML_Tags extends BaseParser {
...
async parse(set, results) {
results = await this.doWork(set, results);
return results;
}
async doWork(set, results) {
results.answer = Answer();
return results;
}
};
async processConf?(conf)
このメソッドは、特定のルールに従って設定を変換するために使用されます。例えば、キャプチャを使用する場合は常にセッションを使用する必要があります:
async processConf(conf) {
if (conf.useCaptcha)
conf.useSessions = 1
}
async parse(set, results) {
if (conf.useSessions)
await this.login();
}
このメソッドが存在する理由は、A-Parser が動的な設定フィールドをサポートしており、一つのタスク内で設定が異なる値を持つ可能性があるためです。このようなシナリオは以下の2つのケースで発生します:
- 設定フィールドでテンプレートを使用する場合(例:User-Agent フィールドに
[% tools.ua.random() %]を使用) - あるスクレイパーから別のスクレイパーを呼び出す際に
overridesを使用する場合(this.parser.request)
processConf メソッドは init() の前に一度呼び出されます。上記のケースでは、各クエリの処理の前に processConf が追加で呼び出されます。
processConf 適用の主なルール:
- 設定の変換がパフォーマンスに影響を与える場合にのみ使用してください。
initは一度だけ実行されますが、processConfは各クエリに対して実行される可能性があることに注意してください。この場合、initが変更される設定フィールドに依存していると、ロジックが崩れる可能性があります(以下参照)。
async init?()
init メソッドは、ベースとなるスクレイパーオブジェクトの初期化時に一度だけ呼び出され、一回限りのアクションを実行するために使用されます:
- ブラウザの起動
this.sessionManager.init()メソッドを使用したセッションマネージャーの初期化- データベースへの接続とDB内でのテーブル作成
- 静的データの読み込み
- など
このメソッドは一度だけ呼び出されるため、init() が依存するすべての設定フィールドは、設定フィールドのテンプレートや this.parsers.request 呼び出し時の overrides と併用することはできません。
async destroy?()
destroy メソッドは、タスクの終了時に一度だけ呼び出され、開いているリソースを正しく破棄するために必要です:
- ブラウザの終了
- DB接続の終了
- など
async threadInit?()
このメソッドは各スレッドの初期化時に実行されます。各スレッドはベースとなるスクレイパーオブジェクトのコピーであり、0 から始まり threads_count - 1 で終わる独自の一意な this.threadId を持ちます。
主なユースケース:
- 各スレッド用のブラウザページ(タブ)の作成
async threadDestroy?()
タスク終了プロセスのスレッド終了時に実行され、そのスレッドに割り当てられたリソースを解放するために使用されます。
async afterResultsProcessor?(results)
このメソッドは、結果コンストラクター、フィルタリング、重複排除による結果処理の後に実行されます。主な用途は、ユーザーフィルターを適用した後に this.query.add メソッドを使用してクエリをキューに追加することです。これにより、スクレイパー
HTML::LinkExtractor の遷移リンクフィルタリング(followlinks)が実装されています。