手把手教你搭建一个中式菜谱知识图谱可视化系统

  • 中式菜谱知识图谱
    • 1、系统功能
    • 2、先来看看效果
      • 实体间关联关系及实体信息显示
      • 不同类型实体开关显示
      • 搜索功能展示
    • 3、系统实现流程
      • 3.1 数据爬取
      • 3.2 D3可视化

中式菜谱知识图谱

今天分享一个自己从数据爬取到d3可视化的中式菜谱知识图谱可视化系统的搭建流程。
Github项目地址:https://github.com/ngl567/CookBook-KG
访问可视化系统GithubPage地址:https://ngl567.github.io/CookBook-KG/

1、系统功能

本项目开发的系统名称为AI Food Time,中文名为爱食光。通过收集网上完全公开的有关中式菜谱的数据,经过数据清洗和分析,转换为知识图谱的存储结构,并提供可视化展示和模糊搜索等功能,为热爱美食与烹饪的人们提供方便快捷的中式菜谱服务,并以知识图谱的形式直观显示出不同菜品的关系及所用原料,在生活中具有很大的实际应用需求,包括:

  • 一类菜品的不同具体做法,例如水煮鱼包括麻辣水煮鱼、小清新版水煮鱼和家常版水煮鱼等;
  • 通过菜品与食材的关联关系,可以查询家中现有食材可以烹饪哪些菜品;
  • 可以直接显示出每种菜品所需主料,辅料,配料及其具体数量和烹饪方法,与网上的一些菜谱网页相比更加简单直观;
  • 可视化能够对各种菜品及关联关系有一个全局的认识,并能够显示每种菜品对应的图片;
  • 搜索菜谱关键词,显示出和关键词相关的各类菜品信息。

2、先来看看效果

实体间关联关系及实体信息显示

不同类型实体开关显示

搜索功能展示


怎么样,是不是觉得还有那么点意思。在可视化系统中,同一类实体用相同颜色的节点表示,鼠标位于某个节点上方时显示其相关联的其它实体和之间的关系名称;具有同一类实体显示开关节点显示模式转换,并支持搜索功能;同时,我们对每种菜品的信息栏中显示菜品对应的成品图片,并进行了实体对齐,消除了食品原料中比如“蒜”和“大蒜”这类的冗余信息。

这里展示的是mini版系统,包含10大类,50种菜品之间的关联关系,包括菜品制作的各种食材制作步骤,建议用电脑浏览器打开,如需体验可直接进入Github Page(如果打开没有可视化显示,请尝试多刷新几次)访问入口

3、系统实现流程

3.1 数据爬取

所有菜谱的数据都是从完全公开的网页上爬取的,这些网页上的数据是以半结构化知识呈现的,如图所示:

使用XPath可以很轻松地从网页上将这些半结构化知识爬取出来,先以树形结构存储菜谱及属性数据:

                       菜品大类|_具体的精品特色菜|_主料|_辅料|_配料|_制作步骤

接着,对于树形结构存储的数据,以三元组的格式:菜品大类-属于-具体的精品特色菜,精品特色菜-主料-主料名,精品特色菜-配料-配料名,精品特色菜-辅料-辅料名,精品特色菜-制作步骤-制作步骤列表表示所有数据。用于可视化的数据分为三元组组成的关系图结构数据vizdata.json和实体属性组成的数据entities_items.json。

三元组组成的关系图结构数据vizdata.json存储的是字典数据,“links”键对应的是所有头实体-关系-尾实体组成的三元组,“nodes”设定了节点的类型、名称和大小等属性。

    "links": [                                                                           {"relation": "选材","source": "山楂红烧肉","target": "五花肉","value": 3},{"relation": "选材","source": "山楂红烧肉","target": "山楂","value": 3},...]"nodes": [{"class": "菜品大类","group": "0","id": "红烧肉","size": "16"},{"class": "精品特色菜","group": "1","id": "家庭版水煮活鱼","size": "10"},...]

实体属性组成的entities_items.json文件存储所有实体属性的字典数据,是以”菜品“为一级索引,对应的主料、辅料、配料和制作步骤分别为二级索引,以及属性值组成的列表,如下所示:

