Advertisement
vovan333

sumkini.ru-parser/Main.js

Apr 29th, 2017
73
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. function LoadDocument(url, OnLoaded)
  2. {
  3.     jsdom.env(
  4.     {
  5.         url: url,
  6.         src: [jQSrc],
  7.         done: (err, window) =>
  8.         {
  9.             if(err)
  10.             {
  11.                 ws.error("Got error in LoadDocument('%s'): %s, retrying...".Error, url, err.message);
  12.                 LoadDocument(url, OnLoaded);
  13.             }
  14.             else
  15.             {
  16.                 OnLoaded(window.$, window);
  17.             }
  18.         }
  19.     });
  20. }
  21.  
  22. function DownloadImage(url, localPath)
  23. {
  24.     if(fetchImages)
  25.     {
  26.         fs.writeFileSync(localPath, ""); // resetting the file to 0 bytes
  27.         var remStream = request(url);
  28.         remStream.on("error", (err) =>
  29.         {
  30.             ws.error("Got error while downloading image: %s, retrying...".Error, err.message);
  31.             DownloadImage(url, localPath);
  32.         })
  33.         var locStream = fs.createWriteStream(localPath);
  34.         remStream.pipe(locStream);
  35.     }
  36. }
  37.  
  38. function GetProductImages($)
  39. {
  40.     var images = [];
  41.     ws.info("Fetching product images".Info);
  42.     $(".gallery-body > ul > li").each((index, elem) =>
  43.     {
  44.         if(imgUrl = $(elem).attr("data-orig-url"))
  45.         {
  46.             var ocImgPath = ocPathPrefix + rs.generate() + ".jpg";
  47.             var finPath = ocInstallDir + "image/" + ocImgPath;
  48.             ws.info("Saving %s into %s".Info, imgUrl, finPath);
  49.             DownloadImage(imgUrl, finPath);
  50.             images.push(ocImgPath);
  51.         }
  52.     });
  53.     return images;
  54. }
  55.  
  56. function GetProductParams($)
  57. {
  58.     var params =
  59.     {
  60.         "Бренд"    : "",
  61.         "Артикул"  : ""
  62.     };
  63.     $(".character-block > ul > li").each((index, elem) =>
  64.     {
  65.         var kvPair = $(elem).text().split(": ");
  66.         var key = kvPair[0];
  67.         var val = kvPair[1];
  68.         params[key] = val ? val.Ruwr() : "";
  69.     });
  70.     return params;
  71. }
  72.  
  73. function ParseProduct(pageUrl, assignedCategoryId)
  74. {
  75.     ws.info("Parsing product of category #%d at %s".Info, assignedCategoryId, pageUrl);
  76.     LoadDocument(pageUrl, ($) =>
  77.     {
  78.         var params = GetProductParams($);
  79.         if(!filterToFid[params["Материал"]]) ws.error("Warning: couldn't get MaterialFID of %s, '%s'", pageUrl, params["Материал"]);
  80.         if(!$(".character-block").html()) ws.error("Warning: looks like there is no .character-block in %s", pageUrl);
  81.         var product =
  82.         {
  83.             CategoryId:     assignedCategoryId,
  84.             Model:          params["Артикул"],
  85.             VendorId:       vendorToVid[params["Бренд"]],
  86.             FilterId:       filterToFid[params["Материал"]] || 1,
  87.             Title:          $("#item-card > div.colon-3-double-thin > div.pull-left.left30.product-box-js > div > h1").text().Ruwr(),
  88.             CurrentPrice:   $(".product-price-js").text().Ruwr() || 0,
  89.             OldPrice:       $("span.linethrough.color999.size24.left20").text().Ruwr() || 0,
  90.             Description:    $(".description").text().Ruwr().replace("Описание :", "").replace("Описание:", "") + $(".character-block").html() ? $(".character-block").html().Ruwr() : "",
  91.             Meta:           GetPageMetadata($),
  92.             Images:         GetProductImages($)
  93.         };
  94.         PushProduct(product);
  95.     });
  96. }
  97.  
  98. function PushProduct(product)
  99. {
  100.     var localPid = currPid;
  101.     currPid ++;
  102.     ws.info("Pushing product %s (CategoryID#%d):".Info, product.Title, product.CategoryId);
  103.  
  104.     var query = sql.build(
  105.     {
  106.         type:       "insert",
  107.         table:      "oc_product",
  108.         values:
  109.         {
  110.             product_id:         localPid,
  111.             model:              product.Model,
  112.             sku:                "",
  113.             upc:                "",
  114.             ean:                "",
  115.             jan:                "",
  116.             isbn:               "",
  117.             mpn:                "",
  118.             location:           "",
  119.             quantity:           1,
  120.             stock_status_id:    6,
  121.             image:              product.Images[0],
  122.             manufacturer_id:    product.VendorId ? product.VendorId : 0,
  123.             shipping:           1,
  124.             price:              product.CurrentPrice,
  125.             tax_class_id:       9,
  126.             status:             1,
  127.             date_available:     dfDate,
  128.             date_added:         dfDate,
  129.             date_modified:      dfDate
  130.         }
  131.     }).query;
  132.     ws.info("Running a query: ".Info + "\n%s".Query, query);
  133.     db.query(query, (err) =>
  134.     {
  135.         ws.info("Total products %s".Info, totalProducts);
  136.         if(err)
  137.         {
  138.             ws.error("Got MySQL Error in PushProduct() (querying `oc_product`): %s, query was: %s".Error, err, query);
  139.         }
  140.         else
  141.         {
  142.             query = sql.build(
  143.             {
  144.                 type:   "insert",
  145.                 table:  "oc_product_to_category",
  146.                 values:
  147.                 {
  148.                     product_id:     localPid,
  149.                     category_id:    product.CategoryId
  150.                 }
  151.             }).query;
  152.             ws.info("Running a query: ".Info + "\n%s".Query, query);
  153.             db.query(query)
  154.  
  155.             query = sql.build(
  156.             {
  157.                 type:   "insert",
  158.                 table:  "oc_product_to_store",
  159.                 values:
  160.                 {
  161.                     product_id: localPid,
  162.                     store_id:   0
  163.                 }
  164.             }).query;
  165.             ws.info("Running a query: ".Info + "\n%s".Query, query);
  166.             db.query(query);
  167.  
  168.             query = sql.build(
  169.             {
  170.                 type:   "insert",
  171.                 table:  "oc_product_description",
  172.                 values:
  173.                 {
  174.                     product_id:         localPid,
  175.                     language_id:        1,
  176.                     name:               product.Title,
  177.                     description:        product.Description,
  178.                     tag:                "",
  179.                     meta_title:         product.Meta.Title,
  180.                     meta_description:   product.Meta.Description,
  181.                     meta_keyword:       product.Meta.Keywords
  182.                 }
  183.             }).query;
  184.             ws.info("Running a query: ".Info + "\n%s".Query, query);
  185.             db.query(query);
  186.  
  187.             query = sql.build(
  188.             {
  189.                 type:   "insert",
  190.                 table:  "oc_product_filter",
  191.                 values:
  192.                 {
  193.                     product_id:         localPid,
  194.                     filter_id:          product.FilterId
  195.                 }
  196.             }).query;
  197.             ws.info("Running a query: ".Info + "\n%s".Query, query);
  198.             db.query(query);
  199.  
  200.             product.Images.forEach((val) =>
  201.             {
  202.                 query = sql.build(
  203.                 {
  204.                     type:   "insert",
  205.                     table:  "oc_product_image",
  206.                     values:
  207.                     {
  208.                         product_id:         localPid,
  209.                         image:              val,
  210.                         sort_order:         0
  211.                     }
  212.                 }).query;
  213.                 ws.info("Running a query: ".Info + "\n%s".Query, query);
  214.                 db.query(query);
  215.             });
  216.         }
  217.         return;
  218.     });
  219. }
  220.  
  221. function PushCategory(cat)
  222. {
  223.     var localCid = currCid;
  224.     ws.info("Pushing category %s (ID#%d):".Info, cat.Name, cat.CategoryId);
  225.  
  226.     var query = sql.build(
  227.     {
  228.         type:       "insert",
  229.         table:      "oc_category",
  230.         values:
  231.         {
  232.             category_id:    cat.CategoryId,
  233.             image:          "",
  234.             parent_id:      cat.ParentId,
  235.             column:         "1",
  236.             top:            cat.ParentId == 0 ? "1" : "0",
  237.             sort_order:     "0",
  238.             status:         "1",
  239.             date_added:     dfDate,
  240.             date_modified:  dfDate
  241.         }
  242.     }).query;
  243.     ws.info("Running a query: ".Info + "\n%s".Query, query);
  244.     db.query(query);
  245.  
  246.     query = sql.build(
  247.     {
  248.         type: "insert",
  249.         table: "oc_category_description",
  250.         values:
  251.         {
  252.             category_id:        cat.CategoryId,
  253.             language_id:        1,
  254.             name:               cat.Name,
  255.             description:        cat.Description,
  256.             meta_title:         cat.Meta.Title,
  257.             meta_description:   cat.Meta.Description,
  258.             meta_keyword:       cat.Meta.Keywords
  259.         }
  260.     }).query;
  261.     ws.info("Running a query: ".Info + "\n%s".Query, query);
  262.     db.query(query);
  263.  
  264.     query = sql.build(
  265.     {
  266.         type: "insert",
  267.         table: "oc_category_path",
  268.         values:
  269.         {
  270.             category_id:        cat.CategoryId,
  271.             path_id:            cat.CategoryId,
  272.             level:              0
  273.         }
  274.     }).query;
  275.     ws.info("Running a query: ".Info + "\n%s".Query, query);
  276.     db.query(query);
  277.  
  278.     query = sql.build(
  279.     {
  280.         type: "insert",
  281.         table: "oc_category_to_store",
  282.         values:
  283.         {
  284.             category_id:        cat.CategoryId,
  285.             store_id:           0
  286.         }
  287.     }).query;
  288.     ws.info("Running a query: ".Info + "\n%s".Query, query);
  289.     db.query(query);
  290.  
  291.     query = sql.build(
  292.     {
  293.         type: "insert",
  294.         table: "oc_category_to_layout",
  295.         values:
  296.         {
  297.             category_id:        cat.CategoryId,
  298.             store_id:           0,
  299.             layout_id:          0
  300.         }
  301.     }).query;
  302.     ws.info("Running a query: ".Info + "\n%s".Query, query);
  303.     db.query(query);
  304. }
  305.  
  306. function InitDBConnection()
  307. {
  308.     var mysql = require("mysql");
  309.     var db    = mysql.createConnection(
  310.     {
  311.         host     : 'localhost',
  312.         user     : 'root',
  313.         password : '1',
  314.         database : 'oc_Sumkini'
  315.     });
  316.     db.connect((err) =>
  317.     {
  318.         if(err) throw err;
  319.     });
  320.     db.on("error", (err) => ws.error("Got MySQL error: %s".Error, err.message));
  321.     return db;
  322. }
  323.  
  324. function PushVendor(name)
  325. {
  326.     ws.info("Pushing vendor %s", name);
  327.     var locVid = currVid;
  328.     currVid ++;
  329.     vendorToVid[name] = locVid;
  330.     var query = sql.build(
  331.     {
  332.         type:   "insert",
  333.         table:  "oc_manufacturer",
  334.         values:
  335.         {
  336.             manufacturer_id: locVid,
  337.             name:            name,
  338.             sort_order:      locVid
  339.         }
  340.     }).query;
  341.     ws.info("Running a query: \n%s".Info, query);
  342.     db.query(query);
  343.     var query = sql.build(
  344.     {
  345.         type:   "insert",
  346.         table:  "oc_manufacturer_to_store",
  347.         values:
  348.         {
  349.             manufacturer_id: locVid,
  350.             store_id:        0
  351.         }
  352.     }).query;
  353.     ws.info("Running a query: \n%s".Info, query);
  354.     db.query(query);
  355. }
  356.  
  357. function GetPageMetadata($)
  358. {
  359.     var kw = $('meta[name="keywords"]')[0];
  360.     var ds = $('meta[name="description"]')[0];
  361.     var meta =
  362.     {
  363.         Title:          $('title')[0].innerHTML.Ruwr(),
  364.         Keywords:       kw ? kw.content.Ruwr() : "",
  365.         Description:    ds ? ds.content.Ruwr() : ""
  366.     };
  367.     return meta;
  368. }
  369.  
  370. function PushMaterial(name, fid)
  371. {
  372.     filterToFid[name] = fid;
  373.     ws.info("Pushing material %s", name);
  374.     var query = sql.build(
  375.     {
  376.         type:  "insert",
  377.         table: "oc_filter",
  378.         values:
  379.         {
  380.             filter_id:       fid,
  381.             filter_group_id: 1,
  382.             sort_order:      fid
  383.         }
  384.     }).query;
  385.     db.query(query);
  386.  
  387.     query = sql.build(
  388.     {
  389.         type:  "insert",
  390.         table: "oc_filter_description",
  391.         values:
  392.         {
  393.             filter_id:       fid,
  394.             filter_group_id: 1,
  395.             name:            name,
  396.             language_id:     1
  397.         }
  398.     }).query;
  399.     db.query(query);
  400. }
  401.  
  402. function ParseVendors($)
  403. {
  404.     $(".left-menu > form > li:has(.brands) > ol > .item").each((index, elem) =>
  405.     {
  406.         PushVendor($(elem).text().Ruwr());
  407.     });
  408. }
  409.  
  410. function ParseMaterials($)
  411. {
  412.     $(".compositions > li > label > span").each((index, elem) =>
  413.     {
  414.         PushMaterial(elem.innerHTML.Ruwr().trim(), index + 3);
  415.     });
  416. }
  417.  
  418. function TruncateTables(list)
  419. {
  420.     list.forEach((val) =>
  421.     {
  422.         var query = "TRUNCATE TABLE `" + val + "`;";
  423.         ws.info("Truncating table %s, running query %s".Info, val, query);
  424.         db.query(query);
  425.     });
  426. }
  427.  
  428. String.prototype.Ruwr = function()
  429. {
  430.     return this.replace(/\`|\'|\"/g, "-").trim();
  431. }
  432.  
  433. async function Initialize()
  434. {
  435.     global.ws               = require("winston");
  436.     global.rs               = require("randomstring");
  437.     global.jsdom            = require("jsdom");
  438.     global.request          = require("request");
  439.     global.fs               = require("fs");
  440.     global.cp               = require("child_process");
  441.     global.sql              = require("json-sql")();
  442.     global.colors           = require("colors");
  443.     global.jQSrc            = fs.readFileSync("./JQuery.js", "utf-8");
  444.     global.db               = await InitDBConnection();
  445.     global.dfDate           = "2009-01-31 01:04:25";
  446.     global.ocPathPrefix     = "catalog/demo/product/";
  447.     global.ocInstallDir     = "/var/www/wc/";
  448.     global.fetchImages      = true;
  449.     global.vendorToVid      = [];
  450.     global.filterToFid      = {};
  451.     global.currPid          = 1;
  452.     global.currCid          = 1;
  453.     global.currVid          = 1;
  454.     global.totalProducts    = 0;
  455.  
  456.     process.on("uncaughtException", (err) => ws.error("Got uncaught exception: %s".Error, err.message));
  457.  
  458.     sql.configure({separatedValues: false});
  459.     sql.setDialect("mysql");
  460.  
  461.     colors.setTheme(
  462.     {
  463.         Error: "red",
  464.         Info:  "cyan",
  465.         Query: "white"
  466.     });
  467.  
  468.     var usedTables =
  469.     [
  470.         'oc_category',
  471.         'oc_category_description',
  472.         'oc_category_path',
  473.         'oc_category_to_store',
  474.         'oc_category_to_layout',
  475.         'oc_filter',
  476.         'oc_filter_description',
  477.         'oc_product',
  478.         'oc_product_description',
  479.         'oc_product_image',
  480.         'oc_product_to_category',
  481.         'oc_product_to_store',
  482.         'oc_product_filter',
  483.         'oc_manufacturer',
  484.         'oc_manufacturer_to_store'
  485.     ];
  486.     await TruncateTables(usedTables);
  487. }
  488.  
  489. function GetCategoryPageCount($)
  490. {
  491.     var paginationBtns = $("div.pagination > div > a");
  492.     if(paginationBtns.length != 0)
  493.     {
  494.         var pageCount = Number(paginationBtns[paginationBtns.length - 2].innerHTML);
  495.     }
  496.     else
  497.     {
  498.         pageCount = 1;
  499.     }
  500.     return pageCount;
  501. }
  502.  
  503. function ParseCategoryPage(categoryUrl, pageIndex, assignedCid)
  504. {
  505.     LoadDocument(categoryUrl + "/?page=" + pageIndex, ($) =>
  506.     {
  507.         var items = $(".item-box > a");
  508.         ws.info("Found %d products in category#".Info, items.length, assignedCid);
  509.         totalProducts += items.length;
  510.         items.each((index, elem) =>
  511.         {
  512.             ParseProduct(elem.href, assignedCid);
  513.         });
  514.     });
  515. }
  516.  
  517. function FindSubcategories($, parentCid)
  518. {
  519.     var subcats = [];
  520.     $(".left-menu > form > li > a").each((index, elem) =>
  521.     {
  522.         var tVal = $(elem).text();
  523.         if(tVal.startsWith("> "))
  524.         {
  525.             subcats.push(
  526.             {
  527.                 HrefElemEmu:
  528.                 {
  529.                     href:      elem.href,
  530.                     innerHTML: tVal.replace("> ", "")
  531.                 },
  532.                 AssignedCid:   ++ currCid
  533.             });
  534.         }
  535.     });
  536.     return subcats;
  537. }
  538.  
  539. function ParseCategory(hrefElem, assignedCid, parentId = 0)
  540. {
  541.     var catUrl  = hrefElem.href;
  542.     var catName = hrefElem.innerHTML;
  543.     ws.info('Parsing category "%s" (ID#%s) (%s)'.Info, catName, assignedCid, catUrl);
  544.  
  545.     var category =
  546.     {
  547.         ParentId:       parentId,
  548.         CategoryId:     assignedCid,
  549.         Name:           catName
  550.     };
  551.  
  552.     LoadDocument(catUrl, ($) =>
  553.     {
  554.         var subcats = FindSubcategories($, assignedCid);
  555.         if(subcats.length != 0 && parentId == 0)
  556.         {
  557.             subcats.forEach((val) =>
  558.             {
  559.                 ParseCategory(val.HrefElemEmu, val.AssignedCid, assignedCid);
  560.             });
  561.         }
  562.        
  563.         var desc = $(".seo-text-block").html();
  564.         var pageCount = GetCategoryPageCount($);
  565.         ws.info("Got number of pages in category#%s: %s".Info, assignedCid, pageCount);
  566.         category.Meta = GetPageMetadata($);
  567.         category.Description = desc ? desc.Ruwr() : "";
  568.         PushCategory(category);
  569.  
  570.         for(var pageIndex = 0; pageIndex != pageCount + 1; pageIndex ++)
  571.         {
  572.             ParseCategoryPage(catUrl, pageIndex, assignedCid);
  573.         }
  574.     });
  575. }
  576.  
  577. function ParseCategoryList($)
  578. {
  579.     $(".left-menu > form > li > a").each((index, clHRefElem) =>
  580.     {
  581.         currCid ++;
  582.         ParseCategory(clHRefElem, currCid);
  583.     });
  584. }
  585.  
  586. function Main()
  587. {
  588.     Initialize();
  589.     LoadDocument("http://sumkini.ru/catalogue", ($) =>
  590.     {
  591.         ws.info("Index document has been loaded".Info);
  592.         ParseVendors($);
  593.         ParseMaterials($);
  594.         ParseCategoryList($);
  595.     });
  596. }
  597.  
  598. Main();
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement