知识图谱项目——红色文化之张学良人物知识图谱(Neo4j+vue+flask+mysql实现)

news2024/11/15 11:13:30

张学良人物简史知识图谱_说明文档

本项目为人工智能专业大三知识图谱课程期末作业。意在完成一个以张学良为背景的红色文化类知识图谱。文末放上本项目的代码地址。

文章目录

  • 张学良人物简史知识图谱_说明文档
      • :rocket:前端
      • :rocket:后端
      • :rocket:中间件
      • :rocket:数据库
      • :rocket:服务器
    • :book:1、数据采集
    • :rabbit2:2、数据预处理
    • :rabbit:3、Neo4j数据库导入
    • :racehorse:4、前端展示
    • :dog:5、项目总体展示
    • :page_facing_up:6、论文知识抽取

🚀前端

  • Vue.js
  • d3.js
  • jQuery
  • html/css/js

🚀后端

  • Flask

🚀中间件

🅰️axios

🅱️neo4j-driver

🚀数据库

  • MySQL
  • Neo4j

🚀服务器

  • 腾讯云轻量应用服务器

📖1、数据采集

互联网上搜集数据,本项目基于百度百科的数据,进行搜集并绘制初始的知识图谱,并搜集到了十种关系类别。并建立 second.csv

idname
1property
2relatives
3biography
4ally
5politicalViewPoint
6Subordinate
7Superior
8Enemy
9Everywhere he goes
10Someone who knew him

由于采集了100条真实数据,为了测试数据量大的情况。使用Faker库来进行张学良去过的地方以及认识张学良的人数据

from faker import Faker
import pandas as pd

fake = Faker(['zh_CN', 'en_US'])

# 生成第一列数据
country1_cities = {fake.city_name() + '市' for i in range(2000)}
column1 = list(country1_cities) + [fake.state()]*2000
print(len(column1))

# 生成第二列数据
names = {fake.name() for j in range(4000)}
column2 = list(names)
print(len(column2))

# 计算每列数据的长度
len1 = len(column1)
len2 = len(column2)

# 如果列的长度不一致,则新建一个DataFrame来保证列的长度一致
if len1 != len2:
    max_len = max(len1, len2)
    dummy_df = pd.DataFrame()
    if len1 < max_len:
        dummy_df['国家或地区'] = ['']*(max_len - len1)
        column1.extend(dummy_df['国家或地区'].tolist())
    elif len2 < max_len:
        dummy_df['人名'] = ['']*(max_len - len2)
        column2.extend(dummy_df['人名'].tolist())

# 将数据转化为DataFrame
df = pd.concat([pd.DataFrame(column1, columns=['国家或地区']), pd.DataFrame(column2, columns=['人名'])], axis=1)

# 保存到csv文件中
df.to_csv('地名与人名不重复.csv', index=False)

使用实体识别技术将网络文本中的实体抽取

import jieba.posseg as pseg
import textract
import csv
file_path = '数据.docx'
text = textract.process(file_path).decode('utf-8')
with open('实体数据结果.csv', 'w', newline='', encoding='utf-8') as csvfile:
    writer = csv.writer(csvfile)
    shiti = pseg.cut(text)
    # 找出所有组成的 'nt'(机构团体)和 'nz'(其他专有名词)类型的词汇
    for word, flag in shiti:
        if flag in ['nt', 'nz']:
            writer.writerow([word, flag])

🐇2、数据预处理

将所有类别采集到的数据放入 third.csv

