电商知识图谱源码实战:从CSV到图谱的推荐与问答系统搭建

发布时间:2026/10/3 2:54:40
电商知识图谱源码实战:从CSV到图谱的推荐与问答系统搭建 简介这份资源围绕电商行业知识图谱的构建与应用展开面向计算机、人工智能等相关专业的在校学生、教师及企业开发者也适合作为毕业设计、课程设计或项目立项的参考案例。项目以Python实现电商领域实体与关系的抽取和建模可支撑商品推荐、商品搭配与智能问答等典型场景帮助读者理解知识图谱从数据到应用的完整链路。压缩包共59个文件约15.49MB包含21个py源码、10个csv与10个txt数据文件、5个json配置、3个md说明文档以及xmind思维导图、docx产品文档和html可视化页面覆盖数据处理、模型、控制器、服务端与视图等模块。目前已有130人学习下载。代码经过测试运行成功答辩评审平均分达96分读者可据此掌握图谱搭建思路、实体关系设计与问答实现方法并在此基础上修改扩展功能。1. 电商知识图谱这套源码到底能跑出什么电商推荐做久了都会碰到一个尴尬协同过滤能算出「买 A 的人还买 B」但解释不了为什么冷启动商品更是直接躺平。这份 ECKG-master 源码走的是另一条路——用 Python 把电商行业的实体和关系抽出来落成一张知识图谱再拿这张图去喂商品推荐、商品搭配和问答系统。它不是纯理论 demo目录里能看到Model/product.py、Model/user.py、Model/dialogue.py三个模型文件Controller/QSController.py管问答DataHandler/QSHandler.py管数据resources/sql下还有product.csv和refer目录说明数据链路是通的。适合谁做毕设、课设、项目立项演示的学生以及想在自己电商项目里加一层语义推荐的开发者。前提是你得先把 Python 环境和图数据库跑起来不然打开就是一堆 import 报错。2. 先看清数据流从 CSV 到图谱再到推荐2.1 目录结构里藏着的数据链路拿到一个陌生源码包我习惯先看目录再动手。ECKG-master 的结构其实已经把数据流交代得很清楚目录/文件作用关键程度DataHandler/DataHandler.py数据加载与清洗入口高DataHandler/QSHandler.py问答数据预处理高Model/product.py商品实体与关系建模高Model/user.py用户行为建模中Model/dialogue.py问答对话逻辑中Controller/QSController.py问答控制器中Controller/DataController.py数据控制器中resources/sql/product.csv商品原始数据高resources/sql/refer/关系参照数据高Config/config.conf数据库与路径配置高Config/variable.ini变量配置中server/dataserver.py数据服务启动中View/view.html前端展示页低demo.py/test.py入口示例与测试高Config/config.conf和Config/variable.ini是两个必须先改的文件数据库连接、文件路径大概率都塞在这里。resources/sql/product.csv是商品主数据refer目录下的文件负责把商品和品类、属性关联起来。dict目录里那堆food.txt、producer.txt、drug.txt、disease.txt、symptom.txt、deny.txt、check.txt、department.txt是实体词典说明这套图谱不只做电商还预留了医疗领域的扩展口子——这点在毕设答辩时是个加分项你可以说「架构支持多领域词典热插拔」。2.2 环境准备Python 版本与依赖安装源码没给requirements.txt这是第一个坑。我一般会先按目录里的 import 反推依赖。从Model和Controller的命名看大概率用到pandas、numpy图数据库操作可能用py2neo或neo4j驱动Web 服务可能用flask或fastapi。# 建议用 Python 3.8~3.10太新的版本某些图数据库驱动会翻车 python -m venv eckg_env source eckg_env/bin/activate # Windows 用 eckg_env\Scripts\activate # 先装基础三件套 pip install pandas numpy flask # 图数据库驱动按需装常见是 neo4j 或 py2neo pip install neo4j py2neo # 如果跑起来报缺什么再单独补 pip install python-dotenv configparser参数说明虚拟环境目录名eckg_env随便起但别用中文路径Windows 下中文路径会让某些 C 扩展库加载失败。neo4j和py2neo二选一即可看源码里 import 的是哪个。如果Config/config.conf里写的是bolt://localhost:7687那就是 Neo4j 的默认端口说明作者用的是 Neo4j 作为图存储。2.3 配置文件怎么改config.conf 与 variable.ini这两个文件是运行前的必经之路。config.conf通常长这样[database] host localhost port 7687 user neo4j password your_password uri bolt://localhost:7687 [path] data_dir ./resources/sql dict_dir ./dictvariable.ini可能放的是业务变量比如推荐权重、问答匹配阈值。改的时候注意三点第一password必须换成你本地 Neo4j 的实际密码默认neo4j/neo4j首次登录会强制改第二data_dir用相对路径时确保你是在项目根目录执行demo.py否则会找不到 CSV第三如果variable.ini里有中文值保存时选 UTF-8 编码不然configparser读出来是乱码。提示改完配置先别急着跑主程序用python -c import configparser; cconfigparser.ConfigParser(); c.read(Config/config.conf); print(c.sections())验证一下能不能正常解析。3. 把图谱建起来实体抽取与关系写入3.1 从 product.csv 抽实体字段映射与清洗resources/sql/product.csv是商品主表常见字段包括商品 ID、名称、品类、价格、品牌。建图谱第一步是把这些字段映射成实体和属性。我一般会先看一眼 CSV 的列名和几行样本import pandas as pd # 先探数据别上来就写全量逻辑 df pd.read_csv(resources/sql/product.csv, encodingutf-8) print(df.columns.tolist()) print(df.head(3)) print(df.isnull().sum())逻辑说明encodingutf-8是必须的电商商品名里常有中文和特殊符号用默认编码会报UnicodeDecodeError。isnull().sum()看每列缺失情况如果品类列缺失超过 30%那基于品类的推荐逻辑就得加兜底。参数上head(3)只是探路确认列名和数据类型后再写正式的抽取函数。实体抽取的核心思路商品名 → 商品实体品类 → 品类实体品牌 → 品牌实体然后用「属于」「生产于」这类关系连起来。refer目录下的文件大概率就是这些关系的映射表。3.2 用 Cypher 把节点和关系写进图数据库如果底层是 Neo4j写入逻辑通常长这样from py2neo import Graph, Node, Relationship # 连接图数据库地址和密码从 config.conf 读 graph Graph(bolt://localhost:7687, auth(neo4j, your_password)) def create_product_node(row): # 商品节点用商品ID做唯一标识 product Node(Product, product_idstr(row[product_id]), namestr(row[name]), pricefloat(row[price]) if pd.notnull(row[price]) else 0.0) graph.merge(product, Product, product_id) # merge 避免重复插入 return product def create_category_node(category_name): category Node(Category, namecategory_name) graph.merge(category, Category, name) return category # 批量写入别一条条 commit慢到怀疑人生 tx graph.begin() for _, row in df.iterrows(): p create_product_node(row) if pd.notnull(row[category]): c create_category_node(row[category]) rel Relationship(p, BELONGS_TO, c) tx.create(rel) tx.commit()逻辑说明merge而不是create是因为商品数据可能有重复merge会先查再插避免图谱里出现两个相同 ID 的节点。graph.begin()开事务批量提交比每条create单独 commit 快一个数量级。参数上Product和product_id是节点标签和唯一键必须和后续查询语句里的写法一致否则查不到。BELONGS_TO是关系类型名你可以改成中文但建议保持英文避免编码问题。3.3 关系抽取从 refer 目录读搭配规则resources/sql/refer/下的文件是关系参照数据可能是「商品 A 搭配 商品 B」的规则表。读取逻辑import os refer_dir resources/sql/refer for fname in os.listdir(refer_dir): if fname.endswith(.csv): rdf pd.read_csv(os.path.join(refer_dir, fname), encodingutf-8) # 假设列是 source_id, target_id, relation_type for _, r in rdf.iterrows(): src graph.nodes.match(Product, product_idstr(r[source_id])).first() tgt graph.nodes.match(Product, product_idstr(r[target_id])).first() if src and tgt: rel Relationship(src, str(r[relation_type]), tgt) graph.create(rel)逻辑说明os.listdir遍历 refer 目录下所有 CSV这样加新关系文件不用改代码。match(...).first()是防御性写法如果某个商品 ID 在商品表里不存在first()返回None直接跳过避免Relationship报错。relation_type从数据里读说明关系类型是数据驱动的不是硬编码——这点设计得不错扩展性强。注意如果 refer 文件很大逐条graph.create会慢。常见做法是攒够 500 条再批量提交或者用graph.run直接执行 Cypher 的UNWIND语句。4. 推荐、搭配、问答三个应用怎么接4.1 商品推荐基于图谱路径的召回知识图谱做推荐的核心优势是「可解释」。协同过滤说「买 A 的人买 B」图谱可以说「A 和 B 属于同一品类且价格区间相近」。源码里Model/product.py大概率实现了基于关系的召回逻辑。一个典型的查询def recommend_by_category(product_id, top_n10): # 找到目标商品再找同品类其他商品 query MATCH (p:Product {product_id: $pid})-[:BELONGS_TO]-(c:Category)-[:BELONGS_TO]-(rec:Product) WHERE rec.product_id $pid RETURN rec.product_id AS id, rec.name AS name, rec.price AS price ORDER BY abs(rec.price - p.price) ASC LIMIT $top_n result graph.run(query, pidproduct_id, top_ntop_n).data() return result逻辑说明这条 Cypher 先找到目标商品的品类再找同品类下的其他商品最后按价格差排序。$pid和$top_n是参数化查询防止注入也方便复用。ORDER BY abs(rec.price - p.price)是「价格相近优先」的排序策略你可以换成销量、评分等字段。参数top_n控制返回数量线上服务一般设 20~50再交给精排模型。4.2 商品搭配用关系类型做组合推荐搭配推荐和同类推荐不同它找的是「互补品」而不是「替代品」。图谱里如果定义了PAIRS_WITH或GOES_WELL_WITH关系查询就变成def recommend_pairing(product_id, top_n5): query MATCH (p:Product {product_id: $pid})-[:PAIRS_WITH]-(pair:Product) RETURN pair.product_id AS id, pair.name AS name LIMIT $top_n return graph.run(query, pidproduct_id, top_ntop_n).data()逻辑说明PAIRS_WITH关系来自 refer 目录的搭配规则是人工或算法挖掘出来的。如果图谱里没有现成搭配关系可以退而求其次用「同品牌不同品类」或「同场景标签」来近似。参数top_n搭配推荐一般给 3~5 个太多用户看不过来。4.3 问答系统QSController 与 dialogue 的协作问答部分由Controller/QSController.py和Model/dialogue.py配合完成。典型流程是用户输入自然语言问题 →QSHandler做意图识别和实体抽取 →QSController转成图查询 →dialogue组织回答。dict目录下的词典文件在这里派上用场用于实体匹配。# 伪代码示意具体实现看 QSController.py def answer_question(user_input): # 1. 从输入里抽实体比如商品名、品类名 entities extract_entities(user_input, dict_dirdict) # 2. 根据意图选查询模板 if 推荐 in user_input: return recommend_by_category(entities[product_id]) elif 搭配 in user_input: return recommend_pairing(entities[product_id]) else: return 暂时无法回答这个问题逻辑说明extract_entities用词典做匹配简单但有效适合毕设场景。意图识别用关键词规则推荐、搭配这类词直接触发对应逻辑。如果要做更复杂的意图分类可以换成sklearn或pytorch的小模型但那就超出这份源码的范围了。5. 避坑与排查跑不起来先看这几条5.1 报错 ModuleNotFoundError: No module named xxx现象运行demo.py直接报缺模块但不知道缺哪个版本。原因源码没带requirements.txt依赖全靠猜。解决先pip install报错里提到的模块名如果装完还报版本冲突用pip install xxx版本号降级。常见冲突是py2neo和neo4j驱动版本不匹配建议只装一个。5.2 连接 Neo4j 失败Connection refused现象Graph(bolt://localhost:7687)报连接拒绝。原因Neo4j 服务没启动或者端口不是 7687。解决先确认 Neo4j Desktop 或服务端已启动浏览器打开http://localhost:7474能进管理页。如果端口被改过去config.conf里同步改。密码错误也会报类似错误注意区分。5.3 CSV 读取乱码UnicodeDecodeError现象pd.read_csv(product.csv)报编码错误。原因CSV 可能是 GBK 或 GB2312 编码不是 UTF-8。解决先试encodinggbk再试encodinggb18030。如果还不行用chardet检测import chardet; print(chardet.detect(open(product.csv,rb).read()))。5.4 图谱查询返回空关系没写进去现象推荐查询返回空列表但商品节点明明存在。原因关系写入时merge的键和查询时用的键不一致或者关系类型名拼写不同。解决先在 Neo4j 浏览器里跑MATCH (p:Product)-[r]-(c) RETURN p, r, c LIMIT 25肉眼确认关系是否存在、类型名是什么。大小写敏感BELONGS_TO和belongs_to是两个东西。5.5 前端 view.html 打不开或空白现象View/view.html用浏览器打开是空白。原因它可能依赖后端接口直接双击打开没有数据。解决先启动server/dataserver.py确认后端端口再把view.html里的接口地址改成实际地址。如果只是静态展示检查浏览器控制台有没有 JS 报错。6. 进阶玩法把词典热插拔和多领域扩展用起来这份源码有个容易被忽略的设计dict目录下同时放了电商和医疗的词典文件。food.txt、producer.txt偏电商drug.txt、disease.txt、symptom.txt、deny.txt、check.txt、department.txt明显是医疗领域的。这意味着实体抽取层是词典驱动的换一套词典就能换一个领域。我一般会这样验证扩展性# 加载不同领域的词典测试实体识别是否切换 def load_dict(domainecommerce): dict_map { ecommerce: [food.txt, producer.txt], medical: [drug.txt, disease.txt, symptom.txt] } entities set() for fname in dict_map.get(domain, []): with open(fdict/{fname}, r, encodingutf-8) as f: for line in f: entities.add(line.strip()) return entities # 切换领域只需改一个参数 ecom_entities load_dict(ecommerce) med_entities load_dict(medical) print(len(ecom_entities), len(med_entities))逻辑说明dict_map把领域和词典文件解耦加新领域只需加一行映射。load_dict返回实体集合后续extract_entities直接用它做匹配。参数domain控制加载哪套词典默认电商。这个设计的好处是你可以在毕设答辩时演示「同一套代码换词典就能做医疗问答」扩展性直接拉满。另一个进阶点是推荐排序的权重调优。variable.ini里如果有price_weight、category_weight这类变量可以写个简单的网格搜索权重组合价格权重品类权重点击率模拟A0.30.70.12B0.50.50.15C0.70.30.11把variable.ini里的值改掉重启服务观察推荐结果变化。虽然源码没带 A/B 测试框架但手动跑几组对比答辩时能说出「我做了权重调优」比「我跑通了」更有说服力。提示改variable.ini后记得重启dataserver.py配置是启动时读的不重启不生效。血泪经验是我第一次跑这套源码时没看Config目录直接python demo.py结果连了默认数据库把本地测试数据全写进去了。从那以后我每次拿到新项目都强制先翻Config和README.md确认数据库地址和路径再动手。希望帮到你。本文还有配套的精品资源点击获取

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询