多读书多实践,勤思考善领悟

从零开始学习知识图谱 之 八.百科知识图谱构建 2.数据清洗及存入图数据库Neo4j

本文于1727天之前发表,文中内容可能已经过时。

一. 简介

前面我们爬取了百度百科的数据,获取400W的数据大概需要10天左右。接下来我们需要把它存到图数据库里来,这里我还是使用neo4j,没选Jena的原因是我个人认为在没有本体模型的情况下,在neo4j上好好的建立上下位关系也许更好。 现有百度百科部分,包含词条4,190,390条,存入 neo4j 后得到节点 10,416,647个,关系 37,317,167 条,属性 45,049,533个。下面我们对其进行介绍。

本教程的项目代码放在github上,下载地址为《从零开始学习知识图谱》项目源代码

二. 环境准备

1. 操作系统

支持操作系统:windows、macOS、Linux。为了方便大家搭建开发环境,笔者尽可能在windows下构建,系列篇未特意说明时操作系统都是windows。Linux安装可以参考VirtualBox虚拟机安装UbuntuVirtualBox虚拟机安装CentOS8进行安装。

2. jdk

安装参见windows系统安装JDK

3. Python3

安装参见从零开始学习知识图谱 之 一

4. 安装Neo4j

参见从零开始学习知识图谱 之 六 -安装Neo4j

三. MYSQL 数据的导出

从MYSQL中,导出所需数据,包含:

  • 节点
    • title: 包含 title,即词条的标题,如上海
    • disambi: 包含 disambi(消除歧义的名称,如 上海 (中华人民共和国直辖市)), title(上面的标题), abstract(词条摘要), curLink(当前词条的网址), exterLink(该词条的引用外部链接)
    • redirect: 包含 redirect,即同义词,如 沪 和上海 (中华人民共和国直辖市)是同一个意思
    • subject: 包含 disambi, subject(词条的分类, 如 地理,地点 等)
  • 关系
    • title_disambi: 词条标题和消岐名称间的关系
    • disambi_redirect: 消岐名称和同义词间的关系
    • disambi_subject: 消岐名称和词条分类间的关系 如 “内森·科德里”,”娱乐人物,人物”
    • disambi_infobox: 消岐名称的对应属性,如 出生地、国籍等

建议使用MySQL Workbench执行下面脚本,

mysql 中导出表的代码为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
                                                                    
SELECT distinct title from lemmas into outfile 'C:/ProgramData/MySQL/MySQL Server 8.0/Uploads/410_title.csv' fields terminated by ',' optionally enclosed by '"' lines terminated by '\r\n';

SELECT disambi, title, abstract, curLink, exterLink from lemmas into outfile 'C:/ProgramData/MySQL/MySQL Server 8.0/Uploads/410_disambi.csv' fields terminated by ',' optionally enclosed by '"' lines terminated by '\r\n';

SELECT distinct redirect from lemmas into outfile 'C:/ProgramData/MySQL/MySQL Server 8.0/Uploads/410_redirect.csv' fields terminated by ',' optionally enclosed by '"' lines terminated by '\r\n';

SELECT disambi, subject from lemmas where subject != '' into outfile 'C:/ProgramData/MySQL/MySQL Server 8.0/Uploads/410_disambi_subject.csv' fields terminated by ',' optionally enclosed by '"' lines terminated by '\r\n';

SELECT title, disambi from lemmas into outfile 'C:/ProgramData/MySQL/MySQL Server 8.0/Uploads/410_title_disambi.csv' fields terminated by ',' optionally enclosed by '"' lines terminated by '\r\n';

SELECT disambi, redirect from lemmas where redirect !='' into outfile 'C:/ProgramData/MySQL/MySQL Server 8.0/Uploads/410_disambi_redirect.csv' fields terminated by ',' optionally enclosed by '"' lines terminated by '\r\n';

SELECT disambi, infobox from lemmas where infobox!='' into outfile 'C:/ProgramData/MySQL/MySQL Server 8.0/Uploads/410_disambi_infobox.csv' fields terminated by ',' optionally enclosed by '"' lines terminated by '\r\n';