idnamedescribe
49联俄、联共、扶助农工,“三大政策”张学良提出的“三大政策”,即联俄、联共、扶助农工,是其治理东北时所推行的主要政策,也是他对于中国革命和现代化建设问题的一种思考。
50中华民族统一和国家现代化张学良认为,实现中华民族统一和国家现代化是中国现代化建设事业的最终目标。他反对分裂主义和帝国主义侵略,主张通过改革和现代化建设提升中国国家实力和综合竞争力。
51民主、法制和教育改革张学良提倡以民主、法制和教育改革为核心的中国现代化进程,认为这是推进社会进步和国家发展的重要保障。他主张发扬民主,建设法治,推进教育改革,促进中国社会的和谐发展。
52统一战线和减轻民众负担张学良主张建立广泛统一战线,积极团结各界人士,推进以减轻民众负担为核心的经济和社会改革。他认为,这是实现中华民族伟大复兴和国家现代化的必经之路。
53杨虎城曾任东北军第一军军长,是张学良手下最得力的将领之一。
54万福麟曾任东北军第二十七师师长,是张学良的心腹之一,后因支持抗日战争而遭到逮捕。
55刘骥曾任东北军副总司令、沈阳市等职,被认为是张学良的得力助手之一。
56谭道源曾任东北军第十三路军军长,是张学良的部属之一。
57傅作义曾任东北军第三军军长、华北政务委员会等职,与张学良关系密切,在1935年“九一八事变”后加入了中国党。
58马步芳曾任东北军第八师师长、奉天等职,是张学良手下的一位著名将领。
59张作霖是张学良的父亲,也是东北军的创始人之一。张学良在东北军的初期时期曾担任他的副手,后继任东北军总司令。
60孙传芳曾是张学良的上级长官,掌管了奉天和陆军第三师等职。
61马步芳曾是张学良的上级长官,任命他为东北军第八师师长。
62蒋介石是中国的创始人和领袖,曾与张学良有过密切合作关系。在国共合作时期,两人曾携手抵抗日本侵略,但在中国内战中,两人成为敌对方。
63汪精卫是中国国内党人以外最早提出“联共”口号的家之一。

建立关系表

third_idsecond_idrole
11sex
21alias
31nationality
41nation
51birthdate

🐰3、Neo4j数据库导入

建约束条件

在导入数据之前,需要先创建节点类型的约束条件,以确保不会出现重复的节点。

Neo4j 1.5版本

CREATE CONSTRAINT FOR (s:second) REQUIRE s.id IS UNIQUE;
CREATE CONSTRAINT FOR (t:third ) REQUIRE t.id IS UNIQUE;

Neo4j 1.4版本

CREATE CONSTRAINT ON (s:second) ASSERT s.id IS UNIQUE;
CREATE CONSTRAINT ON (t:third ) ASSERT t.id IS UNIQUE;

在准备好数据文件和创建约束条件之后,可以使用Cypher导入语句进行数据导入。

#Third.csv

LOAD CSV WITH HEADERS FROM 'file:///second.csv' AS line
CREATE (s:second{id: toInteger(line.id), name: line.name, year: toInteger(line.year)});
LOAD CSV WITH HEADERS FROM "file:///third.csv" AS line
CREATE (t:third {id: toInteger(line.id), name: line.name, gender: line.gender});
LOAD CSV WITH HEADERS FROM "file:///third_role.csv" AS line
MATCH (s:second{id: toInteger(line.second_id)})
MATCH (t:third {id: toInteger(line.third_id)})
CREATE (s)-[:role {name: line.role}]->(t);

创建节点

//创建节点
create (n:person{name:"张学良"})

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OIWpOjHs-1687009471889)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20230617211726846.png)]

建立节点之间的关系

//建立节点之间的关系
match(n:person),(s:second) where n.name="张学良" and s.name="property" create(n)-[r:属性]- >(s);

match(n:person),(s:second) where n.name="张学良" and s.name="biography" create(n)-[r:传记]- >(s);

match(n:person),(s:second) where n.name="张学良" and s.name="relatives" create(n)-[r:亲属]- >(s);

match(n:person),(s:second) where n.name="张学良" and s.name="politicalViewPoint" create(n)-[r:政治观点]- >(s);

match(n:person),(s:second) where n.name="张学良" and s.name="ally" create(n)-[r:盟友]- >(s);

match(n:person),(s:second) where n.name="张学良" and s.name="Subordinate" create(n)-[r:下属]- >(s);

match(n:person),(s:second) where n.name="张学良" and s.name="Superior" create(n)-[r:上司]- >(s);

match(n:person),(s:second) where n.name="张学良" and s.name="Enemy" create(n)-[r:敌人]- >(s);

match(n:person),(s:second) where n.name="张学良" and s.name="Everywhere he goes" create(n)-[r:去过的地方]- >(s);

match(n:person),(s:second) where n.name="张学良" and s.name="Someone who knew him" create(n)-[r:认识他的人]- >(s);