"桂香红烧肉": {    "主料": [
"五花肉: 两条"
],
"辅料": [
"葱: 一根",
"姜: 两片",
"桂皮: 一块",
"香叶: 两片"
],
"配料": [
"老抽: 一汤匙",
"生抽: 两汤匙",
"冰糖: 适量",
"料酒: 两汤匙"
],
"特色": [
"口味: 咸甜",
"工艺: 烧",
"耗时: 一小时",
"难度: 简单"
],
"制作步骤": [
"1: 五花肉放入沸水中,煮至断生,洗净",
"2: 准备材料",
"3: 五花肉切块",
"4: 取砂锅,热锅冷油,加入葱姜,桂皮,香叶爆香。放入五花肉,加高汤。",
"5: 加入冰糖,料酒,生抽和老抽,加盖小火煮一个小时,开盖收汁。"
]
},...

3.2 D3可视化

D3是基于数据的文档操作javascript库,D3能够把数据和HTML、SVG、CSS结合起来,创造出可交互的数据图表。我分别用D3知识图谱力导向图和Neo4j分别构建了知识图谱可视化系统,D3在可视化方面具有更好的展示和灵活性,因此选用D3进行知识图谱的可视化。

对于上面得到的关系图数据vizdata.json和实体属性数据entities_itmes.json两个文件可以存储在自己的github项目中,因为D3可视化只支持从web服务读取json数据。由于字数限制,本文给出D3可视化的几个主要模块。

首先,需要设定可视化的样式,具体可以看github中的代码。然后,需要从json文件中读取关系图数据:

