| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130 |
- """Create a local browsing page and review note for the source-bound evidence sidecar."""
- import argparse
- from html import escape
- import json
- from pathlib import Path
- import shutil
- ROOT=Path(__file__).resolve().parents[1]
- def main():
- p=argparse.ArgumentParser(description=__doc__)
- p.add_argument('--prepared',type=Path,required=True)
- p.add_argument('--audit',type=Path,required=True)
- args=p.parse_args()
- policy=json.loads((args.prepared/'policy-usage.json').read_bytes())
- coverage=json.loads((args.audit/'coverage-matrix.json').read_bytes())
- ranks=json.loads((args.audit/'ranking-source-readiness.json').read_bytes())
- assert policy['generation']==coverage['generation']==ranks['generation']
- for source in args.audit.glob('*.json'):
- shutil.copyfile(source,args.prepared/source.name)
- (args.prepared/'scripts').mkdir(exist_ok=True)
- for name in ('query-industry-policy-usage.py','build-industry-policy-usage.py','audit-industry-free-mainline.py','render-industry-policy-usage.py'):
- shutil.copyfile(ROOT/'scripts'/name,args.prepared/'scripts'/name)
- states={'PDF_PAGE_VERIFIED':'PDF原页已核','ARCHIVED_OFFICIAL_HTML_VERIFIED':'归档官方HTML已核','PENDING_ORIGINAL':'待原件'}
- clause_table='\n'.join('| '+str(r['sourceLine'])+' | '+r['documentId']+' | '+r['clause']+' | '+states[r['verification']]+' | '+r['topic']+' |' for r in policy['clauses'])
- stores_table='\n'.join('| '+r['name']+' | '+str(r['historicalListingProducts'])+' / '+str(r['currentSnapshotProducts'])+' | '+str(r['snapshotReviewRows'])+' | '+str(r['snapshotPriceRows'])+' | '+str(r['productsWithDetailResponse'])+' / '+str(r['productsWithDetailText'])+' |' for r in coverage['stores'])
- date_table='\n'.join('| '+r['documentId']+' | '+r['metadataPublishedAtRaw']+' | '+str(r['visiblePublishedDate'])+' |' for r in policy['documents'] if r.get('publicationDateConflict'))
- details=[]
- for r in policy['clauses']:
- if r['verification']=='PENDING_ORIGINAL':continue
- refs=[]
- for ref in r['sourceReferences']+r.get('supportingSourceReferences',[]):
- if ref.get('pdfPage'):
- refs.append('['+r['documentId']+' PDF第'+str(ref['pdfPage'])+'页 / 印刷第'+ref['printedPage']+'页]('+ref['file']+'#page='+str(ref['pdfPage'])+')')
- else:
- refs.append('['+ref['headingStart']+'原文]('+ref['file']+')(抽取文本字符'+str(ref['textStart'])+'至'+str(ref['textEndExclusive'])+',右端不含)')
- details.append('### '+str(r['sourceLine'])+' · '+r['topic']+'\n\n适用:'+r['applies']+'。\n\n所需资料:'+';'.join(r['inputs'])+'。\n\n'+
- '\n'.join(str(i)+'. '+step for i,step in enumerate(r['steps'],1))+'\n\n使用边界:'+r['limits']+'\n\n原文定位:'+';'.join(refs)+'。\n\n完整条款ID:`'+r['clauseId']+'`。\n')
- report=f'''# 政策使用证据与主线覆盖核查
- 核查日期:2026-11-08。固定库代际:`{policy['generation']}`。这是一份本地只读核查交付,尚未导入线上库或发布到看板。
- ## 已完成和未完成
- 9份PDF与库内期望SHA逐件一致,9个封面的标准号、标题和日期已看图核对。只对本次引用的相关页面作实质核验,不将全部388页说成逐页审读。GB17400、GB29921无可抽取文字层,未把空文本误判为没有正文。
- 25份资料中,13份有匹配原件(9 PDF、4份归档官方HTML),12份仍缺匹配原件。31条全部建成核查记录,其中7条PDF引用、5条官方HTML引用已核,19条待原件。4份HTML的原始观察时间保留为2026-11-04;本轮没有新取官方页面,没有证明今天仍然有效。
- 本次补充了钠与纤维声称的表注、适用对象和计量基准,并为12条已核记录逐条写了输入、方法和边界。核心信息8处在蔬菜水果章节,摘要应保留该语境。方法与研发解释分别标识,不当作法规原句;每条保留完整条款ID供Agent查询。
- ## 31条核查索引
- | 序 | 文件ID | 条款 | 原文核查 | 主题 |
- | --- | --- | --- | --- | --- |
- {clause_table}
- ## 已核条款的具体用法
- {chr(10).join(details)}
- ## 日期差异保留
- 以下3份归档HTML的元数据PubDate与页面可见发布时间不同。两者均保留,不根据URL目录日期或元数据替选一个“正确日期”;不影响本次文字与原件SHA的对应核验,发布日期仍待官方澄清。
- | 文件 | 元数据日期时间 | 页面可见日期 |
- | --- | --- | --- |
- {date_table}
- 2025版GB7718、GB28050封面均标2027-03-16实施,本轮未核后续修订和过渡安排;不只凭实施日期推导完整现行状态。
- ## 主店和竞品的真实覆盖
- 主店京东1000084104:165件,79件有评价;746行→去无正文28行后718行→同商品主评/追评组合去重701份。85件有284条历史价格观察;41件有详情响应,其中12件有详情文字。已核全可访问评价历史商品数为0。每件商品的证据状态、价格来源日期、规格状态和详情来源SHA均见`coverage-matrix.json`。
- | 门店 | 历史目录 / 当前库目录 | 评价行 | 历史价格行 | 有详情响应 / 有详情文字商品 |
- | --- | --- | --- | --- | --- |
- {stores_table}
- 历史目录为2026-11-04的8店64页1444件;当前库对应目录1445件,白象202/203分列,不推断新增或下架。现有库不等于全平台全品类;上述评价仅描述收录覆盖,不用于销量或市场发生率。标题宣称不冒充详情原文,详情字段顺序也不代表页面视觉卖点排序。
- 逐商品真实付费缺页量和金额仍未知。50项只是历史第2页候选,不能作为当前派发队列;244页/¥73.20估算不采用。
- ## 榜单入口核查
- 复核封存目录与55份原详情证据,确认21个真实榜ID;仍只属于详情徽标。归档中可解析到部分官方活动跳转候选,但本轮未新抓榜页,榜型、周期、TopN及完整范围仍未核。完整Top100=0、Top400=0,不能生成上升或新入榜比较。
- 现有目录没有声明京东/天猫完整商品榜接口,这是本地能力目录的边界,不证明所有供应商都不支持。快手购物榜只声明子榜参数,未核面类范围、分页和TopN,不能替代京东/天猫目标。4项“京东/天猫×100/400”分别保留来源缺口,见`ranking-source-readiness.json`。
- ## Agent使用
- ```powershell
- py -3.14 -X utf8 -B scripts/query-industry-policy-usage.py --input policy-usage.json --keyword 钠
- py -3.14 -X utf8 -B scripts/query-industry-policy-usage.py --input policy-usage.json --document-id GB17400-2015
- py -3.14 -X utf8 -B scripts/query-industry-policy-usage.py --input policy-usage.json --include-pending --limit 100
- ```
- 查询默认只返回有原件核查的记录;待核记录必须显式包含。输出含代际、数据SHA、原文定位、实际使用步骤及未知项,不触发网络或写库。`index.html`可直接打开,支持政策搜索、核验状态筛选、逐商品范围查看与榜单ID回查。
- ## 后续条件
- 1. 政策:补12份文件的匹配原件及相关批准/标准附件,才能关闭19条待核;3份日期差异继续保留。
- 2. 采集:在本次覆盖矩阵上核实际可访问范围、发前认领和预算;持续监听还需频率。已有成功响应复用、收费缺正文找旧件、归属冲突阻断分别处理。
- 3. 榜单:先落实真正完整的面类商品榜来源,再取首期与同口径第二期;不由单次徽标拼榜。
- 本轮上游调用0、付费0、研究数据库写入0、生产变更0。已扣¥46.20、未决¥0、保护¥3.80;收费保持停止。A/B/C、八店v3、线上服务和机会排序未调整。主线尚未全部完成。
- '''
- total_pages=sum(r.get('pdfPages',0) for r in policy['documents'])
- report=report.replace('全部388页',f'全部{total_pages}页')
- (args.prepared/'README.md').write_text(report,encoding='utf-8',newline='\n')
- payload=json.dumps({'policy':policy,'coverage':coverage,'rankings':ranks},ensure_ascii=False).replace('<','\\u003c')
- html=r'''<!doctype html><html lang="zh-CN"><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>行业数据核查 · 2026-11-08</title>
- <style>
- :root{font-family:system-ui,"Microsoft YaHei",sans-serif;color:#172c32;background:#f4f6f5;font-size:15px}*{box-sizing:border-box}body{margin:0}header,main{max-width:1160px;margin:auto;padding:24px}header{padding-bottom:12px}h1{font-size:28px;margin:0 0 8px}h2{font-size:20px}p{line-height:1.65}small,.muted{color:#53666c}.lead{max-width:850px}nav{display:flex;flex-wrap:wrap;gap:8px;margin:18px 0}button,input,select{font:inherit;border:1px solid #b9c8c7;border-radius:7px;padding:10px 12px;background:white}button{cursor:pointer}button.active{background:#115d55;color:white;border-color:#115d55}.tools{display:flex;gap:10px;flex-wrap:wrap;margin-bottom:16px}.tools input{flex:1;min-width:180px}.tools select{max-width:100%}.stats{display:flex;gap:12px;flex-wrap:wrap;margin-bottom:14px}.stat{background:#e4eeeb;border-radius:8px;padding:12px 18px}.stat strong{font-size:24px;display:block}.card{background:white;border:1px solid #d9e3e0;border-radius:10px;padding:20px;margin:12px 0;overflow-wrap:anywhere}h3{margin:0 0 10px;font-size:18px}.tag{font-size:12px;border-radius:4px;background:#e4efea;color:#21634d;padding:4px 7px;display:inline-block}.pending{background:#fff0d7;color:#885b11}.label{font-weight:600}.steps{line-height:1.8;padding-left:22px}details{margin-top:14px}summary{cursor:pointer;color:#135d56}pre{white-space:pre-wrap;overflow-wrap:anywhere;background:#f4f7f6;padding:12px;font:13px/1.6 ui-monospace,monospace}a{color:#115d55}.tablebox{overflow:auto}table{border-collapse:collapse;min-width:620px;width:100%;font-size:14px}th,td{text-align:left;padding:10px;border-bottom:1px solid #e1e7e5}th{background:#eaf0ed}code{overflow-wrap:anywhere}.note{border-left:3px solid #cf9b47;padding:8px 12px;background:#fff5e2}footer{max-width:1160px;margin:auto;padding:24px;color:#56676b}@media(max-width:560px){header,main{padding:16px}h1{font-size:24px}.card{padding:16px}.stat{flex:1;min-width:90px;padding:10px}.stat strong{font-size:22px}.tools select{width:100%}}
- </style><header><small>本地核查交付 · 2026-11-08</small><h1>政策使用证据与数据覆盖</h1><p class="lead">查原文、看适用条件,再使用研究解释。31条款中12条已核原件,19条继续待核。商品和榜单均显示实际收录范围。</p><nav><button class="active" data-tab="policy">政策条款</button><button data-tab="coverage">商品覆盖</button><button data-tab="rankings">榜单来源</button></nav></header><main><div id="stats" class="stats"></div><div class="tools"><input id="search" placeholder="搜索主题、原文、完整ID" aria-label="搜索"><select id="status" aria-label="核验状态"><option value="">全部核验状态</option><option value="verified">已有原件核验</option><option value="pending">待原件</option></select></div><p id="count" class="muted" aria-live="polite"></p><div id="results"></div></main><footer>固定代际82b104fc… · 只读现有资料 · 新增付费0 · 本地交付尚未发布到线上看板<br>方法与应用建议不等同法规原句;本次原件核查不代替当前法律状态核查或商品检测。</footer><script type="application/json" id="data">__PAYLOAD__</script><script>
- const data=JSON.parse(document.getElementById('data').textContent),labels={PDF_PAGE_VERIFIED:'PDF原页已核',ARCHIVED_OFFICIAL_HTML_VERIFIED:'归档官方HTML已核',PENDING_ORIGINAL:'待原件'};let tab='policy';
- const esc=v=>String(v??'').replace(/[&<>"']/g,c=>({'&':'&','<':'<','>':'>','"':'"',"'":'''}[c]));const list=a=>'<ol class="steps">'+a.map(x=>'<li>'+esc(x)+'</li>').join('')+'</ol>';
- function render(){const word=document.getElementById('search').value.toLowerCase(),status=document.getElementById('status').value;document.getElementById('status').hidden=tab!=='policy';const stats=tab==='policy'?[[9,'PDF原件'],[12,'已核条款'],[19,'待核条款']]:tab==='coverage'?[[165,'主店商品'],[79,'有评价'],[12,'有详情文字']]:[[21,'详情榜单ID'],[0,'完整Top100'],[0,'完整Top400']];document.getElementById('stats').innerHTML=stats.map(([v,l])=>'<div class="stat"><strong>'+v+'</strong>'+l+'</div>').join('');let rows,body='';
- if(tab==='policy'){rows=data.policy.clauses.filter(r=>(!word||JSON.stringify(r).toLowerCase().includes(word))&&(!status||(status==='pending')===(r.verification==='PENDING_ORIGINAL')));body=rows.map(r=>'<article class="card"><span class="tag '+(r.verification==='PENDING_ORIGINAL'?'pending':'')+'">'+labels[r.verification]+'</span><h3>'+r.sourceLine+' · '+esc(r.topic)+'</h3><p class="muted">'+esc(r.documentId)+' · '+esc(r.clause)+'</p><p><span class="label">适用:</span>'+esc(r.applies)+'</p><p><span class="label">所需资料:</span>'+esc(r.inputs.join(';'))+'</p>'+list(r.steps)+'<p class="note">'+esc(r.limits)+'</p><details><summary>原文定位与归档摘要</summary><p>归档摘要(保留原证据状态):'+esc(r.archivedExcerpt)+'</p>'+r.sourceReferences.map(ref=>'<p><a target="_blank" rel="noopener" href="'+esc(ref.file+(ref.pdfPage?'#page='+ref.pdfPage:''))+'">'+esc(ref.pdfPage?'PDF第'+ref.pdfPage+'页 / 印刷第'+ref.printedPage+'页':ref.headingStart+'原文')+'</a> · SHA '+esc(ref.sha256)+'</p><pre>'+esc(ref.quote||(ref.quotes?ref.quotes.join('\n'):ref.cells?JSON.stringify(ref.cells,null,2):ref.pageText))+'</pre>').join('')+'<p>完整条款ID:<code>'+esc(r.clauseId)+'</code></p></details></article>').join('');}
- else if(tab==='coverage'){rows=data.coverage.primaryProducts.filter(r=>!word||JSON.stringify(r).toLowerCase().includes(word));body='<div class="card"><h3>八店历史与当前库范围</h3><p>历史1444件 / 当前库1445件;不据此推断新增。价格与评价都是收录记录。</p><div class="tablebox"><table><tr><th>店铺</th><th>历史/库内</th><th>评价行</th><th>价格行</th><th>详情文字商品</th></tr>'+data.coverage.stores.map(r=>'<tr><td>'+esc(r.name)+'</td><td>'+r.historicalListingProducts+'/'+r.currentSnapshotProducts+'</td><td>'+r.snapshotReviewRows+'</td><td>'+r.snapshotPriceRows+'</td><td>'+r.productsWithDetailText+'</td></tr>').join('')+'</table></div></div>'+rows.map(r=>'<article class="card"><h3>'+esc(r.title)+'</h3><p><code>'+esc(r.productId)+'</code></p><p>评价 '+r.reviewRows+' 行 · 历史价格 '+r.priceObservations+' 条 · '+(r.detailTextAvailable?'有详情文字':r.detailResponseAvailable?'有详情响应,文字未齐':'无已核详情响应')+'</p><p class="muted">当前评价边界未核;新增请求数未知,派发关闭。</p><details><summary>逐项证据状态</summary><pre>'+esc(JSON.stringify(r,null,2))+'</pre></details></article>').join('');}
- else{rows=data.rankings.rows.filter(r=>!word||JSON.stringify(r).toLowerCase().includes(word));body='<p class="note">以下是详情徽标中的真实榜ID。榜型、周期、TopN及完整范围未核;完整榜单快照为0,不能比较排名趋势。</p>'+rows.map(r=>'<article class="card"><span class="tag pending">详情徽标线索</span><h3>'+esc(r.labels[0])+'</h3><p>平台 '+esc(r.platform)+' · 榜ID <code>'+esc(r.rankId)+'</code> · '+r.badgeObservations+' 次历史徽标记录</p><details><summary>已有来源与待核条件</summary><pre>'+esc(JSON.stringify(r,null,2))+'</pre></details></article>').join('');}
- document.getElementById('count').textContent='匹配 '+rows.length+' 项';document.getElementById('results').innerHTML=body||'<p class="card">没有匹配的记录。</p>';}
- document.querySelectorAll('[data-tab]').forEach(b=>b.addEventListener('click',()=>{tab=b.dataset.tab;document.querySelectorAll('[data-tab]').forEach(x=>x.classList.toggle('active',x===b));document.getElementById('search').value='';render()}));document.getElementById('search').addEventListener('input',render);document.getElementById('status').addEventListener('change',render);render();
- </script></html>'''.replace('__PAYLOAD__',payload)
- (args.prepared/'index.html').write_text(html,encoding='utf-8',newline='\n')
- print(json.dumps({'ok':True,'clauses':31,'primaryProducts':165,'rankIds':21,'htmlBytes':len(html.encode()),'pdfPagesInOriginals':total_pages},ensure_ascii=False))
- if __name__=='__main__':
- main()
|