零基础搭建基于知识图谱的电影问答系统

  • 一、项目准备
  • 二、项目数据
  • 三、训练问题分类器
  • 四、准备问答模板
  • 五、搭建webapp
  • 六、问题预处理

一、项目准备

  1. 首先需要一款python编译器,本人选用的是PyCharm,搭建好Python环境;
  2. 安装第三方依赖库,源码文件夹中的requirements.txt文件中说明了需要用到的第三方库和对应版本;
  3. 本项目采用图数据库进行存储,利用Neo4j图像数据库,可以参照本人博客:全网最详细的Neo4j安装教程进行安装。

那么至此,Python环境和知识图谱的存储环境已经搭建完成,接下来需要获取数据。

二、项目数据

数据采用的是IMDB互联网电影资料库中的数据,IMDB是一个关于电影演员、电影、电视节目、电视明星和电影制作的在线数据库,包括了影片的众多信息、演员、片长、内容介绍、分级、评论等。对于电影的评分使用最多的就是IMDb评分。
利用爬虫获取数据如下:

其中movie、person、genre为数据表,movie_to_genre、person_to_movie两张关系表建立起电影与类型、电影与角色之间的关系。表中相关字段如下:
1.movie.csv(mid:电影序号;title:电影标题;introduction:电影简介;rating:电影评分;releasedate:发布日期)

2.person.csv(pid:演员序号;birth:出生日期;death:离世日期;name:演员姓名;biography:生平简介;birthplace:出生地)

3.person_to_movie.csv(pid:演员序号;mid:电影序号)
4.genre.csv(gid:类型序号;gname:类型名称)

5.movie_to_genre.csv(mid:电影序号;gid:角色序号)

数据获取完成后,将其导入Neo4j图形数据库中。
1.首先将五张数据表放入Neo4j安装目录中的import文件夹下

2.打开Neo4j,依次执行以下代码
建立连接,此时经常会连接不上,原因是7474端口被占用,查看被占用端口:netstat -ano |findstr 7474

关闭端口:taskkill /t /f /pid 9244

(1)导入电影类型genre.csv

//导入节点 电影类型  == 注意类型转换
LOAD CSV WITH HEADERS  FROM "file:///genre.csv" AS line
MERGE (p:Genre{gid:toInteger(line.gid),name:line.gname})



(2)导入演员数据person.csv

//导入节点 演员信息
LOAD CSV WITH HEADERS FROM 'file:///person.csv' AS line
CREATE (p:Person { pid:toInteger(line.pid),birth:line.birth,
death:line.death,name:line.name,
biography:line.biography,
birthplace:line.birthplace})



(3)导入电影数据movie.csv

// 导入节点 电影信息
LOAD CSV WITH HEADERS  FROM "file:///movie.csv" AS line
MERGE (p:Movie{mid:toInteger(line.mid),title:line.title,introduction:line.introduction,
rating:toFloat(line.rating),releasedate:line.releasedate})



(4)创建电影与演员之间的关系person_to_movie.csv

// 创建电影与演员之间的关系 actedin  电影是谁参演的 1对多
LOAD CSV WITH HEADERS FROM "file:///person_to_movie.csv" AS line
match (from:Person{pid:toInteger(line.pid)}),(to:Movie{mid:toInteger(line.mid)})
merge (from)-[r:actedin{pid:toInteger(line.pid),mid:toInteger(line.mid)}]->(to)


(5)创建电影与类型之间的关系movie_to_genre.csv

//导入关系  电影是什么类型 == 1对多
LOAD CSV WITH HEADERS FROM "file:///movie_to_genre.csv" AS line
match (from:Movie{mid:toInteger(line.mid)}),(to:Genre{gid:toInteger(line.gid)})
merge (from)-[r:is{mid:toInteger(line.mid),gid:toInteger(line.gid)}]->(to)



至此,知识图谱的数据存储已经建立完毕!

三、训练问题分类器

针对用户提出的不同问题,需要给与对应的答案,因此需要对问题进行分类。如何识别用户的问题属于那一类,因此需要选择分类器,训练分类器的数据可以从github中下载:https://gitcode.net/mirrors/irvingbei/simple_movie_qa_with_kg?utm_source=csdn_github_accelerator

四、准备问答模板


五、搭建webapp

基于下图目录结构,将文件资源导入即可

六、问题预处理

输入框接收到用户提出的问题后,首先需要获取问题中的询问对象是什么,即主语,是人还是电影,这就涉及到自然语言处理中的命名实体识别;接着还需要从问题中了解到用户的意图,这就涉及到文本表示问题,最基本的文本表示方法是one-hot形式,在项目中使用的是sklearn中的TF-IDF工具。

1.关键信息抽取

通过命名实体识别来获取用户问题中的人名,电影名等信息,在本项目中,通过词性标注工具可以把人名标注出来,通过自定义字典,把所涉及到的所有电影,所有人名和所有电影类型名称都加到了这个字典中,jieba分词的时候就会参考字典里面的词来进行分词和词性标注了,自定义词典的格式如下:

# 电影名称 nm
Forrest Gump 15 nm
Kill Bill: Vol. 1 15 nm
英雄 15 nm
......
# 演员名称 nr
张学友 15 nr
刘德华 15 nr
林雪 15 nr
......
# 电影类型 ng
冒险 15 ng
奇幻 15 ng
动画 15 ng
......

分词与词性标注同步进行,代码实现如下:

        def question_posseg(self):# 加载自定义词库jieba.load_userdict("./data/userdict3.txt")# 去除问题中的特殊符号clean_question = re.sub("[\s+\.\!\/_,$%^*(+\"\')]+|[+——()?【】“”!,。?、~@#¥%……&*()]+","",self.raw_question)self.clean_question=clean_question# 调用jieba 进行分词# 例如 clean_question = '章子怡的生日'question_seged=jieba.posseg.cut(str(clean_question))result=[]question_word, question_flag = [], []for w in question_seged:# '章子怡/nr' 每一个word后拼接 / 词性temp_word=f"{w.word}/{w.flag}"result.append(temp_word)# 预处理问题word, flag = w.word,w.flagprint('word:', word)print('flag:' ,flag)question_word.append(str(word).strip())print('question_word:', question_word)question_flag.append(str(flag).strip())print('question_flag:', question_flag)# 最终得到 question_word: ['章子怡', '的', '生日'] 对应 question_flag: ['nr', 'uj', 't']assert len(question_flag) == len(question_word) # 两个列表长度相等self.question_word = question_wordself.question_flag = question_flagprint(result) # ['章子怡/nr', '的/uj', '生日/t']return result

2.问题分类和模板填充

接下来需要对用户的问题进行分类,获取对应问题模板,从而明白用户的意图,首先要根据用户习惯构造的各种各样的问题来训练一个分类器,该项目使用的sklearn中的贝叶斯分类器。

(1)获取训练数据:

# 获取训练数据def read_train_data(self):# 存放抽象问题train_x=[]# 存放抽象问题 对应的类别序号 0-13train_y=[]# 读入所有的问题分类数据 0-13file_list=getfilelist("./data/question/")# 遍历所有文件for one_file in file_list:# 获取文件名中的数字num = re.sub(r'\D', "", one_file)# 如果该文件名有数字,则读取该文件if str(num).strip()!="":# 设置当前文件下的数据标签label_num=int(num)# 读取文件内容with(open(one_file,"r",encoding="utf-8")) as fr:data_list=fr.readlines()for one_line in data_list:word_list=list(jieba.cut(str(one_line).strip()))# 将这一行加入结果集train_x.append(" ".join(word_list))train_y.append(label_num)print(train_x) # 问题列表print(train_y) # 问题序号列表return train_x,train_y
['nm 的 评分 是 多少', 'nm 得 了 多少 分', 'nm 的 评分 有 多少', 'nm 的 评分', 'nm 的 分数 是', 'nm 电影 分数 是 多少', 'nm 评分', 'nm 的 分数 是 多少', 'nm 这部 电影 的 评分 是 多少', 'nnt 演过 哪些 风格 的 电影', 'nnt 演过 的 电影 都 有 哪些 风格', 'nnt 演过 的 电影 有 哪些 类型', 'nnt 演过 风格 的 电影', 'nnt 演过 类型 的 电影', 'nnt 演过 题材 的 电影', '\ufeff nnt 和 nnr 合作 的 电影 有 哪些', 'nnt 和 nnr 一起 拍 了 哪些 电影', 'nnt 和 nnr 一起 演 过 哪些 电影', 'nnt 与 nnr 合拍 了 哪些 电影', 'nnt 和 nnr 合作 了 哪些 电影', '\ufeff nnt 一共 参演 过 多少 电影', 'nnt 演过 多少 部 电影', 'nnt 演过 多少 电影', 'nnt 参演 的 电影 有 多少', 'nnt 的 出生日期', 'nnt 的 生日', 'nnt 生日 多少', 'nnt 的 出生 是 什么 时候', 'nnt 的 出生 是 多少', 'nnt 生日 是 什么 时候', 'nnt 生日 什么 时候', 'nnt 出生日期 是 什么 时候', 'nnt 什么 时候 出生 的', 'nnt 出 生于 哪一天', 'nnt 的 出生日期 是 哪一天', 'nnt 哪一天 出生 的', 'nm 的 上映 时间 是 什么 时候', 'nm 的 首映 时间 是 什么 时候', 'nm 什么 时候 上映', 'nm 什么 时候 首映', 'nm 什么 时候 在 影院 上线', '什么 时候 可以 在 影院 看到 nm', 'nm 什么 时候 在 影院 放映', 'nm 什么 时候 首播', 'nm 的 风格 是 什么', 'nm 是 什么 风格 的 电影', 'nm 的 格调 是 什么', 'nm 是 什么 格调 的 电影', 'nm 是 什么 类型 的 电影', 'nm 的 类型 是 什么', 'nm 是 什么 类型 的', 'nm 的 剧情 是 什么', 'nm 主要 讲 什么 内容', 'nm 的 主要 剧情 是 什么', 'nm 主要 讲 什么 故事', 'nm 的 故事 线索 是 什么', 'nm 讲 了 什么', 'nm 的 剧情简介', 'nm 的 故事 内容', 'nm 的 主要 情节', 'nm 的 情节 梗概', 'nm 的 故事梗概', 'nm 有 哪些 演员 出演', 'nm 是 由 哪些 人演 的', 'nm 中 参演 的 演员 都 有 哪些', 'nm 中 哪些 人演 过', 'nm 这部 电影 的 演员 都 有 哪些', 'nm 这部 电影 中 哪些 人演 过', 'nnt', 'nnt', 'nnt', 'nnt', 'nnt', 'nnt 是', 'nnt 是 谁', 'nnt 的 介绍', 'nnt 的 简介', '谁 是 nnt', 'nnt 的 详细信息', 'nnt 的 信息', 'nnt 演过 哪些 ng 电影', 'nnt 演 哪些 ng 电影', 'nnt 演过 ng 电影', 'nnt 演过 什么 ng 电影', 'nnt 演过 ng 电影', 'nnt 演过 的 ng 电影 有 哪些', 'nnt 出演 的 ng 电影 有 哪些', 'nnt 演了 什么 电影', 'nnt 出演 了 什么 电影', 'nnt 演过 什么 电影', 'nnt 演过 哪些 电影', 'nnt 过去 演 过 哪些 电影', 'nnt 以前 演 过 哪些 电影', 'nnt 演过 的 电影 有 什么', 'nnt 有 哪些 电影', '\ufeff nnt 参演 的 评分 大于 x 的 电影 有 哪些', 'nnt 参演 的 电影 评分 大于 x 的 有 哪些', 'nnt 参演 的 电影 评分 超过 x 的 有 哪些', 'nnt 演 的 电影 评分 超过 x 的 有 哪些', 'nnt 演 的 电影 评分 大于 x 的 都 有 哪些', 'nnt 演 的 电影 评分 在 x 以上 的 都 有 哪些', '\ufeff nnt 参演 的 评分 小于 x 的 电影 有 哪些', 'nnt 参演 的 电影 评分 小于 x 的 有 哪些', 'nnt 参演 的 电影 评分 低于 x 的 有 哪些', 'nnt 演 的 电影 评分 低于 x 的 有 哪些', 'nnt 演 的 电影 评分 小于 x 的 都 有 哪些', 'nnt 演 的 电影 评分 在 x 以下 的 都 有 哪些']
[0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9]