而后我们将导出的csv文件转移到<NEO4J_HOME>\import文件夹内:

文件移动Dos命令:

1
2
3
4
5
6
7
8
9
C:\Users\mmm>move C:\"ProgramData\MySQL\MySQL Server 8.0\Uploads\*.csv" C:\my\neo4j\import\
C:\ProgramData\MySQL\MySQL Server 8.0\Uploads\410_disambi.csv
C:\ProgramData\MySQL\MySQL Server 8.0\Uploads\410_disambi_infobox.csv
C:\ProgramData\MySQL\MySQL Server 8.0\Uploads\410_disambi_redirect.csv
C:\ProgramData\MySQL\MySQL Server 8.0\Uploads\410_disambi_subject.csv
C:\ProgramData\MySQL\MySQL Server 8.0\Uploads\410_redirect.csv
C:\ProgramData\MySQL\MySQL Server 8.0\Uploads\410_title.csv
C:\ProgramData\MySQL\MySQL Server 8.0\Uploads\410_title_disambi.csv
移动了 7 个文件。

四. 清洗数据

接下来需要对上面的这些文件做数据清洗,重点清洗对象为:title、disambi、infobox、subject这种。这里需要注意的是像disambi这种在不同文件中都出现的东西,一定要使用统一的标准去清洗它们,防止对不上导致错误。这里我建立了一个单独的python文件来统一定义清洗它们的方式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import re        
import commands

class Clean(object):
@staticmethod
def clean_word(word, clean_level='others'):
""" Remove symbols in words :word word with unicode :clean_level keep different symbols for disambi/title :return clean word """
word = word.strip()

if clean_level == "title":
word = word.strip().strip("\"").replace("\n", " ").replace("\"","").strip(u"\\") elif clean_level == "subject":
word = word.replace("\"", "").strip("\\").strip()
elif clean_level == "redirect":
word = word.strip("\"")
elif clean_level == "disambi":
word = re.sub(u"[,。、&∈*.↑【2—‘:“#> BFR·Z<bf≈j×~①Ⅲ⑤⑨÷〔!%》-』1→5=AE∧I/″▲; ]ξaeφi}④⑧…─☆《『0В<D∪L±γ′TXλ: dh|③⑦~、℃'〉+」/】3〕Δ’;”?■CGΨ[=μ_cgβ㈧o{②⑥'⑩。\~\!\@\#\$\%\^\&\*\(\)\_\-\+\=\{\}\[\]\\\|\:\;\'\"\.\>\?\/\, \xa0\u00a0\u3000\r\n]", "", word)
elif clean_level == 'others':
word = re.sub(u"[,。、&∈*.↑【2—‘:“#> BFR·Z<bf≈j×~①Ⅲ⑤⑨÷〔!%)》-』1→5=AE∧I/″▲; ]ξaeφi}④⑧…─☆(《『0В<D∪L±γ′TXλ: dh|③⑦~、℃'〉+」/】3〕Δ’;”?■CGΨ[=μ_cgβ㈧o{②⑥'⑩。\~\!\@\#\$\%\^\&\*\(\)\_\-\+\=\{\}\[\]\\\|\:\;\'\"\.\>\?\/\,\xa0\u00a0\u3000\r\n]", "", word)
return word

接下来:

  • 运行 gen_disambi_infobox.py 得到 410_title_new.csv 的title 节点文件、410_disambi_infobox_out.csv 的 disambi_inbox 关系文件还有出现频次大于10的属性 all_attr.txt 文件。

  • 运行 remove_disambi.py 得到 410_disambi_new.csv 节点文件

  • 运行 get_subject.py 得到 disambi_subject.csv 关系文件和all_subject.csv 的全部subject文件。

  • 运行 cleanFile.py 得到 410_title_disambi 的关系文件 和 410_disambi_redirect的关系文件。

以上程序放在ie/struct_to_rdf/baidu2neo4j 目录下,使用的话需要根据实际文件的存放路径进行更改。需要注意的是上面几个程序的重合度很高,在完成互动百科爬虫后,我将重写它们的结构。

五. 将数据导入 neo4j

