PHP實現平臺商品和京東價格做對比

我們公司最近有個需求 ,經產品部門的反應,說現在我們的商品價格和京東不同步,或者說不合理,要我們技術部的人查出原因。

那麼很不幸的是,老大把這個任務交給了我。

我也沒辦法 只能硬着頭皮上。首先我得到一個sku基礎數據,查了一下   有10w多條呢。


最初的做法  我貼出代碼

<?php
set_time_limit(0);
error_reporting(E_ALL^E_NOTICE);
header("Content-type: text/html; charset=utf-8");
require("./jdapi.class.php");
require("./token.php");
date_default_timezone_set('Asia/Shanghai');
$jd = new jdapi();
$refreshToken = '';
$token = get_token($refreshToken);
//讀取csv文件
$csv = 'd:/sku1.csv';
$data = read_csv($csv);
$col = array(
    'sku'=>0,
    'cost_price'=>1
);
echo '<pre>';
$res = '';
foreach ($data as $k =>$one)
{
    $sku = $one[$col['sku']];
    $cost_price = $one[$col['cost_price']];
    //獲取京東的售價 ,如果小於等於我們的成本價就有問題
    $jd_json = $jd->getPrice($token,$sku);
    $arr = json_decode($jd_json,1);
    $hava_pro = '';
    $jd_shoujia = $arr['result'][0]['price'];
    if($jd_shoujia<=$cost_price)
    {
        $hava_pro = '有問題';
    }
    else
    {
        $hava_pro = '正常';
    }
    $res[$k]['sku'] = $sku;
    $res[$k]['cost_price'] = $cost_price;
    $res[$k]['jd_price'] = $jd_shoujia;
    $res[$k]['pro'] = $hava_pro;


}
createcsv($res);
 function read_csv($file)
{
    setlocale(LC_ALL,'zh_CN');//linux系統下生效
    $data = null;//返回的文件數據行
    if(!is_file($file)&&!file_exists($file))
    {
        die('文件錯誤');
    }
    $cvs_file = fopen($file,'r'); //開始讀取csv文件數據
    $i = 0;//記錄cvs的行
    while ($file_data = fgetcsv($cvs_file))
    {
        $i++;
        if($i==1)
        {
            continue;//過濾表頭
        }
        if($file_data[0]!='')
        {
            $data[$i] = $file_data;
        }

    }
    fclose($cvs_file);
    return $data;
}

function createcsv($csv_body)
{
    // 頭部標題
    $csv_header = array('sku','我們自己的成本價','京東自己的銷售價','對比結果');

    /**
     * 開始生成
     * 1. 首先將數組拆分成以逗號(注意需要英文)分割的字符串
     * 2. 然後加上每行的換行符號,這裏建議直接使用PHP的預定義
     * 常量PHP_EOL
     * 3. 最後寫入文件
     */
// 打開文件資源,不存在則創建
    $des_file = 'd:/res.csv';
    $fp = fopen(    $des_file,'a');
// 處理頭部標題
    $header = implode(',', $csv_header) . PHP_EOL;
// 處理內容
    $content = '';
    foreach ($csv_body as $k => $v) {
        $content .= implode(',', $v) . PHP_EOL;
    }
// 拼接
    $csv = $header.$content;
// 寫入並關閉資源
    fwrite($fp, $csv);
    fclose($fp);
}
function buildOrderId()
{
    $randStr = str_shuffle('ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890');
    $rand = substr($randStr,0,6);
    return 'XRY_JD'.date('YmdHis',time()).$rand;
}

function get_token(&$refreshToken)
{
    global $g_token;
    $time = isset($g_token['time'])?$g_token['time']:NULL;
    $expires_in = isset($g_token['expires_in'])?$g_token['expires_in']:NULL;
    $access_token = isset($g_token['access_token'])?$g_token['access_token']:NULL;
    $refreshToken = isset($g_token['refresh_token'])?$g_token['refresh_token']:NULL;
    if($time && $expires_in && $access_token)
    {
        $now = time();
        if(($now + 3600) > ($time/1000 + $expires_in))
        {
            get_token_in($access_token);
        }
    }
    else
    {
        get_token_in($access_token);
    }
    return $access_token;
}

function get_token_in(&$token)
{
    global $jd;
    $json = $jd->getAccessToken();
    $obj = json_decode($json,true);
    if($obj['success'])
    {
        $token = $obj['result']["access_token"];
        //
        $text_token = '<?php $g_token = array(';
        foreach($obj['result'] as $key=>$value)
        {
            $text_token .= '"'.$key.'"=>"'.$value.'",';
        }
        $text_token .= ');';
        $text_token = utf8_encode($text_token);
        $fp=@fopen('./token.php','w');
        if($fp)
        {
            fwrite($fp,$text_token);
            fclose($fp);
        }
    }

    return $json;
}