(2)训练多分类贝叶斯分类器模型

# 训练并测试模型-NBdef train_model_NB(self):X_train, y_train = self.train_x, self.train_y# 调用sklearn中的TF-IDFself.tv = TfidfVectorizer()# fit_transform(trainData)对部分数据先拟合fit,找到该part的整体指标,# 如均值、方差、最大值最小值等等(根据具体转换的目的),# 然后对该trainData进行转换transform,从而实现数据的标准化、归一化等等。train_data = self.tv.fit_transform(X_train).toarray()# alpha:浮点型,可选项,默认1.0,添加拉普拉斯/Lidstone平滑参数。# 当α=1时,称作Laplace平滑,当0<α<1时,称作Lidstone平滑,α=0时不做平滑。# MultinomialNB多项式朴素贝叶斯clf = MultinomialNB(alpha=0.01)clf.fit(train_data, y_train)return clf

(3)利用训练好的模型来对新问题进行分类预测

# 预测def predict(self,question):# 对问题进行分词question=[" ".join(list(jieba.cut(question)))]# 将问题输入转换为词向量矩阵test_data=self.tv.transform(question).toarray()# 调用模型完成预测 返回问题编号 0 - 13y_predict = self.model.predict(test_data)[0]print("question type:",y_predict)return y_predict


返回用户问题所属的类别编号,这个编号也就对应一个问题模板:

0:nm 评分
1:nm 上映时间
2:nm 类型
3:nm 简介
4:nm 演员列表
5:nnt 介绍
6:nnt ng 电影作品
7:nnt 电影作品
8:nnt 参演评分 大于 x
9:nnt 参演评分 小于 x
10:nnt 电影类型
11:nnt nnr 合作 电影列表
12:nnt 电影数量
13:nnt 出生日期

(4)替换模板中的抽象内容

