SlimerJSを使用してオンラインストア用のユニバーサルパーサーを実装する試み

オンラインストアのテンプレートパーサーの例を提供したいと思います。 この例は、オンラインストアから構造化データを取得するための普遍的なツールのふりをしていませんが、おそらくインターネット上にたくさんあるテンプレートオンラインストアに適しています。

オンラインストアの解析

サイトを解析するためのツールとして、SlimerJSを使用します。



私は、できるだけ単純化された普遍的な形で可能な限り例を挙げようとしました。



エントリポイント:

このファイルの最初の部分は、SlimerJsの作業に関連する一般的なロジックです

script.js

var grab = require('./grab'); //   grab.create().init('/catalog'); //  
      
      





ここでは、パーサーモジュールが接続および初期化され、製品カタログページのURLがinit()メソッドに渡されます。リンクは相対的です。 メインサイトドメインはconfig.jsファイルで設定されます



すべてのパーサーロジックはgrab.jsファイルにあります 私はそれを2つの部分に分けました。最初の部分は、SlimerJSのオブジェクトラッパーで、ブラウザーの複数のコピーを同時に操作するためのものです。

コードの理解を簡単にするために、コードに関するすべてのコメントをリストに入れました。



grab.js

 var file = require("./file").create(); //        var config = require("./config").getConfig(); //    /** *  - */ function Grab() { this.page; //    "webpage" this.current_url; //   URL this.parentCategory; //    /** *    * @param url string   ( /contacts ) * @param parent */ this.init = function(url, parent) { this.page = require("webpage").create(); //   webpage this.callbackInit(); //  callback   webpage if(url) { //   ,     config.host += url; } this.parentCategory = parent; this.open(config.host); //  URL }; /** *  URL * @param {string} url     */ this.open = function(url) { /* *      */ this.page.open(url); }; /** *      */ this.close = function() { this.page.close() }; /** *  callback */ this.callbackInit = function() { var self = this; /** *      * @param {string} message error * @param {type} stack */ this.page.onError = function (message, stack) { console.log(message); }; /** *         * @param {string} url  URL */ this.page.onUrlChanged = function (url) { self.current_url = url; //  URL   }; /** *  ,    webpage   console.log() * @param {string} message * @param {type} line * @param {type} file */ this.page.onConsoleMessage = function (message, line, file) { console.log(message); //       }; /** *       * @param {string} status    */ this.page.onLoadFinished = function(status) { if(status !== 'success') { console.log("Sorry, the page is not loaded"); self.close(); } self.route(); //      }; }; }
      
      





ファイルの2番目の部分は動作を定義し、作成されたGrabオブジェクトを拡張します

 Grab.prototype.route = function() { try { //         if(this.isCategoryPage()) { var categories = this.getCategories(); //      file.writeJson(config.result_file, categories, 'a'); //     for (var i = 0; i < categories.length; i++) { //     var url = categories[i].url_article; //  URL       new Grab().init(url, categories[i].title); //    slimer.wait(3000); //  3 ,     } } else { //      var content = this.getContent(); //      file.writeJson(config.result_file, content, 'a'); //     this.close(); //    } this.close(); } catch(err) { console.log(err); this.close(); } }; /** *     ,    * @returns {Object} */ Grab.prototype.getCategories = function() { return this.getContent('categories') }; /** * ,       * @returns {bool} */ Grab.prototype.isCategoryPage = function() { return this.page.evaluate(function() { // ,   ,     return !$(".catalog-list .item .price").length; }); }; /** *      * @param {string} typeContent     {categories|product} * @returns {Object} */ Grab.prototype.getContent = function(typeContent) { var result = this.page.evaluate(function(typeContent) { var result = []; //  ,      (      ) $(".catalog-list .item").each(function(key, value) { var $link = $(value).find('a.name'); //   var obj = { //      'type': 'category', 'title': $link.text().trim().toLowerCase(), //   'url_article': $link.attr('href'), //        'url_article_image': $(value).find('a.img > img').attr('src') }; //    ,        if(typeContent !== 'categories') { obj.size = []; obj.type = 'product'; $('.razmers:first .pink').each(function(key, value) { // ||... obj.size.push($(value).text().trim()); }); obj.price = parseInt($(value).find('.price').text(), 10); //  } result.push(obj); }); return result; }, typeContent); return result; }; exports.create = function() { return new Grab(); };
      
      





ファイルシステムとの便利な作業のために、SlimerJSはデータの読み取りと書き込みの両方を可能にするAPIを提供します

file.js

 var fs = require('fs'); /** *    */ function FileHelper() { /** *   * @param {string} path_to_file     * @returns array -  */ this.read = function(path_to_file) { if(!fs.isFile(path_to_file)){ throw new Error('File ('+path_to_file+') not found'); } var content = fs.read(path_to_file); if(!content.length) { throw new Error('File ('+path_to_file+') empty'); } return content.split("\n"); }; /** *     * @param {string} path_to_file     * @param {string} content    * @param {string} mode   'r', 'w', 'a/+', 'b' */ this.write = function(path_to_file, content, mode) { fs.write(path_to_file, content, mode); } /** *     JSON * @param {string} path_to_file     * @param {array} content    * @param {string} mode   'r', 'w', 'a/+', 'b' */ this.writeJson = function(path_to_file, content, mode) { var result = ''; for(var i=0; i < content.length; i++) { result += JSON.stringify(content[i]) + "\n"; } this.write(path_to_file, result, mode); } } exports.create = function() { return new FileHelper(); };
      
      





最後のファイルは、システム全体に共通の変数を指定できる構成ファイルです

config.js

 var Config = function() { this.host = 'http://example.ru'; this.log_path = 'logs\\error.txt'; this.result_file = 'result\\result.txt'; }; exports.getConfig = function() { return new Config(); };
      
      







作業の結果は、さらにデータをエクスポートするために処理できるファイルの形式になります。

スクリプトは、コンソールからのコマンドによって実行されます



 slimerjs script.js
      
      





画像 ソースコード



All Articles