敌人

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YpKcDJXu-1687009471893)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20230617211805402.png)]

上司

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cQNI6zTw-1687009471894)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20230617211840837.png)]

认识他的人(显示达到上限)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qiI8RcGQ-1687009471895)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20230617211956800.png)]

🐎4、前端展示

由于neo4j数据库中最多只能显示300个节点,我就是想看所有节点,想炫酷地一起展示几千个节点。

所以使用d3、neo4j-driver进行数据库连接、读取和前端展示

<!--APP.vue-->
<template>
<div id="graph-container"></div>
</template>

<script>
import neo4j from "neo4j-driver";
import * as d3 from 'd3';
import * as d3Force from 'd3-force';

let driver = neo4j.driver(
  "bolt://localhost:7687",
  neo4j.auth.basic("neo4j", "1234")
);

export default {
  name: "app",
  data() {
    return {
      graphData: [],
      nodes: [],
      relationships: [],
    };
  },
  props: {},
  created() {
    this.fetchData();
  },
  methods: {
    setupNeo4j() {
      this.driver = neo4j.driver(
        'bolt://localhost:7687',
        neo4j.auth.basic('neo4j', '1234'),
        { encrypted: false }
      );
      this.session = this.driver.session();
    },
    async getData() {
      const result = await this.session.run(
        `
        MATCH (n)-[r]->(p)
        RETURN n, r, p
        `
      );

      const nodes = [];
      const edges = [];

      result.records.forEach(record => {
        nodes.push({
          id: record.get('n').identity.toNumber(),
          name: record.get('n').properties.name,
          label: record.get('n').labels[0],
        });

        nodes.push({
          id: record.get('p').identity.toNumber(),
          name: record.get('p').properties.name,
          label: record.get('p').labels[0],
        });

        edges.push({
          source: record.get('n').identity.toNumber(),
          target: record.get('p').identity.toNumber(),
          type: record.get('r').type,
          properties: record.get('r').properties,
        });
      });

      return { nodes, edges };
    },
    async drawGraph() {
      const data = await this.getData();

      const svg = d3.select('#graph-container').append('svg');

      const width = window.innerWidth;
      const height = window.innerHeight;

      svg.attr('width', width).attr('height', height);

      const simulation = d3Force
        .forceSimulation()
        .force(
          'link',
          d3Force
            .forceLink()
            .id(d => d.id)
            .distance(100)
        )
        .force(
          'charge',
          d3Force.forceManyBody().strength(-500).distanceMax(500)
        )
        .force('center', d3Force.forceCenter(width / 2, height / 2));

      const link = svg
        .selectAll('line')
        .data(data.edges)
        .enter()
        .append('line')
        .attr('stroke', '#999')
        .attr('stroke-opacity', 0.6)
        .attr('stroke-width', d => Math.sqrt(d.properties.weight));

      const node = svg
        .selectAll('circle')
        .data(data.nodes)
        .enter()
        .append('circle')
        .attr('r', 10)
        .attr('fill', '#69b3a2')
        .call(
          d3.drag().on('start', dragstarted).on('drag', dragged).on('end', dragended)
        );

      node.append('title').text(d => d.name);

      simulation.nodes(data.nodes).on('tick', ticked);
      simulation.force('link').links(data.edges);

      function ticked() {
        link
          .attr('x1', d => d.source.x)
          .attr('y1', d => d.source.y)
          .attr('x2', d => d.target.x)
          .attr('y2', d => d.target.y);

        node.attr('cx', d => d.x).attr('cy', d => d.y);
      }

      function dragstarted(d) {
        if (!d3.event.active) simulation.alphaTarget(0.3).restart();
        d.fx = d.x;
        d.fy = d.y;
      }

      function dragged(d) {
        d.fx = d3.event.x;
        d.fy = d3.event.y;
      }

      function dragended(d) {
        if (!d3.event.active) simulation.alphaTarget(0);
        d.fx = null;
        d.fy = null;
      }
    }
  },
  mounted() {
    this.setupNeo4j();
    this.drawGraph();
  },
};
</script>

<style scoped>
ul {
  list-style: none;
  padding: 0;
}
</style>

