#!/bin/python #coding: utf-8 # +------------------------------------------------------------------- # | django-vue-lyadmin # +------------------------------------------------------------------- # | Author: lybbn # +------------------------------------------------------------------- # | QQ: 1042594286 # +------------------------------------------------------------------- # | Date: 2023-07-20 # +------------------------------------------------------------------- # 抖音商品同步 # ------------------------------ from utils.douyin.douyin_utils import douyin from utils.douyin.doudian_utils import doudian from utils.douyin.douyinUnion_utils import douyinUnion from utils.common import formatdatetime_convert,formatdatetime from apps.lyTiktokUnion.models import DYSystemAccount,DyProductSaleData,DyAwardTaskManage,DyColonelActivityManage,DyProductManage,DyShopManage,DyProductCategoryManage import datetime from config import DOUYIN_OPENAPI_CLIENT_KEY,DOUYIN_OPENAPI_CLIENT_SECRET,DOMAIN_HOST,DOUDIAN_TUANZHUANG_ZIYAN_APPKEY,DOUDIAN_TUANZHUANG_ZIYAN_APPSECRET,DOUDIAN_DKLIVE_ZIYAN_APPKEY,DOUDIAN_DKLIVE_ZIYAN_APPSECRET,DOUDIAN_DKFX_TOOL_APPKEY,DOUDIAN_DKFX_TOOL_APPSECRET import logging logger = logging.getLogger(__name__) newdoudian_tz_yz = doudian(app_key=DOUDIAN_TUANZHUANG_ZIYAN_APPKEY,app_secret=DOUDIAN_TUANZHUANG_ZIYAN_APPSECRET,app_type="tool",code="test") newdouyin = douyin(client_key=DOUYIN_OPENAPI_CLIENT_KEY,client_secret=DOUYIN_OPENAPI_CLIENT_SECRET) newdouyinUnion = douyinUnion(client_key=DOUYIN_OPENAPI_CLIENT_KEY,client_secret=DOUYIN_OPENAPI_CLIENT_SECRET) newdoudian_dklive_yz = doudian(app_key=DOUDIAN_DKLIVE_ZIYAN_APPKEY,app_secret=DOUDIAN_DKLIVE_ZIYAN_APPSECRET,app_type="tool",code="test") newdoudian_dkfx_gj = doudian(app_key=DOUDIAN_DKFX_TOOL_APPKEY,app_secret=DOUDIAN_DKFX_TOOL_APPSECRET,app_type="tool",code="test") def lyFloat(string): try: if string: return float(string) return 0 except: return 0 def get_page_count(total, per_page): """ 计算分页总数 :param total: 记录总数 :param per_page: 每页记录数 :return: 分页总数 """ page_count = total // per_page if total % per_page != 0: page_count += 1 return page_count def get_product_detail_brief(data): """ 处理商品详情中的商品装修图,改为数组 """ new_data = [] if not data: return new_data for i in data: new_data.append(i.get('image').get('pic_url')) return new_data # 检查达人账号授权是否过期 def checkDouyinAccountExpire(instance): """ instance 为用户抖音达人授权数据对象 return : 返回用户access_token和是否过期,为True表示已过期,前面access_token内容为报错消息内容 """ now = datetime.datetime.now() if instance.access_token_expire >= now: return instance.access_token,False if instance.refresh_token_expire >=now: res = newdouyin.refresh_access_token(instance.refresh_token) if not res: return "刷新token错误",True if "error_code" in res["data"] and not res["data"]["error_code"] == 0: return "获取刷新access_token失败,错误码:%s,描述:%s"%(res["data"]["error_code"],res["data"]["description"]),True res = res['data'] access_token = res.get("access_token") instance.access_token = access_token expires_in = res.get("expires_in") access_token_expire = now + datetime.timedelta(seconds=int(expires_in)) instance.access_token_expire = access_token_expire instance.save() return access_token,False return "该抖音账号已过期,请重新授权",True #获取精选联盟商品分类 #https://buyin.jinritemai.com/dashboard/service-provider/doc-center?docId=637 def getAllianceGoodsCategory(parent_id=0): path = '/alliance/materialsProductCategory' params = {"parent_id":parent_id} result = newdoudian_tz_yz.request(path=path, params=params) return result #精选联盟商品同步(未完成) def allianceGoodsSync(): """ return:False失败,True成功 """ instance = DYSystemAccount.objects.filter(is_delete=False).first() msgData,isexpire = checkDouyinAccountExpire(instance) if isexpire: logger.error("同步精选联盟商品-请求商品列表,检查token已过期,内容:%s"%msgData) return False params = {"search_type":0,"sort_type":0,"page":1,"page_size":20} result = newdouyinUnion.product_list_search(access_token=msgData,open_id=instance.open_id,params=params) return True #获取精选联盟商品分类(行业类目) #https://buyin.jinritemai.com/dashboard/service-provider/doc-center?docId=1882 def getActivityProductCategoryList(): path = '/alliance/activityProductCategoryList' params = {} result = newdoudian_tz_yz.request(path=path, params=params) return result # 同步商品行业类目 def activityProductCategoryListSync(): """ return:False失败,True成功 """ result = getActivityProductCategoryList() if result and result.get("code") == 10000: data = result.get("data").get("category_list") for i in data: DyProductCategoryManage.objects.get_or_create(category_id=i.get("category_id"),defaults={'name':i.get("name")}) return True return False #获取团长活动列表 #https://buyin.jinritemai.com/dashboard/service-provider/doc-center?docId=1330 def getAllianceColonelActivityList(status=0,search_type=0,sort_type=0,page=1,page_size=20): """ status : 活动状态。0:任意状态; 1:未上线; 2:报名未开始; 3:报名中; 4:推广未开始; 5:推广中; 7:报名结束 search_type: 排序选项,0:创建时间; 1:活动报名开始时间排序;2:活动报名结束时间排序 """ path = '/alliance/instituteColonelActivityList' params ={"status":status,"search_type":search_type,"sort_type":sort_type,"page":page,"page_size":page_size} result = newdoudian_tz_yz.request(path=path, params=params) return result # 同步团长活动列表 def allianceColonelActivityListSync(status=0,search_type=0,sort_type=0,page=1,page_size=20): """ return:False失败,True成功 """ result = getAllianceColonelActivityList(status=status,search_type=search_type,sort_type=sort_type,page=page,page_size=page_size) logger.info("同步团长活动列表,第%s页,返回内容:%s"%(page,result)) if result and result.get("code") == 10000: total = int(result.get("data").get("total")) total_page = get_page_count(total,page_size) data = result.get("data").get("activity_list") colonel_buyin_id = result.get("data").get("colonel_buyin_id") institution_id = result.get("data").get("institution_id") for i in data: instance,created = DyColonelActivityManage.objects.get_or_create(activity_id=i.get("activity_id"),defaults={"activity_name":i.get("activity_name"),"activity_start_time":i.get("activity_start_time"),"activity_end_time":i.get("activity_end_time"),"status":i.get("status"),"colonel_buyin_id":colonel_buyin_id,"institution_id":institution_id}) if not created: instance.activity_name = i.get("activity_name") instance.activity_start_time = i.get("activity_start_time") instance.activity_end_time = i.get("activity_end_time") instance.status = i.get("status") instance.colonel_buyin_id = colonel_buyin_id instance.institution_id = institution_id instance.update_datetime = datetime.datetime.now() instance.save() if page 0: total_page = get_page_count(total,count) data = result.get("data").get("data") institution_id = result.get("data").get("institution_id") product_ids = [] product_ids_delete = [] for i in data: status = i.get("status")#活动商品状态:0:待审核;1:推广中;2:申请未通过;3:合作已终止;6:合作已到期 product_id = i.get("product_id") if status == 1: shop_score = lyFloat(i.get("shop_score")) p_data = {'title':i.get("title"),'shop_score':shop_score,'activity_id':activity_id,'detail_url':i.get("detail_url"),'category_id':i.get("category_id"),'category_name':i.get("category_name"),'price':i.get("price"),'sales':i.get("sales"),'cover':i.get("cover"),'cos_ratio':i.get('cos_ratio'),'cos_fee':i.get('cos_fee'),'special_cos_ratio':int(i.get('activity_cos_ratio'))/100,'shop_id':i.get('shop_id'),'is_calc_award':True,'begin_time':activity_start_time,'end_time':activity_end_time} product_ids.append(product_id) instance,created = DyProductManage.objects.get_or_create(product_id=product_id,source=1,defaults=p_data) if not created: p_data['update_datetime'] = datetime.datetime.now() p_data.pop('is_calc_award') p_data.pop('begin_time') p_data.pop('end_time') p_data['is_delete'] = False DyProductManage.objects.filter(product_id=product_id,source=1).update(**p_data) else:#团长下架商品或者商品到期,则平台删除(逻辑)此商品展示 product_ids_delete.append(product_id) #清除失效商品 if product_ids_delete: DyProductManage.objects.filter(product_id__in=product_ids_delete).update(status=False,is_delete=True) #更新商品详情 if product_ids: res_details = getProductsDetail(product_ids=product_ids) logger.info("团长活动商品列表递归同步到数据库(商品详情),product_ids=%s,返回内容:%s"%(product_ids,res_details)) if res_details and res_details.get("code") == 10000: logger.info("更新商品详情到数据库") d_data = res_details.get("data").get("products",[]) if d_data: for i in d_data: #店铺数据更新 shop_info = i.get('shop_info') shop_id = shop_info.get('shop_id') shop_total_score = shop_info.get('shop_total_score') if shop_total_score: shop_info_dic = {'shop_name':shop_info.get('shop_name'),'shop_total_score':shop_total_score,'shop_score':shop_total_score.get('shop_score').get('score'),'shop_score_level':shop_total_score.get('shop_score').get('level')} else: shop_info_dic = {'shop_name':shop_info.get('shop_name'),'shop_total_score':shop_total_score} logger.info("正在更新店铺信息:%s"%shop_info_dic) s_instance,s_created = DyShopManage.objects.get_or_create(shop_id=shop_id,defaults=shop_info_dic) if not s_created: shop_info_dic['update_datetime'] = datetime.datetime.now() DyShopManage.objects.filter(shop_id=shop_id).update(**shop_info_dic) #商品更新 product_id = i.get("base_info").get('product_id') imgs = i.get("base_info").get('imgs') logistics_info = i.get('logistics_info').get('text') has_sxt = i.get('qualification_info').get('has_sxt') detail_brief = get_product_detail_brief(i.get('detail_brief').get('component_info')) comment_score = i.get('comment_info').get('comment_score') is_assured = i.get('rights_info').get('is_assured') sharable = i.get('share_info').get('sharable') has_subsidy_tag = i.get('tags').get('has_subsidy_tag') has_douin_goods_tag = i.get('tags').get('has_douin_goods_tag') has_shop_brand_tag = i.get('tags').get('has_shop_brand_tag') has_supermarket_tag = i.get('tags').get('has_supermarket_tag') coupon_price = i.get('coupon_info').get('coupon_price') coupon = len(i.get('coupon_info').get('available_coupons',[])) order_num_30 = i.get('month_sale_data').get('order_num',0) view_num_30 = i.get('month_sale_data').get('view_num', 0) kol_num_30 = i.get('month_sale_data').get('kol_num', 0) daily_statistics = i.get('month_sale_data').get('daily_statistics', []) product_queryset = DyProductManage.objects.filter(product_id=product_id) product_queryset.update(view_num=view_num_30,order_num = order_num_30,kol_num = kol_num_30,dyshop=s_instance,coupon_price=coupon_price,coupon=coupon,imgs=imgs,logistics_info=logistics_info,has_sxt=has_sxt,detail_brief=detail_brief,comment_score=comment_score,is_assured=is_assured,has_subsidy_tag=has_subsidy_tag,has_douin_goods_tag=has_douin_goods_tag,has_shop_brand_tag=has_shop_brand_tag,has_supermarket_tag=has_supermarket_tag,sharable=sharable,update_datetime = datetime.datetime.now()) ds_obj_list = [] product_instance = product_queryset.first() for ds in daily_statistics: d_statics_date = datetime.datetime.strptime(ds.get('date'), '%Y%m%d') if not DyProductSaleData.objects.filter(product_id=product_id,date=d_statics_date).exists(): ds_obj_list.append(DyProductSaleData(inner_product_id_id=product_instance.id,product_id=product_id,date=d_statics_date,order_num=ds.get('order_num'),view_num=ds.get('view_num'),kol_num=ds.get('kol_num'))) if ds_obj_list: DyProductSaleData.objects.bulk_create(ds_obj_list) if page