我們公司最近有個需求 ,經產品部門的反應,說現在我們的商品價格和京東不同步,或者說不合理,要我們技術部的人查出原因。
那麼很不幸的是,老大把這個任務交給了我。
我也沒辦法 只能硬着頭皮上。首先我得到一個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;
然後導出
就這樣給公司交了一份滿意的答案。。。。