import json,math,re,collections P=json.load(open('cost_plan.json',encoding='utf-8')); D=json.load(open('cost_detail.json',encoding='utf-8')) PACK={'C382328':1,'C1525':100,'C163651':20,'C22383480':10,'C440198':20,'C25894':100,'C25744':100,'C25900':100,'C2887585':20,'C49851':1,'C841779':10,'C2570006':10,'C25741':100,'C5210749':1,'C377773':50,'C38117':5,'C12891':10,'C43473':100,'C76857':1,'C25854':100,'C9900163599':1,'C50951':10,'C130026':1,'C5215473':1,'C478081':1,'C2762192':5,'C1547':100,'C25752':100,'C52923':100,'C165948':5,'C25905':100,'C25765':100,'C6186':1,'C116575':5,'C26083':50,'C19188869':1,'C11702':100,'C20917':5,'C2891776':50,'C15127':5,'C8678':20,'C25756':100,'C2847671':50,'C13564':25,'C310990':1,'C151920':20,'C307331':50,'C28323':50,'C42459160':1,'C25750':100,'C3188410':1,'C780205':1,'C25745':100,'C84248':1,'C2653873':1,'C11537':100,'C15195':100,'C13594':50,'C1546':100,'C29402':100,'C25792':100,'C8545':20,'C2934046':20,'C407675':100,'C25755':100,'C310998':10,'C2688893':1,'C36871':100,'C225104':1,'C353034':1,'C3828985':1,'C15008':10,'C5221288':20,'C424561':1,'C2687116':1,'C131941':1,'C25796':100} ASSUMED={'C76857':'包装数未写明,按 1 只计','C15195':'包装数未写明,按 100 只计','C6186':'包装数未写明,按 1 只计','C25741':'改用欧贝顿 0402 100K 1% 100个(¥2,页面实测)'} KEY={'C84248','C2653873','C49851','C478081','C5215473','C2688893','C3188410','C9900163599'} LC_ESP=36.1474 rows=[]; ship=collections.defaultdict(float); shipnote={} for p in P: sid=p['sid']; d=D.get(sid) or {} price=float(d['price']); shop=d['shop']; url=d['url']; sku=d.get('chosen') if sid=='C25741': price=2.0; shop='欧贝顿旗舰店'; url='https://detail.tmall.com/item.htm?id=608928061564'; sku=['0402 100K 1% 100个']; d={'ship':'免运费'} packs=math.ceil(p['need']/PACK[sid]); cost=round(packs*price,2) s=d.get('ship') or '' m=re.match(r'([\d.]+)',s); sv=float(m.group(1)) if m else (0.0 if '免运费' in s else 4.0) if not m and '免运费' not in s: shipnote[shop]='页面未给运费,按 ¥4 估' ship[shop]=max(ship[shop],sv) lc=p['lcsc'] if sid!='C9900163599' else LC_ESP rows.append(dict(sid=sid,mid=p['mid'] if sid!='C9900163599' else 'ESP32-S3-WROOM-1-N16R8',need=p['need'],shop=shop,sku=' / '.join(x for x in (sku or []) if x),price=price,pack=PACK[sid],packs=packs,cost=cost,lcsc=lc,lcsc_cost=round(lc*p['need'],2) if lc else None,url=url,note=ASSUMED.get(sid,''),key=sid in KEY)) goods=sum(r['cost'] for r in rows); sh=sum(ship.values()) print('goods',round(goods,2),'ship',round(sh,2),'shops',len(ship),'total',round(goods+sh,2)) alt=goods-sum(r['cost'] for r in rows if r['key'])+sum(r['lcsc_cost'] for r in rows if r['key']) kshops={r['shop'] for r in rows if r['key']}; nonkey_shops={r['shop'] for r in rows if not r['key']} sh_alt=sum(v for k,v in ship.items() if k in nonkey_shops) print('alt keyIC via LCSC: goods',round(alt,2),'ship(taobao)',sh_alt,'total',round(alt+sh_alt,2)) print('key taobao',round(sum(r['cost'] for r in rows if r['key']),2),'key lcsc',round(sum(r['lcsc_cost'] for r in rows if r['key']),2)) byshop=collections.defaultdict(lambda:[0,0.0]) for r in rows: byshop[r['shop']][0]+=1; byshop[r['shop']][1]+=r['cost'] for k,v in sorted(byshop.items(),key=lambda x:-x[1][1]): print(f' {k[:14]:14} {v[0]:2}种 货¥{v[1]:.2f} 运费¥{ship[k]} {shipnote.get(k,"")}') for r in sorted(rows,key=lambda r:-r['cost'])[:15]: print(f" {r['mid'][:22]:22} x{r['need']:<3} ¥{r['price']}/{r['pack']} ×{r['packs']} = ¥{r['cost']} (立创 ¥{r['lcsc_cost']})") json.dump(dict(rows=rows,ship=ship,shipnote=shipnote,goods=goods,shipsum=sh,alt=alt,sh_alt=sh_alt),open('total.json','w',encoding='utf-8'),ensure_ascii=False,indent=1)