结果如图:和neo4j拥有一样的浮动效果,就是没有实现拖拽哈哈。

在这里插入图片描述

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-n34VyRDZ-1687009471898)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20230617212827643.png)]

🐶5、项目总体展示

使用Flask框架连接mysql数据库实现了节点的动态存储

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ek4VePtb-1687009471898)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20230617213324015.png)]

由于需要操作数据库,所以实现了登录注册功能,来对能操作建立节点的用户设置权限。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xkgOH9AW-1687009471899)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20230617213442350.png)]

使用简单的get请求来传到url上,仅供学习。

点击建立节点页面

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fCoBriXh-1687009471899)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20230617213619129.png)]

我们可以输入主节点的名称、主节点的关系和指向节点的名称,注意节点名在数据库中只能存在一个。

此外还可以新增节点来建立多个节点之间的关系。比如我们要将右侧的案例复现。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-A8zlPyYE-1687009471899)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20230617213917726.png)]

提交后结果如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ywX9cxRo-1687009471900)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20230617213943061.png)]

Flask后端实现代码如下:

from kgview import kg_view
import json
from flask import Flask, render_template, request
# 导入pymysql模块
import pymysql

# 连接database
conn = pymysql.connect(host="localhost", user="root", password="1234", port=3306, database="test", charset="utf8",
                       autocommit=True)
# 得到一个可以执行SQL语句的光标对象
cursor = conn.cursor()
class saveData():
    idData = None
data = saveData()
app = Flask(__name__)


# 装饰器  给函数新增功能
@app.route('/')  # 路由
def index():
    return render_template('Z.html')


@app.route('/s')
def search():
    keyword = request.args.get('search')
    kg_view(keyword)
    links = kg_view(keyword)
    for i in range(len(links)):
        links[i] = links[i].replace("source", '"source"').replace("target", '"target"').replace("type",
                                                                                                '"type"').replace("'",
                                                                                                                  '"')
        links[i] = json.loads(links[i])
    return render_template('index.html', result_json=links)


@app.errorhandler(404)
# 当发生404错误时,会被该路由匹配
def handle_404_error(err_msg):
    """自定义的异常处理函数"""
    # 这个函数的返回值就是前端用户看到的最终结果 (404错误页面)
    return u"出现了404错误, 错误信息:%s" % err_msg


@app.route('/dl')
def dl():
    return render_template('dl.html')


@app.route('/dltj')
def dltj():
    """登录"""
    pwd = request.args.get('password')
    id = request.args.get('username')
    data.idData = id
    try:
        sql = """
        SELECT pwd FROM users WHERE pwd=%s;
        """
        # 执行SQL语句
        # 判断是否查询到结果1为有0为无
        judge = cursor.execute(sql, id)
        conn.commit()
        desc = cursor.description
        data_dict = [dict(zip([col[0] for col in desc], row)) for row in cursor.fetchall()]  # 列表表达式把数据组装起来
        print(data_dict)
        # 真实密码
        zm = data_dict[0].get('pwd')
        print(zm)
        if judge == 0:
            return "没有这个用户!"
        else:
            if zm == pwd:
                return render_template('Z.html')
            else:
                return "密码错误"
    except:
        return "用户不存在"
    return render_template('Z.html')


@app.route('/zc')
def zc():
    return render_template('zc.html')


@app.route('/zctj')
def zctj():
    """注册"""
    zcpwd = request.args.get('zcpassword')
    zcid = request.args.get('zcid')
    try:
        sql = """
        INSERT INTO users (id,pwd) VALUES (%s,%s);
        """
        # 执行SQL语句
        cursor.execute(sql, [zcid, zcpwd])
        conn.commit()
    except:
        return "用户名重复"
    # 关闭光标对象
    # cursor.close()
    return render_template('dl.html')


@app.route('/myNode')
def returnMyNode():
    id = data.idData
    """取出我的节点"""
    try:
        sql = """
        SELECT nodeData FROM users WHERE id=%s;
        """
        # 执行SQL语句
        # 判断是否查询到结果1为有0为无
        cursor.execute(sql, id)
        conn.commit()
        desc = cursor.description
        data_dict = [dict(zip([col[0] for col in desc], row)) for row in cursor.fetchall()]  # 列表表达式把数据组装起来
        # 节点数据
        nd = data_dict[0].get('nodeData')
    except:
        return "您还尚未登录"
    links = nd
    return render_template('index.html', result_json=links)


