0 neo4j使用中遇到的小问题
今天在使用neo4j时遇到了一些问题,也发现前面学习笔记1中的一些没搞清楚的地方。
在删除已存在的数据库时,我根据视频讲解,直接删除了data下的database文件夹,然后再运行
neo4j console
时就一直报错,后来把整个neo4j文件夹重新解压缩,才解决。
研究了一下网上的相关资料,发现很多可能是针对的以前版本的neo4j,比如说网上的版本大多在neo4j.conf文件中使用的active_database,而我用的,比较新的版本(Neo4j Community Edition 4.3.3),默认使用的是default_database。
关于直接更换数据库的问题,现在我还没有找到一个好的办法。删除data下的database或者data/database下的我新建的数据库,都会导致报错或者连接不上数据库的问题。
目前我的做法是,备份一个database文件夹,之后如果需要空白的数据库的话,将已有的文件夹更名,直接使用备份的这个文件夹。
如果大家有关于这个问题的解决办法的话,也欢迎留言给我。
1 将csv文件数据导入neo4j中
1 获取数据
我将要使用的数据是豆瓣电影250。使用如下代码,爬取豆瓣250的数据
# encoding:UTF-8
import csv
import json
import requests
from lxml import etree
# from bs4 import BeautifulSoup
# import pandas as pd
import json
class DouBan:
def __init__(self):
self.temp_url = "https://movie.douban.com/top250?start={}&filter="
self.headers = {
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36"}
def get_url_list(self):
return [self.temp_url.format(i*25) for i in range(10)]
def parse_url(self, url):
response = requests.get(url, headers=self.headers)
return response.content.decode()
def get_content_list(self, html_str, content_list):
html = etree.HTML(html_str)
li_list = html.xpath("//*[@id='content']/div/div[1]/ol/li")
for li in li_list:
item = {}
item["rank"] = li.xpath("div/div[1]/em/text()")[0]
item["名字"] = li.xpath("div/div[2]/div[1]/a/span[1]/text()")[0]
item["评价人数"] = li.xpath("div/div[2]/div[2]/div/span[4]/text()")[0]
item_temp = li.xpath("div / div[2] / div[2] / p[1] / text()[2]")[0].strip()
item["类别"] = item_temp.replace("\xa0", "")
content_list.append(item)
return content_list
def save_content_list(self, content_list):
file_name = 'data.json'
with open(file_name, 'w',encoding='utf-8') as file_object:
json.dump(content_list, file_object, ensure_ascii=False,indent=4)
for content in content_list:
print(content)
def run(self):
# 1 获取URL列表
url_list = self.get_url_list()
# 2 遍历发送请求 获取响应
content_list = []
for url in url_list:
html_str = self.parse_url(url)
# 3 提取数据
content_list = self.get_content_list(html_str, content_list)
# 保存
self.save_content_list(content_list)
def trans(jsonpath, csvpath):
json_file = open(jsonpath, 'r', encoding='utf8')
csv_file = open(csvpath, 'w', newline='', encoding='gbk')
keys = []
writer = csv.writer(csv_file)
json_data = json_file.read()
dic_data = json.loads(json_data, encoding='utf8')
for dic in dic_data:
keys = dic.keys()
# 写入列名
writer.writerow(keys)
break
for dic in dic_data:
for key in keys:
if key not in dic:
dic[key] = ''
writer.writerow(dic.values())
json_file.close()
csv_file.close()
if __name__ == '__main__':
douban = DouBan()
douban.run()
trans('data.json', 'data.csv')
得到数据如图
2 数据导入
将这个得到的csv文件放到neo4j的import文件夹下,然后在neo4j服务器上输入以下代码:
LOAD CSV WITH HEADERS FROM "file:///data.csv" AS line
CREATE(:电影名字 {name:line.名字,class:line.类别})
CREATE(:电影排名 {name:line.rank})
CREATE(:人数 {name:line.评价人数})
这段代码创建了三个实体,分别是电影名字、电影排名、打分人数(当然在实际中我们也可以把电影排名和打分人数作为电影名字的属性),其中电影名字还要一个属性是他的类别。
这里我遇到了一个问题
之前的csv文件,保存时使用的是ANSI编码,这样会导致两种情况:
- 在读取“名字”时就出问题,这样的话运行出来的电影名字是1、2、3、4这样
- 在显示时出错,这样显示出来的电影名字全部都是乱码
解决方式是:用记事本打开csv文件,另存为时选择UTF-8格式编码
这里参考了这篇文章
添加图的边,将电影名字和电影排名连接起来。
LOAD CSV WITH HEADERS FROM "file:///data.csv" AS line
MATCH (entity1:电影名字{name:line.名字}) , (entity2:电影排名{name:line.rank})
CREATE(entity1)-[:rank{type:line.relation,name:'排名'}]->(entity2)
添加另一个边,将电影名字和电影评价人数连接起来。
LOAD CSV WITH HEADERS FROM "file:///data.csv" AS line
MATCH (entity1:电影名字{name:line.名字}),(entity2:人数{name:line.评价人数})
CREATE(entity1)-[:评价人数{type:line.relation}]->(entity2)
运行结果如图:
2 Protégé的使用
这里关于SPARQL和OWL的语句规则等,不做具体描述,讲一下如何使用Protégé来构建语义网。
1.1 安装Protégé
官方下载网址点击这里。
拖到最下面有个Download for Windows,需要注册,其实好像不注册,只要在那个页面停留一段时间就行。这里因为这个资源好像是挂在GitHub上的,因此下载非常慢,如果有需要的话可以点击这里。
下载完后直接解压缩,运行Protege.exe,运行界面如图,其中的Ontology是我们的前缀,点击Entities。
1.2 安装graphviz插件(可略过)
官方下载地址点击这里。
选择最新稳定版下载即可。
下载后点击Protege的File-Preferences-OWLViz,在Path to DOT处选择刚才安装后的dot.exe
这个插件可以防止OWLViz中的图都缩在左上角。
2.1 创建类
点击Class可以查看类,所有的类都在Thing这个类的子类,在Thing上点击右键创建类,这里我创建了Person和Place两个类。
2.2 创建等价类
再定义一个类Didian,作为Place的等价类。首先创建一个Didian类,点击这个类后,在右边点击Equivalent To,然后点击Class hierarchy(Class hierarchy的位置可能不同),选中我们想要让他等价的类,然后点击确定。
2.3 创建类的子类
定义一个类Player,点击SubClass of,点击Class hierarchy,然后点击Person,最后确定。
也可以直接在左边的Person节点点击右键创建Person的子类。
3.1 创建对象属性
点击Object properties可以查看属性。所有的属性都是topObjectProperty的子属性,在topObjectProperty上点击右键创建属性输入属性名后点击continue,然后点击finish。这里我创建了一个属性。
点击相应的属性,然后点击3左边的这个符号,可以删除创建过的属性,类的删除方式也是类似的。
3.2 给属性添加Domains和Ranges
对于一个三元组,A出生于B,属性“出生于”的Domain就是A的类,Ranges就是B的类型以及相关限定条件。这点类似于函数f(x)的域和范围。
选择相应属性,点击Domains,点击Class hierarchy,即可选择属性对应的类。
选择下方的Ranges,点击Object restrinction creator,可选择属性的类型等。
这里需要注意,在选择对象属性的ranges时,一定要选择Object restrinction creator,不能选择Data restrinction creator,否则后续运行会报错。
运行后点击右下角的红色三角图标,可以看到运行时的错误,错误大概是:
An error occurred during reasoning: Error: In OWL 2 DL, owl:topDataProperty is only allowed to occur in the super property position…
4 创建数据属性
点击data properties可以查看数据属性。
创建数据属性的步骤与对象属性基本相同。
5.1 创建实体
点击individuals,点击2这里这个带+的图标,创建实体,我这里创建了张三和北京两个实体,一个是人一个是地点。
创建好了以后点击相应实体,在右侧我们可以看到Types这里我们可以添加这个实体的类,Same Individual As可以添加与他等价的实体,Different Individuals可以添加与他不同的实体。
5.2 为实体添加属性
点击Object property assertions为实体添加对象属性,点击Data property assertions为实体添加数据属性。
这里说一下对象属性和数据属性的区别:
对象属性必须是有实体的,而数据属性不需要。
比如说上面的例子,如果我们输入“出生于 上海”的话,则会报错,因为没有上海这个实体:
前面的对象属性名称如果不在我们添加的对象属性名称中的话也会报错:
6 运行
- 点击Reasoner-Configure,将所有未勾选项全部勾选上
- 检查下面的选项是否在HermiT上
3.点击Start reasoner,如果有错误的话会有一个弹窗,点击Explain。
可以看到这是我的报错,报错后点击确定,有问题的地方系统会标红。
点击Stop Reasoner,修改好后再运行。
点击Windows-Tabs,将OWLViz和OntoGraf勾选上
点击OntoGraf和OWLViz就可以看到我们刚刚做的图了。
我这里只是做了一些简单的操作,详细教程可以点击这里。