我们公司最近有个需求 ,经产品部门的反应,说现在我们的商品价格和京东不同步,或者说不合理,要我们技术部的人查出原因。
那么很不幸的是,老大把这个任务交给了我。
我也没办法 只能硬着头皮上。首先我得到一个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;
然后导出
就这样给公司交了一份满意的答案。。。。