var graph;
d3.json("https://raw.githubusercontent.com/ngl567/CookBook-KG/master/visualization
/vizdata_mimini_aglin.json", function(error, data)

用vizdata.json中的links数据去驱动两个节点之间的边的线宽:

//边上的文字(实体之间的关系)
var linktext = svg.append('g')
.attr("class", "linetexts")
.selectAll("text")
.data(graph.links)
.enter()
.append("text")
.style("display","block")
.style("color","red")
.text(function(d){
return d.relation;
});

用vizdata.json中的links数据去驱动两个节点之间的边的线宽:

//边上的文字(实体之间的关系)
var linktext = svg.append('g')
.attr("class", "linetexts")
.selectAll("text")
.data(graph.links)
.enter()
.append("text")
.style("display","block")
.style("color","red")
.text(function(d){
return d.relation;
});

添加所有的节点,并对每个节点按照不同的类型设置节点颜色:

// 添加所有的node
var node = svg.append('g')
.attr('class', 'nodes')
.selectAll('circle')
.data(graph.nodes)
.enter().append('circle')
.attr("r", function(d) {
return d.size
})
.attr('fill', function(d){ // 填充的颜色
return colors[d.group];
})
.attr('stroke', 'none')    // 没有描边
.attr('name', function(d){
return d.id;
})
.call(d3.drag()             // 绑定d3的拖动函数
.on("start", dragstarted) // 拖动开始
.on("drag", dragged)      // 拖动进行
.on("end", dragended));   // 拖动结束

通过点击圆点和文字两种方式表示节点切换不同的模式:

// 处理模式点击后的事件(这些元素页面上本来有)
$('#mode span').click(function(event) {
// 把mode里面所有span的active全部去掉
// 把被点击的这个设置为active
$('#mode span').removeClass('active')
$(this).addClass('active')
if ($(this).text() == 'Circles') {
// 隐藏所有文本里面的svg元素
// 把node里面的显示出来
$('.texts text').hide();
$('.nodes circle').show();
}
else {
$('.texts text').show();
$('.nodes circle').hide ();
}
});

不同类型的实体有一个开关,决定一类实体节点是否显示:

// 处理开关1点击后的事件(这些元素页面上本来有)
$('#switch1 span').click(function(event) {
// 把mode里面所有span的active全部去掉
// 把被点击的这个设置为active
$('#switch1 span').removeClass('active')
$(this).addClass('active')
if ($(this).text() == 'On') {
sw1 = true;
d3.select('#svg1 .nodes').selectAll('circle').attr('class', function(d){
// 当前选中类型实体显示
if (d.group == 0 && sw1 == true) {
return '';
}
else if (d.group == 1 && sw2 == true){
return '';
}
else if (d.group == 2 && sw3 == true){
return '';
}
else{
return 'inactive'
}
});

当鼠标悬浮在某个实体节点上方时,实体的属性信息都能够显示出来,如果是精品特色菜类的实体,菜品图片等信息都能显示:

// 增加各个菜品的图片
if (typeof(info[name]) != "undefined") {
//avatar_ID = info[name]['ID'][0]
//if(outlier_avatar_ID.indexOf(avatar_ID) != -1) {
//    avatar_ID = avatar_ID + '0'
//}
if ('主料' in info[name]){
$('#info').append('<p>' + '<img src="https://raw.githubusercontent.com/ngl567/CookBook-KG
/master/visualization/recipe_photo/' + name + '.jpg" />' + '</p>');
}
}
for (var key in info[name]) {
value = info[name][key];
var flag_none = false;
for (var item in value) {
if (value[item] == null || value[item] == 'N/A' || value[item] == '') {
flag_none = true;
break;
}
}
if (flag_none == true) {              // 排除为空的属性值
continue;
}    $('#info').append('<p><span>' + key + '</span></p>');
var item_info = '';
count = 0
for (var food_item in info[name][key]){
if (count == 0){
item_info = item_info + info[name][key][food_item];
}
else{
item_info = item_info + "&nbsp;||&nbsp;" + info[name][key][food_item];
}
count = count + 1;
}
$('#info').append('<p>' + item_info + '</p>');
}

设置搜索功能,按照搜索框中的关键词显示所有匹配到关键词的所有节点:

// 搜索框
$('#search input').keyup(function(event) {
// 如果输入为空,全部显示出来
if ($(this).val() == '') {
d3.select('#svg1 .texts').selectAll('text').attr('class', '');;
d3.select('#svg1 .nodes').selectAll('circle').attr('class', '');;
d3.select('#svg1 .links').selectAll('line').attr('class', '');;
d3.select("#svg1 .linetexts").selectAll('text').attr('fill-opacity', 0);
}
else { // 筛选,判断这三个东西里的元素是否包含输入的东西
var name = $(this).val();
d3.select('#svg1 .nodes').selectAll('circle').attr('class', function(d) {
if (d.id.toLowerCase().indexOf(name.toLowerCase()) >= 0) {
return '';
} else {
return 'inactive';
}
});
d3.select('#svg1 .texts').selectAll('text').attr('class', function(d) {
if (d.id.toLowerCase().indexOf(name.toLowerCase()) >= 0) {
return '';
} else {
return 'inactive';
}
});
d3.select("#svg1 .links").selectAll('line').attr('class', function(d) {
return 'inactive';
});
d3.select("#svg1 .linetexts").selectAll('text').attr('fill-opacity', 0);
}
});

具体一些比如页面设计的代码具体可以看github中的代码,如果有任何问题也可以与我交流讨论,希望这个工作可能帮助大家一起来做点有意思的小项目。

同时,如果对我们的文章感兴趣,欢迎关注知乎专栏“人工智能遇上知识图谱“,也欢迎关注”人工智能遇上知识图谱“微信公众号,我们会力求为您呈上知识图谱领域的精彩内容,让我们一起学习并交流讨论人工智能与知识图谱技术。

手把手教你搭建一个中式菜谱知识图谱可视化系统相关推荐

  1. 手把手教你搭建一个基于Java的分布式爬虫系统

    http://blog.51cto.com/xpleaf/2093952 1 概述 在不用爬虫框架的情况,经过多方学习,尝试实现了一个分布式爬虫系统,并且可以将数据保存到不同地方,类似MySQL.HB ...

  2. 手把手教你搭建一个属于自己的Ghost博客

    介绍 Ghost 是基于 Node.js 的开源博客平台,由前 WordPress UI 部门主管 John O'Nolan 和 WordPress 高级工程师(女) Hannah Wolfe 创立, ...

  3. 手把手教你:基于Django的用户画像可视化系统

    系列文章 第九章.手把手教你:个人信贷违约预测模型 第八章.手把手教你:基于LSTM的股票预测系统 第七章.手把手教你:基于深度残差网络(ResNet)的水果分类识别系统 目录 系列文章 一.项目简介 ...

  4. 手把手教你搭建一个【文件共享平台】系列教程第一话——你想知道的,这里都有

    文章目录 Beginning what why how Effect Picture Source Code Ending Beginning 写在最前头(多图慎入).这篇系列教程将手把手(很详细)地 ...

  5. 手把手教你搭建一个学习Python好看的 Jupyter 环境

    又到摆脱重复工作,换个心情,然而并没有软用的时间了.这次,教大家如何搭建一个好看的jupyter环境. 安装Jupyter 先来展示一下我的环境 python: 3.5.* macos: 10.12. ...

  6. axios下载图片 node_vue+node.js手把手教你搭建一个直播平台(二)

    上一期,帅气的小羽给老铁们介绍了直播平台的项目的后端搭建,这期就让小羽带大家来搭建一下前端的框架. 1.创建前端工程 毫无疑问,搭建一个项目的框架,那第一步肯定是得创建一个工程啦.cmd命令,输入vu ...

  7. vue+node.js手把手教你搭建一个直播平台(二)

    上一期,帅气的小羽给老铁们介绍了直播平台的项目的后端搭建,这期就让小羽带大家来搭建一下前端的框架. 1.创建前端工程 毫无疑问,搭建一个项目的框架,那第一步肯定是得创建一个工程啦.cmd命令,输入vu ...

  8. 手把手教你搭建一个Minecraft 服务器

    这次,我们教大家如何搭建一个我的世界服务器 首先,我们来到这个网站 MCVersions.net - Minecraft Versions Download ListMCVersions.net of ...

  9. 【新手建站教学】如何使用成本更低的虚拟主机实现快速建站?手把手教你搭建一个属于自己的网站。

    本篇文章教大家如何使用成本更低的虚拟主机去搭建一个网站. 虚拟主机价格远低于服务器,所以选择虚拟主机建站是个非常不错的选择. 虚拟主机就是一台服务器分出来的小空间,一台虚拟机只能建一个网站,一台服务器 ...

最新文章

  1. 风格化图像_【技术综述】人脸风格化核心技术与数据集总结
  2. iBatis resultMap出错 The error happened while setting a property on the result object 解决办法
  3. 7-6 列出连通集 (25 分)(C语言实现)
  4. 葡萄酒质量和时间的关系
  5. 华为S5300系列交换机V100R005SPH020升级补丁
  6. C++ 无限for循环的bug
  7. SLAM中直接法分类及对应的项目
  8. dede在发布文章时自动加上关键词链接
  9. 《c语言南开100题》,二级C语言南开100题 免费
  10. 怎么添加网络扫描仪到计算机,MAC如何添加网络扫描仪
  11. 食品级L-天门冬氨酸市场现状及未来发展趋势
  12. 深入理解color model(颜色模型)
  13. 作业帮面经(已拿offer)
  14. 给我一首歌的时间D调吉他谱 - 周杰伦
  15. 渲染引擎入门到精通一_导入模型的实现和解决fbxsdk的使用坑
  16. 大数据分析:新浪微博兴趣圈自动挖掘
  17. 阿里云盘获取Refresh Token的方法
  18. xp系统打开itunes显示服务器失败,win7系统打开iTunes显示Apple Mobile Device Service无法启动怎么解决...
  19. 了解学习 Elasticsearch 及其与 Python 实现全文搜索
  20. 浅谈IP地址和网络安全

热门文章

  1. python三角函数作业思路
  2. linux查看某一个进程的socket连接数
  3. 我待JAVA如初恋,JAVA虐我千百遍,如何彻底卸载JAVA
  4. gojs DiagramEvent 图表事件中文文档
  5. ArcGIS GA、RA环境搭建
  6. RA8875 触屏控制
  7. 获取中国省、市、区数据(调用高德API)
  8. python-区间划分,统计年龄段性别占比
  9. My SQL数据库基础知识点全面总结笔记(下)
  10. 数位云开发者平台:室内定位api接入文档