数字和模板的对应关系可以提前存到一个字典中,当预测出编号后,直接通过这个编号作为字典的key值,value就是根据该模板来查询答案的方法,这样就查询出问题模板了。比如预测的结果是2,则对应的问题模板 nm 类型,表示询问某部电影的类型,再结合前一阶段获取的电影名字,则可以组成一个新的问题,比如:

    def __init__(self):self.q_template_dict={0:self.get_movie_rating, # 电影评分1:self.get_movie_releasedate,# 电影上映时间2:self.get_movie_type,# 电影类型3:self.get_movie_introduction,# 电影简介4:self.get_movie_actor_list,# 电影演员列表5:self.get_actor_info,# 电影简介6:self.get_actor_act_type_movie,# 演员的该类别电影作品7:self.get_actor_act_movie_list,# 演员的电影作品8:self.get_movie_rating_bigger,# 演员的参演评分大于x9:self.get_movie_rating_smaller,# 演员的参演评分小于x10:self.get_actor_movie_type,# 电影类型11:self.get_cooperation_movie_list,# 合作的电影列表12:self.get_actor_movie_num, # 电影数量13:self.get_actor_birthday# 演员出生日期}
肖申克的救赎 类型

3.答案获取
在已知问题和答案模板之后,可以通过调用对应的方法得到结果。在对应的方法中,利用Cypher语言来构建查询语句,其基本形式是:

match(n)-[r] -(b)

项目使用python的库py2neo来操作图数据库neo4j。这里只涉及到查询操作,所以直接构造了Cypher查询语句,然后使用py2neo库的run方法来查询,数据库的链接和查询单独的写了一个类,在需要的时候调用即可:

#-*- coding: UTF-8 -*-
# @Time    : 2022/11/14
# @Author  : zgf
# @Site    :
# @File    : query.py
# @Software: PyCharm
from py2neo import Graph,Node,Relationship,NodeMatcher
class Query():def __init__(self):# self.graph=Graph("http://localhost:7474", username="neo4j",password="090711zgf")# 连接图形数据库用户名和密码self.graph=Graph("http://localhost:7474", auth=("neo4j", "090711zgf"))# 问题类型0,查询电影得分def run(self,cql):# find_rela  = test_graph.run("match (n:Person{name:'张学友'})-[actedin]-(m:Movie) return m.title")result=[]find_rela = self.graph.run(cql)for i in find_rela:result.append(i.items()[0][1])return result
# if __name__ == '__main__':
#     SQL=Query()
#     result=SQL.run("match (m:Movie)-[]->() where m.title='卧虎藏龙' return m.rating")
#     print(result)

那么接下来就是13个问题对应的实现方法,主要是构造Cypher查询语句

(1)获取电影评分

# 0:nm 电影评分def get_movie_rating(self):# 获取电影名称,这个是在原问题中抽取的movie_name=self.get_movie_name()# cql语句# match 从数据库获取有关节点、关系和属性的数据 相当于查询# match (节点的名称:节点标签名称)# -[<relationship-label-name>:<relationship-name>]关系的名称:关系的标签名称# where : Neo4j CQL在CQL match命令中提供了where子句来过滤MATCH查询的结果# WHERE <condition> 其中condition语法为:<property-name> <comparison-operator> <value> cql比较运算符# return m的电影评分cql = f"match (m:Movie)-[]->() where m.title='{movie_name}' return m.rating"print(cql)# 执行sql语句answer = self.graph.run(cql)[0]print(answer)answer = round(answer, 2) # 用于数字的四舍五入,保留两位小数final_answer=movie_name+"电影评分为"+str(answer)+"分!"return final_answer

(2)上映时间

# 1:nm 上映时间def get_movie_releasedate(self):movie_name = self.get_movie_name()cql = f"match(m:Movie)-[]->() where m.title='{movie_name}' return m.releasedate"print(cql)answer = self.graph.run(cql)[0]final_answer = movie_name + "的上映时间是" + str(answer) + "!"return final_answer

(3)电影类型

# 2:nm 类型def get_movie_type(self):movie_name = self.get_movie_name()cql = f"match(m:Movie)-[r:is]->(b) where m.title='{movie_name}' return b.name"print(cql)answer = self.graph.run(cql)answer_set=set(answer)answer_list=list(answer_set)answer="、".join(answer_list)final_answer = movie_name + "是" + str(answer) + "等类型的电影!"return final_answer

(4)电影简介

# 3:nm 简介def get_movie_introduction(self):movie_name = self.get_movie_name()cql = f"match(m:Movie)-[]->() where m.title='{movie_name}' return m.introduction"print(cql)answer = self.graph.run(cql)[0]final_answer = movie_name + "主要讲述了" + str(answer) + "!"return final_answer

(5)演员列表

# 4:nm 演员列表def get_movie_actor_list(self):movie_name=self.get_movie_name()cql = f"match(n:Person)-[r:actedin]->(m:Movie) where m.title='{movie_name}' return n.name"print(cql)answer = self.graph.run(cql)answer_set = set(answer)answer_list = list(answer_set)answer = "、".join(answer_list)final_answer = movie_name + "由" + str(answer) + "等演员主演!"return final_answer

(6)演员介绍

# 5:nnt 介绍def get_actor_info(self):actor_name = self.get_name('nr')cql = f"match(n:Person)-[]->() where n.name='{actor_name}' return n.biography"print(cql)answer = self.graph.run(cql)[0]final_answer = answerreturn final_answer

(7)演员出演作品类型

# 6:nnt ng 电影作品def get_actor_act_type_movie(self):actor_name = self.get_name("nr")type=self.get_name("ng")# 查询电影名称cql = f"match(n:Person)-[]->(m:Movie) where n.name='{actor_name}' return m.title"print(cql)movie_name_list = list(set(self.graph.run(cql)))# 查询类型result=[]for movie_name in movie_name_list:movie_name=str(movie_name).strip()try:cql=f"match(m:Movie)-[r:is]->(t) where m.title='{movie_name}' return t.name"# print(cql)temp_type=self.graph.run(cql)if len(temp_type)==0:continueif type in temp_type:result.append(movie_name)except:continueanswer="、".join(result)print(answer)final_answer = actor_name+"演过的"+type+"电影有:\n"+answer+"。"return final_answer

(8)演员出演作品

# 7:nnt 电影作品def get_actor_act_movie_list(self):actor_name = self.get_name("nr")answer_list=self.get_actorname_movie_list(actor_name)answer = "、".join(answer_list)final_answer = actor_name + "演过" + str(answer) + "等电影!"return final_answerdef get_actorname_movie_list(self,actorname):# 查询电影名称cql = f"match(n:Person)-[]->(m:Movie) where n.name='{actorname}' return m.title"print(cql)answer = self.graph.run(cql)answer_set = set(answer)answer_list = list(answer_set)return answer_list

(9)作品评分

    def get_movie_rating_bigger(self):actor_name=self.get_name('nr')x=self.get_num_x()cql = f"match(n:Person)-[r:actedin]->(m:Movie) where n.name='{actor_name}' and m.rating>={x} return m.title"print(cql)answer = self.graph.run(cql)answer = "、".join(answer)answer = str(answer).strip()final_answer=actor_name+"演的电影评分大于"+x+"分的有"+answer+"等!"return final_answerdef get_movie_rating_smaller(self):actor_name = self.get_name('nr')x = self.get_num_x()cql = f"match(n:Person)-[r:actedin]->(m:Movie) where n.name='{actor_name}' and m.rating<{x} return m.title"print(cql)answer = self.graph.run(cql)answer = "、".join(answer)answer = str(answer).strip()final_answer = actor_name + "演的电影评分小于" + x + "分的有" + answer + "等!"return final_answer

(10)其他问题

    def get_actor_movie_type(self):actor_name = self.get_name("nr")# 查询电影名称cql = f"match(n:Person)-[]->(m:Movie) where n.name='{actor_name}' return m.title"print(cql)movie_name_list = list(set(self.graph.run(cql)))# 查询类型result = []for movie_name in movie_name_list:movie_name = str(movie_name).strip()try:cql = f"match(m:Movie)-[r:is]->(t) where m.title='{movie_name}' return t.name"# print(cql)temp_type = self.graph.run(cql)if len(temp_type) == 0:continueresult+=temp_typeexcept:continueanswer = "、".join(list(set(result)))print(answer)final_answer = actor_name + "演过的电影有" + answer + "等类型。"return final_answerdef get_cooperation_movie_list(self):# 获取演员名字actor_name_list=self.get_name('nr')movie_list={}for i,actor_name in enumerate(actor_name_list):answer_list=self.get_actorname_movie_list(actor_name)movie_list[i]=answer_listresult_list=list(set(movie_list[0]).intersection(set(movie_list[1])))print(result_list)answer="、".join(result_list)final_answer=actor_name_list[0]+"和"+actor_name_list[1]+"一起演过的电影主要是"+answer+"!"return final_answerdef get_actor_movie_num(self):actor_name=self.get_name("nr")answer_list=self.get_actorname_movie_list(actor_name)movie_num=len(set(answer_list))answer=movie_numfinal_answer=actor_name+"演过"+str(answer)+"部电影!"return final_answer

(11)演员生日

    def get_actor_birthday(self):actor_name = self.get_name('nr')cql = f"match(n:Person)-[]->() where n.name='{actor_name}' return n.birth"print(cql)answer = self.graph.run(cql)[0]final_answer = actor_name+"的生日是"+answer+"。"return final_answer

零基础搭建基于知识图谱的电影问答系统相关推荐

  1. 300行python代码从零开始构建基于知识图谱的电影问答系统2-系统业务逻辑介绍

    昨天把这个教程的目录给理出来了,然后今天就想趁着这满腔热情(无心搬砖)把剩下的教程也写了. 对于整个系统,不管具体细节是怎么实现的,是逻辑一定要理清楚,于是这一节主要介绍各个模块的逻辑,为什么要这么做 ...

  2. python+neo4j构建基于知识图谱的电影知识智能问答系统

    目录 一.写在前面: 二.系统准备: 三.系统构建 四.总结反思: 五.完整代码: Author:qyan.li Date:2022.6.3 Topic:借助于python构建知识图谱的电影知识智能问 ...

  3. app后台运行会给服务器发信息吗_零基础搭建电视直播APP平台第一弹(支持安卓+电视盒子)...

    大家好 , 我是阿尘,欢迎来到:极梦小屋. 由于公众号改版,建议大家 星标置顶 本公众号,就可以第一时间接收到我们所推荐的精品资源啦! 为了大家更方便的交流和可以不错过每天的分享,所以特意建了一个交流 ...

  4. 最新最全vuepress零基础搭建(github搭建+新增插件)

    最新最全vuepress零基础搭建 标注:最终版以及修改最终都在www.javanode.cn是最终版本,在学习中需要修改的内容以及笔记全在这个网站,谢谢!有任何不妥的地方望纠正 看完了,发现对你有用 ...

  5. 【Workshshop No.3 | Kyligence X 青云QingCloud Workshop】零基础搭建云上大数据平台

    7月13日Kyligence 与青云QingCloud 联合举办的"零基础搭建云上大数据平台" Workshop诚邀您参加. Kyligence Cloud 是 Kyligence ...

  6. 局部配置和全局配置_06. 教你零基础搭建小程序(解读全局配置文件-tabBar字段)...

    自从开始在知乎上发教程后,发现一个事情啊, 大家对于我写的教程,都在偷偷地收藏~~ 但是, 却没有银点赞~ 知乎这个平台吧,点赞的分量比收藏更大, 这里也不是要赞(我知道自己还能做的更好), 只是希望 ...

  7. apk安装到电视上看不到图标_零基础搭建电视直播APP平台第二弹(修改APP)

    大家好 , 我是阿尘,欢迎来到:极梦小屋. 由于公众号改版,建议大家 星标置顶 本公众号,就可以第一时间接收到我们所推荐的精品资源啦! 为了大家更方便的交流和可以不错过每天的分享,所以特意建了一个交流 ...

  8. 零基础搭建获利的外卖cps平台公众号

    1 .前言 很多小伙伴想做外卖CPS赚钱,那给大家做一起超详细的外卖CPS教程.话不多说,直接上货 为什么说能赚钱?例如你有一千个好友(四,五个微信群),如果每个人一天吃一顿外卖20块,你拿5% 10 ...

  9. php 上传apk包到cdn_零基础搭建自己的博客网站和配置CDN设置wordpress篇

    零基础搭建自己的博客网站 博客类的建站程序有很多例如wordpress. typecho.zblog.emlog等等这几种是最常见的 平时我们用的见的更多的都是wordpress,因为wordpres ...

最新文章

  1. CouncurrentHashMap源码解析
  2. Android --- 从相册中选择图片或者拍着选择图片遇到的问题
  3. Apache Mahout基于商品的协同过滤算法流程分析
  4. 替换url部分_MOCTF部分Web题攻略
  5. python按行读取文件取消空白行_python去掉空白行的多种实现代码
  6. 使用 保存文件_使用SaveFileDialog调用保存文件对话框
  7. PostgreSQL的backuplabel file 初步学习
  8. 2018.06.30 BZOJ1857: [Scoi2010]传送带(三分套三分)
  9. [Wireshark]_002_玩转数据包
  10. asterisk queue 队列
  11. html5怎么给标题居中,html5标题居中 Html5如何使div里面文字在水平垂直居中对齐...
  12. 怎么让照片里的人嘴巴动起来_让照片动起来软件下载-让照片动起来制作软件下载-西西软件下载...
  13. 大数据工程师和数据分析师有什么区别
  14. igg google
  15. poi导出数据文件名错误_POI导出Excel报错“扩展名与文件的格式不匹配”
  16. 从利用gensim 训练好的word2vec模型中取出向量并计算余弦相似度,Levenshtein distance 计算
  17. vue项目使用高德地图
  18. VBA中字典的写入技巧
  19. BPF之巅--洞悉Linux系统和应用性能 Brendan Gregg
  20. 公司绝对不会告诉你的潜规则 - 看到职场如战场了吧

热门文章

  1. 常见web登陆授权方式及原理
  2. 连续8年 远见领跑|山石网科入选Gartner 2021网络防火墙魔力象限
  3. Excel 2010 多个窗口独立同屏显示方法——修改注册表方法
  4. iphone 打开safari调试
  5. 快速读懂Http3协议总结
  6. win7安全模式如何打开计算机管理,Win7怎么退出安全模式 win7系统退出安全模式的方法...
  7. 运维工程师都在做什么
  8. 复旦大学计算机保研夏令营
  9. 惠普服务器开机显示系统恢复选项,惠普一键恢复出厂设置【操作办法】
  10. 我国信创行业迅速发展,IT产业等领域有望实现国产化