由于数据量较大,我们需要采用neo4j-import 工具进行数据导入,运行下面的命令将数据导入 neo4j。

*_header.csv头文件定义放在ie/struct_to_rdf/baidu2neo4j/header_file文件夹内。

需要注意的是下面所有的csv文件需要在当前目录下,或者使用路径指向它们,而后..\bin\neo4j-import、..\data\databases\的路径也根据你所处的路径而变化。同时保证..\data\databases\graph.db不存在,否则改名。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
C:\my\neo4j\import>..\bin\neo4j-import --multiline-fields=true --bad-tolerance=1000000 --into ..\data\databases\graph.db --id-type string --nodes:Title title_header.csv,410_title_new.csv --nodes:Disambi disambi_headers.csv,410_disambi_new.csv --nodes:Redirect redirect_header.csv,410_redirect.csv --nodes:Subject subject_header.csv,all_subject.csv --relationships:DisambiName title_disambi_header.csv,410_title_disambi_out.csv --relationships:RedirectName disambi_redirect_header.csv,410_disambi_redirect_out.csv --relationships:DisambiSubject disambi_subject_header.csv,disambi_subject.csv --relationships:Role disambi_infobox_header.csv,410_disambi_infobox_out.csv;
WARNING: neo4j-import is deprecated and support for it will be removed in a future
version of Neo4j; please use neo4j-admin import instead.
Neo4j version: 3.5.11
Importing the contents of these files into C:\my\neo4j\data\databases\graph.db:
Nodes:
:Title
C:\my\neo4j\import\title_header.csv
C:\my\neo4j\import\410_title_new.csv

:Disambi
C:\my\neo4j\import\disambi_headers.csv
C:\my\neo4j\import\410_disambi_new.csv

:Redirect
C:\my\neo4j\import\redirect_header.csv
C:\my\neo4j\import\410_redirect.csv

:Subject
C:\my\neo4j\import\subject_header.csv
C:\my\neo4j\import\all_subject.csv
Relationships:
:DisambiName
C:\my\neo4j\import\title_disambi_header.csv
C:\my\neo4j\import\410_title_disambi_out.csv

:RedirectName
C:\my\neo4j\import\disambi_redirect_header.csv
C:\my\neo4j\import\410_disambi_redirect_out.csv

:DisambiSubject
C:\my\neo4j\import\disambi_subject_header.csv
C:\my\neo4j\import\disambi_subject.csv

:Role
C:\my\neo4j\import\disambi_infobox_header.csv

Available resources:
Total machine memory: 15.85 GB
Free machine memory: 9.93 GB
Max heap memory : 3.52 GB
Processors: 8
Configured max memory: 11.09 GB
High-IO: false

Import starting 2019-10-29 17:05:36.714+0800

······

Imported:
10,416,647 nodes
37,317,167 relationships
45,049,533 properties
Peak memory usage: 1.03 GB
There were bad entries which were skipped and logged into C:\my\neo4j\import\..\data\databases\graph.db\bad.log

其中我们定义了如下节点:

  • Title: 只包含title名称
  • Disambi:包含 disambi、title、abstract、curLink、exterLink五项内容。
  • Redirect:只包含redirect名称
  • Subject: 只包含subject

除此之外还定义如下关系:

  • DisambiName:表示 title到disambi间的关系
  • RedirectName: 表示disambi 到 redirect间的关系
  • DisambiSubject:表示 disambi 到 subject间的关系
  • Role:表示disambi 到infobox里各个属性和属性值间的关系

除此之外,使用 neo4j-import 最好使用像 disambi_infobox_header.csv 这种的header文件,里面包含

1
:START_ID(Disambi),role,:END_ID(Title)

其中START_ID表示关系的开始节点,END_ID表示关系的结束节点。中间的role表示关系的属性。需要注意的是上面这一行里面千万不能有空格,否则就会出现”role”这种情况。头文件定义放在ie/struct_to_rdf/baidu2neo4j/header_file文件夹内,大家可以参考使用。

六. 参考

Use the Import tool:https://neo4j.com/docs/operations-manual/current/tutorial/import-tool/