进口5万多件产品到woocommerce,需要4个多小时



我要发疯了,试图解决这个问题,已经为此工作了两个星期了。我将感激所有的帮助。

我有一个问题,从xml文件导入超过50,000个产品到woocommerce。xml解析很快,不到几分钟就能完成,但是"导入"部分商业是非常缓慢的。

我尝试了wordpress/woocommerce rest api,这是一个很大的不,太慢了。所以现在我在服务器上使用一个PHP文件来解析xml文件并上传它们。

我得到以下格式的XML文件:
<product>
<SKU>28760</SKU>
<Name>...</Name>
<Description>...</Description>
<Category>...</Category>
<Price>...</Price>
<Shipping>...</Shipping>
<Currency></Currency>
<Instock>yes</Instock>
<ProductUrl>...</ProductUrl>
<ImageUrl>...</ImageUrl>
<Brand>...</Brand>
<OriginalPrice>...</OriginalPrice>
<Ean>...</Ean>
<ManufacturerArticleNumber>...</ManufacturerArticleNumber>
</product>

然后在使用XMLReader解析im时,将每个元素/行推入临时数组,然后使用该数组调用导入函数。

功能如下:

  1. Bash脚本运行php import.php>run.log
  2. 导入文件开始,xml解析速度快,但导入速度慢,当达到2000个产品时速度变慢。

我使用WC_Product_Variable类来创建一个新产品。

这是我的函数"import($p, $coId, $coName)"其中$p是product, $coId是companyId, $coName是公司名称,我从那里得到xml文件。

try {
$product_exists = wc_get_product_id_by_sku($p->SKU . "-MAIN");
if ($product_exists !== 0) {
$product = wc_get_product($product_exists);
$log->info('Product already exists, skipping', ["SKU" => $p->SKU . "-MAIN"]);
} else {
$product = new WC_Product_Variable();
$product->set_name($p->Name);
$product->set_sku($p->SKU . "-MAIN");

$category = (string)$p->Category;

$categories = explode(" - ", $category);
$parent_id = 0; 
foreach ($categories as $cat) {     
$term = term_exists($cat, 'product_cat', $parent_id); 
if (!$term) {
$term = wp_insert_term(
$cat, mn
'product_cat', 
array(
'parent' => $parent_id 
)
);
}
// New category id
$parent_id = $term['term_id'];
}
// Upload image to wordpress
$image_url = $p->ImageUrl;
$image_id = media_sideload_image("{$image_url}", 0, null, "id");
if (is_wp_error($image_id)) {
echo "Error uploading image n";
} else {
$product->set_image_id($image_id);
}
$product->set_category_ids(array($parent_id));
$attributes = array();
// one available for variation attribute
$attribute = new WC_Product_Attribute();
$attribute->set_name('Company');
$attribute->set_options(array("{$coName}"));
$attribute->set_position(0);
$attribute->set_visible(true);
$attribute->set_variation(true);
$attributes[] = $attribute;
$attribute = new WC_Product_Attribute();
$attribute->set_name('Brand');
$attribute->set_options(array($p->Brand));
$attribute->set_position(0);
$attribute->set_visible(true);
$attribute->set_variation(false);
$attributes[] = $attribute;
$product->set_short_description((string)$p->Description);
$product->set_attributes($attributes);
$product->set_regular_price($p->OriginalPrice);
$product->set_sale_price($p->Price); 
$product->set_stock_status("outofstock");
$product->save();
$insertTag = wp_set_object_terms($product->get_id(), $p->Brand, "product_tag", true);
if (is_wp_error($insertTag)) {
echo "Cant insert tag for product: " . $insertTag->get_error_message() . " n";
}
}
} catch (Exception $e) {
$log->error("Can't create main product", ["Error" => $e->getMessage(), "Product SKU" => $p->SKU]);
}
try {
// now we need two variations for Magical and Non-magical Wizard hat
$variation = new WC_Product_Variation();
$variation->set_parent_id($product->get_id());
$variation->set_sku((string)$p->SKU . "-" . $coId);
$variation->set_attributes(array('company' => $coName));
$variation->set_regular_price((string)$p->OriginalPrice);
$variation->set_sale_price((string)$p->Price);
$variation->set_stock_status(($p->Instock == "no" ? "outofstock" : "instock"));
$variation->update_meta_data("brand", (string)$p->Brand);
$variation->update_meta_data("updated", (string)Date("Y-m-d H:i:s"));
$variation->save();
} catch (Exception $e) {
$log->error("Can't create variant product", ["Error" => $e->getMessage(), "Product SKU" => $p->SKU]);
}
// Check memory and CPU usage
$load = sys_getloadavg();
$memory_usage = memory_get_usage(true);


if ($load[0] > 1.5 || $memory_usage > 0.9 * $memory_limit) {
$logger->warning('Current memory and CPU usage - PAUSING 10 SEC', [
'loadavg' => $load[0],
'memory' => $memory_usage . " of " . $memory_limit,
]);
sleep(10); // Pause 10 seconds
}

有什么办法可以让它更快吗?现在进口25000件产品大约需要4个小时。

我用的是4GB内存,2个CPU的VPS。

除了这个函数,下面是我的文件在函数之前包含的内容:

set_time_limit(0);
ini_set('memory_limit', '1024M');
ini_set('max_execution_time', 0);

require_once "vendor/autoload.php";
if (!defined('ABSPATH')) {
define('ABSPATH', '/opt/bitnami/projects/****/public_html/');
}
include_once ABSPATH . 'wp-load.php';
include_once ABSPATH . 'wp-includes/class-wp-error.php';
include_once ABSPATH . 'wp-admin/includes/plugin.php';
include_once ABSPATH . 'wp-admin/includes/file.php';
include_once ABSPATH . 'wp-admin/includes/image.php';
require_once(ABSPATH . 'wp-admin/includes/media.php');

use MonologLogger;
use MonologHandlerStreamHandler;
$memory_limit = ini_get('memory_limit');
if (preg_match('/^(d+)(.)$/', $memory_limit, $matches)) {
if ($matches[2] == 'M') {
$memory_limit = $matches[1] * 1024 * 1024; // nnnM -> nnn MB
} else if ($matches[2] == 'K') {
$memory_limit = $matches[1] * 1024; // nnnK -> nnn KB
}
}
// Create a logger
$log = new Logger('import');
$log->pushHandler(new StreamHandler('/opt/bitnami/projects/****/logs/import-' . Date("Y-m-d") . '.log', Logger::INFO));
$log->info('Init import', ["Status" => "Starting up"]);

// Log the current memory and CPU usage
$logger = new MonologLogger('import-usage');
$logger->pushHandler(new MonologHandlerStreamHandler('/opt/bitnami/projects/****/logs/import-' . Date("Y-m-d") . '.log', MonologLogger::DEBUG));

echo "Start import job... n";

为什么不在每一步之后添加时间戳日志呢?另外,我看到你的代码中有sleep(10),它执行的频率是多少?

我认为问题的部分是图像下载。您可以尝试不调用wp_sideload_image导入吗?根据您的图像大小和位置,这一步可能是最长的。也许您可以在另一个步骤中做到这一点,在运行导入之前,您将所有图像下载到服务器,然后在导入过程中附加它们。这有道理吗?

相关内容

最新更新