@app.route('/createNode')
def createMyNode():
    return render_template('createNode.html')



@app.route('/add')
def addnode():
    print(data.idData)
    id = data.idData
    i = request.args.get('nodeNum')
    i = int(i)
    insideDict={}
    links = []
    links1 = []
    for j in range(1, i + 1):
        node = request.args.get('mainnode' + str(j))  # 节点
        target = request.args.get('point' + str(j))  # 指向
        rela = request.args.get('rela' + str(j))  # 关系
        insideDict = {'source': node,'target': target,'type':'resolved',  'rela': rela,}
        links.append(insideDict)
        links1.append(node)
        links1.append(target)
        links1.append(rela)
    link = str(links)
    """节点存入数据库"""
    print(insideDict.values())
    sql = """
    insert into node (node,relation,target,id) values (%s,%s,%s,%s)
    """

    cursor.execute(sql, [links1[0],links1[1],links1[2],id])
    conn.commit()
    return render_template('index.html',result_json=links)


if __name__ == '__main__':
    # debug调试模式=true自动重启
    app.run(debug=True)

📄6、论文知识抽取

我们根据已有的内容总结出了论文——docx文档

随后,对论文进行了知识抽取功能

  • 1、读取文档内容
  • 2、去停用词、分词
  • 3、实体识别
  • 4、词性标注
  • 5、依存句法分析
  • 6、词频统计
  • 7、词云展示
  • 8、关系抽取
import jieba
from collections import Counter
from wordcloud import WordCloud
import textract
import pytesseract
from PIL import Image
import numpy as np
import cv2
import csv
import textract
import jieba.posseg as pseg
import nltk
from nltk.parse import stanford
from nltk.corpus import stopwords
from stanfordcorenlp import StanfordCoreNLP
import spacy
nlp = spacy.load('en_core_web_sm')


# 读取文档内容
file_path = '知识图谱论文.docx'
text = textract.process(file_path).decode('utf-8')


# 去停用词、分词
baidu_stopwords = [line.strip() for line in open('baidu_stopwords.txt', 'r', encoding='utf-8').readlines()]
words = [word for word in jieba.cut(text) if word not in baidu_stopwords and len(word) > 1]
print(words)


# 实体识别
shiti = pseg.cut(text)
# 找出所有组成的 'nt'(机构团体)和 'nz'(其他专有名词)类型的词汇
for word, flag in shiti:
    if flag in ['nt', 'nz']:
        print(word, flag)



# 词性标注
# 对每个列表元素进行词性标注
for word, flag in pseg.cut(" ".join(words)):
    print(word, flag)
with open("词性标注.txt", "w", encoding="utf-8") as f:
    for word, flag in pseg.cut(" ".join(words)):
        f.write(word + " " + flag + "\n")


# 查看句子的依存关系
doc = nlp(' '.join(words))

for token in doc:
    print(token.text, token.dep_, token.head.text, token.head.pos_,
            [child for child in token.children])
# 其中,token.dep_表示词性依存关系,例如nsubj表示主语,amod表示形容词修饰语,dobj表示直接宾语等等;token.head表示当前单词的父节点;token.children表示当前单词的子节点。
with open("依存关系.txt", "w") as f:
    for token in doc:
        f.write(f"{token.text}\t{token.dep_}\t{token.head.text}\t{token.head.pos_}\t"
                f"{[child for child in token.children]}\n")



# 词频统计
word_count = Counter(words)

# 词云展示
wordcloud = WordCloud(font_path='simkai.ttf', background_color='white', width=1000,
                      height=800).generate_from_frequencies(word_count)
wordcloud.to_file('wordcloud.png')