?>

這個方法 我數據量少的時候 是正常運行 可以得到預期的值,。現在我真實數據10w。發現nginx報504錯誤。。

我就去修改代碼,經過一番查資料我加上如下代碼

set_time_limit(0);

nginx配置文件



依然沒有作用。。。

然後我急了。急沒辦法啊,。

此時我再去讀京東接口文檔,發現 價格查詢接口最多支持100個查詢。多了,。就報錯。。問題1這是。

第二個問題是我一次性操作10w個商品肯定會報錯的,超過php單頁面執行時間了。這個肯定不行,得換個思路。


然後我開始 轉變  ,我把基礎表的數據,導入到一個新表 用來做結果比對錶

先生成比對錶用sql語句

這是比對錶

CREATE TABLE `difen` (
  `id` int(8) NOT NULL AUTO_INCREMENT,
  `sku` varchar(20) NOT NULL,
  `cost_price` decimal(10,2) NOT NULL,
  `price` decimal(10,2) DEFAULT '1.00',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=131071 DEFAULT CHARSET=utf8;

price字段先留空 ,稍後做填充

創建表之後 我們執行以下sql語句

INSERT into difen(sku,price) SELECT g.sku,g.cost_price FROM goodsdb.`goods` g WHERE g.`sale_status` = 1 AND g.`status` = 1 and g.supplier_id=2;

得到一部分對比數據。。

然後我通過程序代碼 把price填充進來

<?php
set_time_limit(0);
error_reporting(E_ALL^E_NOTICE);
header("Content-type: text/html; charset=utf-8");
require("./jdapi.class.php");
require("./token.php");
date_default_timezone_set('Asia/Shanghai');
$jd = new jdapi();
$refreshToken = '';
$token = get_token($refreshToken);
//讀取csv文件
$mysqli = new mysqli('localhost','root','root','test');

while (true){
    $sql1 = "select * from diff where price is null";
    $res = $mysqli->query($sql1);
    $set_sku_arr = '';
    while (($row = $res->fetch_assoc())==true)
    {
        if(count($set_sku_arr)<100)
        {
            $set_sku_arr[] = $row['sku'];
        }
    }

    $str = implode(',',$set_sku_arr);
    $jd_json = $jd->getPrice($token,$str);
    $arr = json_decode($jd_json,1);
    $result_list = $arr['result'];
    //echo '<pre>';print_r($arr);
    $sku_list = '';
    $sql = "UPDATE diff SET price = CASE sku ";
    foreach ($result_list as $res)
    {
        $sku_list[] = $res['skuId'];
        $sql .= sprintf("WHEN \"%s\" THEN \"%.2f\" ", $res['skuId'], $res['jdPrice']); // 拼接SQL語句
    }
    $sku_str = implode(',', array_map("change_to_quotes", $sku_list));
    $sql .= "END WHERE sku IN ($sku_str)";
    //執行
    $mysqli->query($sql);
}
function change_to_quotes($str)
{
    return sprintf("\"%s\"", $str);
}

function get_token(&$refreshToken)
{
    global $g_token;
    $time = isset($g_token['time'])?$g_token['time']:NULL;
    $expires_in = isset($g_token['expires_in'])?$g_token['expires_in']:NULL;
    $access_token = isset($g_token['access_token'])?$g_token['access_token']:NULL;
    $refreshToken = isset($g_token['refresh_token'])?$g_token['refresh_token']:NULL;
    if($time && $expires_in && $access_token)
    {
        $now = time();
        if(($now + 3600) > ($time/1000 + $expires_in))
        {
            get_token_in($access_token);
        }
    }
    else
    {
        get_token_in($access_token);
    }
    return $access_token;
}

function get_token_in(&$token)
{
    global $jd;
    $json = $jd->getAccessToken();
    $obj = json_decode($json,true);
    if($obj['success'])
    {
        $token = $obj['result']["access_token"];
        //
        $text_token = '<?php $g_token = array(';
        foreach($obj['result'] as $key=>$value)
        {
            $text_token .= '"'.$key.'"=>"'.$value.'",';
        }
        $text_token .= ');';
        $text_token = utf8_encode($text_token);
        $fp=@fopen('./token.php','w');
        if($fp)
        {
            fwrite($fp,$text_token);
            fclose($fp);
        }
    }

    return $json;
}

?>

這個執行完,就把price填充好了,。接下來用一條sql語句實現對比 再導出即可

SELECT sku 'sku',cost_price '成本價',price '京東銷售價',(case when price<=cost_price then '不合格' else '合格' end) '對比結果' from difen;

然後導出



就這樣給公司交了一份滿意的答案。。。。大笑





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章