同一篇通稿被十个网站转载,页面若只数链接,会显示“10 个独立来源”,可信指数也被虚高。新闻核验真正要统计的是相互独立的证据源,以及这些来源分别支持或反驳了哪条陈述。
新闻可信度看板已经展示可信指数、独立来源和待核事实,场景页也区分官方发布、现场媒体和社交平台。我将页面数据拆成陈述、来源和证据三层,使“来源数量”不再等于 URL 数量。
一条新闻可以包含多条待核陈述
整篇新闻只有一个真假值会丢失细节。同一报道中的时间可能已经证实,伤亡数字仍在变化,地点描述也可能有误。
exporttypeClaimStatus='unverified'|'supported'|'disputed'|'insufficient'exporttypeEvidenceStance='support'|'contradict'|'context'exportinterfaceClaim{id:stringtext:stringstatus:ClaimStatus updatedAt:number}exportinterfaceSource{id:stringpublisher:stringcanonicalUrl:stringoriginId:stringpublishedAt:numbersourceType:'official'|'media'|'eyewitness'|'social'}exportinterfaceEvidence{id:stringclaimId:stringsourceId:stringstance:EvidenceStance excerpt:stringcapturedAt:number}originId表示内容最初来源。转载站点可以拥有不同Source.id和网址,但只要追溯到同一篇原稿,它们就在独立性统计中归为一组。
URL 先规范化,再判断转载关系
常见链接带有追踪参数和锚点。若不清理,同一页面就可能被当成多个来源。
exportfunctioncanonicalize(raw:string):string{try{consturl=newURL(raw)constremovable=['utm_source','utm_medium','utm_campaign','from','share']removable.forEach((key:string)=>url.searchParams.delete(key))url.hash=''url.hostname=url.hostname.toLocaleLowerCase()if(url.pathname.length>1&&url.pathname.endsWith('/')){url.pathname=url.pathname.slice(0,-1)}returnurl.toString()}catch(_){returnraw.trim()}}exportfunctionuniqueOrigins(sources:Source[]):Source[]{constmap=newMap<string,Source>()sources.forEach((source:Source)=>{constkey=source.originId.length>0?source.originId:canonicalize(source.canonicalUrl)constprevious=map.get(key)if(!previous||source.publishedAt<previous.publishedAt){map.set(key,source)}})returnArray.from(map.values())}仅靠 URL 不能可靠识别所有转载。真实服务还需要内容指纹、引用链和人工确认;本地界面先允许录入originId,把独立性规则放在模型中,而不是写死为域名数量。
每条陈述独立计算状态
来源可信度不能替代证据关系。官方来源可能只确认事件发生,没有确认传播最广的数字。状态计算只看与当前陈述关联的证据。
exportinterfaceClaimAssessment{claimId:stringstatus:ClaimStatus independentSupport:numberindependentContradiction:number}exportfunctionassessClaim(claim:Claim,evidence:Evidence[],sources:Source[]):ClaimAssessment{constsourceMap=newMap(sources.map((source:Source)=>[source.id,source]))constrelated=evidence.filter((item:Evidence)=>item.claimId===claim.id)constsupport=newSet<string>()constcontradiction=newSet<string>()related.forEach((item:Evidence)=>{constsource=sourceMap.get(item.sourceId)if(!source||item.stance==='context')returnconstorigin=source.originId||canonicalize(source.canonicalUrl)if(item.stance==='support')support.add(origin)if(item.stance==='contradict')contradiction.add(origin)})letstatus:ClaimStatus='unverified'if(support.size>=2&&contradiction.size===0)status='supported'elseif(contradiction.size>0)status='disputed'elseif(support.size===1)status='insufficient'return{claimId:claim.id,status,independentSupport:support.size,independentContradiction:contradiction.size}}这里设定“两份独立支持且无反证”为本地演示规则,不代表新闻事实核验的通用结论。界面应把依据数量和冲突状态展示出来,让读者知道评分如何形成。
看板评分保留待核数量
总分是导航信息,不能覆盖明细。我根据已支持、存在争议和证据不足的陈述生成简单分数,同时返回待核数量。
exportinterfaceBoardSummary{score:numberindependentSources:numberpendingClaims:numberassessments:ClaimAssessment[]}exportfunctionsummarizeBoard(claims:Claim[],evidence:Evidence[],sources:Source[]):BoardSummary{constassessments=claims.map((claim:Claim)=>assessClaim(claim,evidence,sources))constraw=assessments.reduce((sum:number,item:ClaimAssessment)=>{if(item.status==='supported')returnsum+100if(item.status==='insufficient')returnsum+55if(item.status==='disputed')returnsum+25returnsum+40},0)constscore=assessments.length===0?0:Math.round(raw/assessments.length)constpendingClaims=assessments.filter((item:ClaimAssessment)=>item.status!=='supported').lengthreturn{score,independentSources:uniqueOrigins(sources).length,pendingClaims,assessments}}页面上的“可信指数 82”“独立来源 7”“待核事实 3”就可以从同一份BoardSummary读取。点击待核数量时,列表过滤到status !== 'supported',不用另外维护一套待办数组。
晚到证据不覆盖人工结论
证据抓取可能异步完成。自动评估结果到达时,如果用户已经人工标记陈述,需要保留人工版本。模型可以增加decisionSource和修订号。
exportinterfaceClaimDecision{claimId:stringstatus:ClaimStatus decisionSource:'automatic'|'manual'revision:number}exportfunctionapplyAutomaticDecision(current:ClaimDecision,next:ClaimDecision):ClaimDecision{if(current.decisionSource==='manual'){returncurrent}returnnext.revision>=current.revision?next:current}报告页可以继续使用环形综合评分,但“值得关注”区域应由争议项和待核项生成,而不是固定文案。
当前项目使用本地演示数据,不会自动判断现实新闻真伪。后续接入抓取或检索服务时,外部能力只负责产生来源与证据;来源归并、陈述状态、人工覆盖和页面选择仍留在本地业务层。即使一下子导入几十个链接,看板统计的也会是证据链,而不是链接数量。