# 关系抽取
img = cv2.imread('wordcloud.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(gray, 127, 255, 0)
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
for cnt in contours:
    x, y, w, h = cv2.boundingRect(cnt)
    if w > 30 and h > 30:
        crop_img = img[y:y + h, x:x + w]
        cv2.imwrite('crop_img.png', crop_img)
        break

img = Image.open('crop_img.png')

print('去停用词、分词后的结果为:', words)
print('词频统计的结果为:', word_count)

词性标注结果:
在这里插入图片描述

依存关系:
在这里插入图片描述

词云:
在这里插入图片描述
这就是本项目的全部分享了,代码已开源,地址见评论或私信

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/657434.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

深度学习(22)——YOLO系列(2)

深度学习&#xff08;22&#xff09;——YOLO系列&#xff08;2&#xff09; 文章目录 深度学习&#xff08;22&#xff09;——YOLO系列&#xff08;2&#xff09;1. model2. dataset3. utils4. test/detect5. detect全过程 今天先写YOLO v3的代码&#xff0c;后面再出v5&…

代码托管/版本控制工具:Git的安装和使用

目录 一、Git的下载和安装二、Git基本配置三、代码上传到远程仓库四、代码下载到本地 一、Git的下载和安装 1.登录GitHub官网https://github.com/注册账户密码 2.登录https://git-scm.com/download/win &#xff08;根据自己电脑的位数和系统下载git&#xff09; 3.双击Gi…

02-IDEA 集成Maven

一. 下载IDEA编辑器 下载地址&#xff1a;Download IntelliJ IDEA – The Leading Java and Kotlin IDE 选中免费开源的社区版本 创建桌面图标和添加安装路径到系统变量&#xff0c;其他的默认安装即可。 二. 配置Maven环境 分为局部配置和全局配置 1. 局部配置maven环境 …

004依赖

传递 一个坐标引入多个jar 传递 子工程 引入了父pom 也是一种传递 继承 继承是为了消除重复&#xff0c;如果将 dao、service、web 分开创建独立的工程则每个工程的 pom.xml 文件中的内容存在重复&#xff0c;比如&#xff1a;设置编译版本、锁定 spring 的版本的等&#xff…

和鲸社区数据分析每周挑战【第九十三期:特斯拉充电桩分布分析】

和鲸社区数据分析每周挑战【第九十三期&#xff1a;特斯拉充电桩分布分析】 文章目录 和鲸社区数据分析每周挑战【第九十三期&#xff1a;特斯拉充电桩分布分析】一、前言二、数据读取和初步探索三、数据探索及可视化1、获取拥有最多充电站的 10 个国家2、一年中各月新开业数量…

I.MX RT1170之FlexSPI详解:FlexSPI基础知识和特性

最近我也在做RT1170的相关项目&#xff0c;由于项目需要&#xff0c;研究了Flash下载算法、NOR Flash空间的擦除/烧写(OTFAD XIP更新固件时要更新OTFAD Key Blob字段)、HyperRAM初始化等功能&#xff0c;这些都是开发过程中可能会遇到的一些问题&#xff0c;而这些都与FlexSPI接…

第2章 信息技术发展

文章目录 2.1.2计算机网络1.网络标准协议2.软件定义网络3.第五代移动通信技术 2.1.3存储和数据库1.存储技术2.数据结构模型3.常用数据库类型4.数据仓库 2.1.4信息安全2.1.5信息技术的发展2.2.1物联网2.2.2云计算2.2.3大数据2.2.4区块链2.2.5人工智能2.2.6虚拟现实 信息技术是在…

前端vue入门(纯代码)09

【09.vue中组件的自定义事件】 自定义组件链接 在vue中用的click【点击】、keyup【按键】……等事件&#xff0c;这些属于内置事件&#xff0c;也就是js自带的事件。 问题一&#xff1a;什么是组件自定义事件呢&#xff1f; 【内置事件】:是给html元素用的&#xff0c;比如s…

UG\NX二次开发 加密锁(加密狗)

文章作者:里海 来源网站:https://blog.csdn.net/WangPaiFeiXingYuan 加密锁简介 加密狗是一种用于保护软件版权的技术手段,它可以限制未经授权的用户在未经许可的情况下使用某些软件。软件加密锁可以保护软件开发商的知识产权,防止盗版和非法复制等行为,同时也可以…

React 对比class与Effect Hook优化响应式数据更新监听,感受useEffect真正的强大

还是之前写过的一个组件 import React from "react"export default class index extends React.Component{constructor(props){super(props);this.state {name: "小猫猫"}}componentDidMount ()>{document.title this.state.name;}componentDidUpda…

msvcr110.dll,丢失修复,msvcr110.dll,丢失修复详细解决办法

我们在运行软件程序或者游戏的时候&#xff0c;如果程序提示“无法启动此程序&#xff0c;因为计算机中丢失msvcr110.dll。尝试重新安装该程序以解决此问题”&#xff0c;如果说明您电脑系统中缺少或者未注册msvcr110.dll这个运行库文件&#xff0c;那么我们要如何解决这个问题…

Node内存管理+垃圾回收机制

最近看到《深入浅出node》这本书&#xff0c;里面正好有内存控制&#xff0c; 加上最近看到一篇文章&#xff0c;也是讲了内存管理和垃圾回收机制。 由于自己曾经做过一个ssl接口&#xff0c;导致node服务经常重启&#xff0c;我潜意识就怀疑是内存管理出现了问题&#xff0c;…

H264 NALU分析

标题 1.H264介绍2.H264编解码解析2.1. H264编码原理2.2 H264的I帧,P帧,B帧2.3 H264编码结构解析2.4 NALU2.4.1 NALU结构2.4.2 解析NALU2.4.3 annexb模式 1.H264介绍 H.264从1999年开始&#xff0c;到2003年形成草案&#xff0c;最后在2007年定稿有待核实。在ITU的标准⾥称为H.…

Ansible Playbook

Ansible 的脚本 --- playbook 剧本 playbooks 本身由以下各部分组成 &#xff08;1&#xff09;Tasks&#xff1a;任务&#xff0c;即通过 task 调用 ansible 的模板将多个操作组织在一个 playbook 中运行 &#xff08;2&#xff09;Variables&#xff1a;变量 &#xff08;3&…

Postman接口测试之:添加Cookie伪造请求

1&#xff0c;获取cookie值 登录某网站&#xff0c;通过开发者工具&#xff08;或者fiddler抓包工具&#xff09;&#xff0c;获取登录成功后的请求头中的cookie值。 大家肯定奇怪&#xff0c;明明访问首页的时候就已经生成了cookie值&#xff0c;为什么还登录呢&#xff1f;…

Linux中磁盘管理之格式化、分区、挂载-详解

今天给大家介绍一下Linux中磁盘管理中格式化、分区、挂载等操作步骤&#xff0c;希望这篇文章对大家有所帮助。 一、磁盘知识 1.磁盘含义 磁盘&#xff08;Disk&#xff09;是一种用于存储和读取数据的物理设备&#xff0c;它由一个或多个旋转的磁性盘片组成。这些盘片通常由…

递归算法学习

递归算法介绍 递归指的是函数或算法在执行过程中调用自身。在递归的过程中&#xff0c;程序会不断地将自身的执行过程压入调用栈中&#xff0c;直到满足某个条件结束递归调用并开始返回。递归算法常用于解决一些具有递归结构的问题&#xff0c;比如树、图、排序等。递归算法可以…

5.controller部署nova服务

nova 服务是 OpenStack service 计算服务&#xff0c;负责维护和管理云环境的计算资源&#xff1b; 例如&#xff1a; 接收客户端请求需要的计算资源&#xff1b; 确定实例在哪个物理机上创建&#xff1b; 通过虚机化的方式将实例启动运行等工作。 controller节点 在安装和配…

JAVA为什么要面向对象

JAVA是一个面向对象的语言 ok&#xff0c;我们开始&#xff0c;用了那么久的java&#xff0c;看了那么多代码&#xff0c;你是否懂得了面向对象&#xff0c;今天我们的第一个问题就是&#xff0c;为什么java要面向对象&#xff0c;要解释为啥要面向对象&#xff0c;我们首先要…

Python selenium自动化测试模型图解

1、线性测试 优势&#xff1a;每一个脚本都是完整独立的&#xff0c;每一个脚本对应一个测试用例 缺点&#xff1a;开发成本高&#xff0c;会有重复操作重复脚本&#xff1b;维护成本也高&#xff0c;修改重复操作的脚本时&#xff0c;要逐一进行修改。 2、模块化驱动测试 …