当前位置: 首页 > news >正文

【开源】2024最新python豆瓣电影数据爬虫+可视化分析项目

项目介绍

【开源】项目基于python+pandas+flask+mysql等技术实现豆瓣电影数据获取及可视化分析展示,觉得有用的朋友可以来个一键三连,感谢!!!

项目演示

【开源】2024最新python豆瓣电影数据爬虫+可视化分析项目

项目截图

  • 首页
    在这里插入图片描述
  • 列表页
    在这里插入图片描述
  • 爬虫演示
    在这里插入图片描述

项目地址

https://github.com/mudfish/python-douban-view

项目结构

在这里插入图片描述

核心模块

电影爬虫


"""
异步并发爬虫
"""# 本次运行获取的最大页数
MAX_PAGES = 5
# 进度控制文件
PAGE_PROGRESS_FILE = "page_progress.json"
# 电影类型
MOVIE_TYPES = ["剧情", "喜剧", "动作", "爱情", "科幻", "动画"]
# CSV文件名
CSV_NAME = "movie_data.csv"
# CSV头
CSV_HEADS = ["id","movie_id","title","year","directors","casts","rating","cover","country","summary","types","lang","release_date","time","url",
]
# 上映日期匹配正则,剔除非数字和-
RELEASE_DATE_REMOVE_RE = r"[^0-9-]"engine = create_engine("mysql+pymysql://root:123456@127.0.0.1:3306/db_douban")def get_id():return str(random.randint(1, 100000000)) + str(time.time()).split(".")[1].strip()class Spider:def __init__(self):self.movie_page_url = "https://m.douban.com/rexxar/api/v2/movie/recommend?"self.movie_detail_url = "https://movie.douban.com/subject/{}/"self.headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36","Referer": "https://movie.douban.com/explore",}self.movie_types = MOVIE_TYPESself.page_progress = {}# 需要抓取的页面数self.total_pages = 0self.completed_pages = 0self.global_progress_bar = Nonedef init(self):# 每次跑之前,先删除之前的csv文件if os.path.exists(CSV_NAME):os.remove(CSV_NAME)with open(CSV_NAME, "w", newline="", encoding="utf-8") as writer_f:writer = csv.writer(writer_f)writer.writerow(CSV_HEADS)def load_page_progress(self):if os.path.exists(PAGE_PROGRESS_FILE):with open(PAGE_PROGRESS_FILE, "r", encoding="utf-8") as f:# 判断文件内容是否为空if os.stat(PAGE_PROGRESS_FILE).st_size == 0:# 初始化页面进度print("初始化页面进度")self.page_progress = {}self.save_page_progress()else:self.page_progress = json.load(f)def save_page_progress(self):with open(PAGE_PROGRESS_FILE, "w", encoding="utf-8") as f:json.dump(self.page_progress, f, ensure_ascii=False)async def get_movie_pages(self, session, type_name):start_page = self.page_progress.get(type_name, 1)if start_page <= MAX_PAGES:for page in range(start_page, MAX_PAGES + 1):# print(f'{type_name}第{page}页:')start_time = time.time()params = {"start": (page - 1) * 20, "count": 10, "tags": type_name}try:async with session.get(self.movie_page_url, headers=self.headers, params=params) as resp:resp.raise_for_status()respJson = await resp.json()movie_list = respJson["items"]for i, m in enumerate(movie_list):if m["type"] == "movie":await self.process_movie(session, m)# progress_bar.update(round(1/len(movie_list)))self.page_progress[type_name] = page + 1# 记录进度self.save_page_progress()# 刷新全局进度self.update_global_progress()except Exception as e:print(f"处理:{type_name}{page}页失败: {e}")traceback.print_exc()continueasync def process_movie(self, session, movie):movie_data = []movie_data.append(get_id())movie_data.append(movie["id"])movie_data.append(movie["title"])movie_data.append(movie["year"])async with session.get(self.movie_detail_url.format(movie["id"]), headers=self.headers) as resp:resp.raise_for_status()html_text = await resp.text()path = etree.HTML(html_text)# 导演movie_data.append(",".join(path.xpath('//a[@rel="v:directedBy"]/text()')))# 主演movie_data.append(",".join(path.xpath('//a[@rel="v:starring"]/text()')))# 评分movie_data.append(path.xpath('//strong[@property="v:average"]/text()')[0])# 封面movie_data.append(path.xpath('//img[@rel="v:image"]/@src')[0])# 国家movie_data.append(path.xpath('//span[contains(text(),"制片国家")]/following-sibling::br[1]/preceding-sibling::text()[1]')[0].replace(" / ", ","))# 摘要movie_data.append(path.xpath('//span[@property="v:summary"]/text()')[0].strip())# 类型movie_data.append(",".join(path.xpath('//div[@id="info"]/span[@property="v:genre"]/text()')))# 语言movie_data.append(path.xpath('//span[contains(text(),"语言")]/following-sibling::br[1]/preceding-sibling::text()[1]')[0])# 上映日期movie_data.append(re.sub(RELEASE_DATE_REMOVE_RE,"",path.xpath('//span[@property="v:initialReleaseDate"]/text()')[0][:10],))# 时长(空处理)# print(movie["id"])movie_time = path.xpath('//span[@property="v:runtime"]/text()')if len(movie_time) > 0:movie_data.append(movie_time[0])else:movie_data.append("")# urlmovie_data.append(self.movie_detail_url.format(movie["id"]))self.save_to_csv(movie_data)def save_to_csv(self, row):with open(CSV_NAME, "a", newline="", encoding="utf-8") as f:writer = csv.writer(f)writer.writerow(row)def clean_csv(self):print("===========清理数据============")df = pd.read_csv(CSV_NAME, encoding="utf-8")df.drop_duplicates(subset=["movie_id"], keep="first", inplace=True)print("存储到数据库...")df.to_sql("tb_movie", con=engine, index=False, if_exists="append")print("清理重复数据...")engine.connect().execute(text("delete t1 from tb_movie t1 inner join (select min(id) as id,movie_id from tb_movie group by movie_id having count(*) > 1) t2 on t1.movie_id=t2.movie_id where t1.id>t2.id"))def update_global_progress(self):self.completed_pages += 1# print(self.completed_pages)self.global_progress_bar.update(1)self.global_progress_bar.refresh()async def run(self):self.init()self.load_page_progress()# self.total_pages = MAX_PAGES*len(MOVIE_TYPES) - sum(self.page_progress.get(type_name, 1) for type_name in MOVIE_TYPES)for type_name in MOVIE_TYPES:if MAX_PAGES > self.page_progress.get(type_name, 1):self.total_pages += MAX_PAGES + 1 - self.page_progress.get(type_name, 1)print(self.total_pages)if self.total_pages > 0:self.global_progress_bar = tqdm(total=self.total_pages, desc="progress", unit="page", colour="GREEN")async with aiohttp.ClientSession() as session:tasks = [self.get_movie_pages(session, type_name)for type_name in self.movie_types]await asyncio.gather(*tasks)# 请求结束后,清空页面进度# self.page_progress = {}# self.save_page_progress()self.global_progress_bar.close()self.clean_csv()if __name__ == "__main__":loop = asyncio.get_event_loop()spider = Spider()loop.run_until_complete(spider.run())

电影可视化

接口代码

from flask import Flask, render_template, request, redirect, url_for, session
from utils import db_queryapp = Flask(__name__)
app.secret_key = "mysessionkey"# 统一请求拦截
@app.before_request
def before_request():# 利用正则匹配,如果/static开头和/login, /logout,/register的请求,则不拦截;其他的判断是否已登录if (request.path.startswith("/static")or request.path == "/login"or request.path == "/logout"or request.path == "/register"):return# 如果没有登录,则跳转到登录页面if not session.get("login_username"):return redirect(url_for("login"))# 首页
@app.route("/")
def index():# 获取电影统计数据movie_stats = db_query.fetch_movie_statistics()# 获取电影分类统计movie_type_distribution = db_query.fetch_movie_type_distribution()# 获取电影评分统计movie_rating_distribution = db_query.fetch_movie_rating_distribution()print(movie_rating_distribution)return render_template("index.html",login_username=session.get("login_username"),movie_stats=movie_stats,movie_type_distribution=movie_type_distribution,movie_rating_distribution=movie_rating_distribution,)# 登录
@app.route("/login", methods=["GET", "POST"])
def login():if request.method == "POST":req_params = dict(request.form)# 判断用户名密码是否正确sql = "SELECT * FROM `tb_user` WHERE `username` = %s AND `password` = %s"params = (req_params["username"], req_params["password"])if len(db_query.query(sql, params)) > 0:# 存储sessionsession["login_username"] = req_params["username"]return redirect(url_for("index"))else:return render_template("error.html",error="用户名或密码错误",)elif request.method == "GET":return render_template("login.html")# 退出
@app.route("/logout")
def logout():session.pop("login_username", None)return redirect(url_for("index"))# 注册
@app.route("/register", methods=["GET", "POST"])
def register():if request.method == "POST":req_params = dict(request.form)if req_params["password"] == req_params["password_confirm"]:# 判断是否已存在该用户名sql = "SELECT * FROM `tb_user` WHERE `username` = %s"params = (req_params["username"],)result = db_query.query(sql, params)if len(result) > 0:return render_template("error.html",error="用户名已存在",)sql = "INSERT INTO `tb_user` (`username`, `password`) VALUES (%s, %s)"params = (req_params["username"],req_params["password"],)db_query.query(sql, params, db_query.QueryType.NO_SELECT)return redirect(url_for("login"))else:return render_template("error.html",error="两次密码输入不一致",)elif request.method == "GET":return render_template("register.html")@app.route("/list")
def movie_list():# 查询数据库获取电影列表movies = db_query.fetch_movie_list()  # 假设此函数返回一个包含电影信息的列表# 渲染并返回list.html,同时传递movies数据return render_template("list.html", login_username=session.get("login_username"), movies=movies)@app.errorhandler(404)
def page_not_found(error):return render_template("404.html"), 404@app.errorhandler(500)
def system_error(error):return render_template("500.html"), 500if __name__ == "__main__":# 静态文件缓存自动刷新app.jinja_env.auto_reload = Trueapp.run(host="127.0.0.1", port=8002, debug=True)

首页

<!DOCTYPE html>
<html lang="en"><head><meta charset="utf-8" /><meta http-equiv="X-UA-Compatible" content="IE=edge" /><metaname="viewport"content="width=device-width, initial-scale=1, shrink-to-fit=no"/><meta name="description" content="" /><meta name="author" content="" /><title>首页</title><!-- Custom fonts for this template--><linkhref="/static/vendor/fontawesome-free/css/all.min.css"rel="stylesheet"type="text/css"/><linkhref="https://fonts.googleapis.com/css?family=Nunito:200,200i,300,300i,400,400i,600,600i,700,700i,800,800i,900,900i"rel="stylesheet"/><!-- Custom styles for this template--><link href="/static/css/sb-admin-2.min.css" rel="stylesheet" /></head><body id="page-top"><!-- Page Wrapper --><div id="wrapper"><!-- Sidebar --><ulclass="navbar-nav bg-gradient-primary sidebar sidebar-dark accordion"id="accordionSidebar"><!-- Sidebar - Brand --><aclass="sidebar-brand d-flex align-items-center justify-content-center"href="index.html"><div class="sidebar-brand-icon rotate-n-15"><i class="fas fa-laugh-wink"></i></div><div class="sidebar-brand-text mx-3">豆瓣电影可视化</div></a><!-- Divider --><hr class="sidebar-divider my-0" /><!-- Nav Item - Dashboard --><li class="nav-item active"><a class="nav-link" href="/"><i class="fas fa-fw fa-tachometer-alt"></i><span>首页</span></a></li><!-- 列表 --><li class="nav-item"><a class="nav-link" href="/list"><i class="fas fa-fw fa-table"></i><span>电影列表</span></a></li><!-- Divider --><hr class="sidebar-divider d-none d-md-block" /><!-- Sidebar Toggler (Sidebar) --><div class="text-center d-none d-md-inline"><button class="rounded-circle border-0" id="sidebarToggle"></button></div></ul><!-- End of Sidebar --><!-- Content Wrapper --><div id="content-wrapper" class="d-flex flex-column"><!-- Main Content --><div id="content"><!-- Topbar --><navclass="navbar navbar-expand navbar-light bg-white topbar mb-4 static-top shadow"><!-- Sidebar Toggle (Topbar) --><buttonid="sidebarToggleTop"class="btn btn-link d-md-none rounded-circle mr-3"><i class="fa fa-bars"></i></button><!-- Topbar Search --><!-- <form class="d-none d-sm-inline-block form-inline mr-auto ml-md-3 my-2 my-md-0 mw-100 navbar-search"><div class="input-group"><input type="text" class="form-control bg-light border-0 small" placeholder="Search for..." aria-label="Search" aria-describedby="basic-addon2"><div class="input-group-append"><button class="btn btn-primary" type="button"><i class="fas fa-search fa-sm"></i></button></div></div></form> --><!-- Topbar Navbar --><ul class="navbar-nav ml-auto"><div class="topbar-divider d-none d-sm-block"></div><!-- Nav Item - User Information --><li class="nav-item dropdown no-arrow"><aclass="nav-link dropdown-toggle"href="#"id="userDropdown"role="button"data-toggle="dropdown"aria-haspopup="true"aria-expanded="false"><span class="mr-2 d-none d-lg-inline text-gray-600 small">{{login_username}}</span><imgclass="img-profile rounded-circle"src="/static/img/avatar.png"/></a><!-- Dropdown - User Information --><divclass="dropdown-menu dropdown-menu-right shadow animated--grow-in"aria-labelledby="userDropdown"><aclass="dropdown-item"href="#"data-toggle="modal"data-target="#logoutModal"><iclass="fas fa-sign-out-alt fa-sm fa-fw mr-2 text-gray-400"></i>Logout</a></div></li></ul></nav><!-- End of Topbar --><!-- Begin Page Content --><div class="container-fluid"><!-- Page Heading --><!-- <div class="d-sm-flex align-items-center justify-content-between mb-4"><h1 class="h3 mb-0 text-gray-800">Dashboard</h1><a href="#" class="d-none d-sm-inline-block btn btn-sm btn-primary shadow-sm"><i class="fas fa-download fa-sm text-white-50"></i> Generate Report</a></div> --><!-- Content Row --><div class="row"><!-- Earnings (Monthly) Card Example --><div class="col-xl-3 col-md-6 mb-4"><div class="card border-left-primary shadow h-100 py-2"><div class="card-body"><div class="row no-gutters align-items-center"><div class="col mr-2"><divclass="font-weight-bold text-primary text-uppercase mb-1">电影总数</div><div class="h5 mb-0 font-weight-bold text-gray-800">{{ movie_stats['total_movies'] }}</div></div><div class="col-auto"><i class="fas fa-calendar fa-2x text-gray-300"></i></div></div></div></div></div><!-- Earnings (Monthly) Card Example --><div class="col-xl-3 col-md-6 mb-4"><div class="card border-left-success shadow h-100 py-2"><div class="card-body"><div class="row no-gutters align-items-center"><div class="col mr-2"><divclass="font-weight-bold text-success text-uppercase mb-1">电影最高评分</div><div class="h5 mb-0 font-weight-bold text-gray-800">{{ movie_stats['highest_rating'] }}</div></div><div class="col-auto"><i class="fas fa-dollar-sign fa-2x text-gray-300"></i></div></div></div></div></div><!-- Earnings (Monthly) Card Example --><div class="col-xl-3 col-md-6 mb-4"><div class="card border-left-info shadow h-100 py-2"><div class="card-body"><div class="row no-gutters align-items-center"><div class="col mr-2"><divclass="font-weight-bold text-info text-uppercase mb-1">出演最多演员</div><div class="row no-gutters align-items-center"><div class="col-auto"><divclass="h5 mb-0 mr-3 font-weight-bold text-gray-800">{{ movie_stats['most_popular_cast'] }}</div></div><div class="col"><div class="progress progress-sm mr-2"><divclass="progress-bar bg-info"role="progressbar"style="width: 50%"aria-valuenow="50"aria-valuemin="0"aria-valuemax="100"></div></div></div></div></div><div class="col-auto"><iclass="fas fa-clipboard-list fa-2x text-gray-300"></i></div></div></div></div></div><!-- Pending Requests Card Example --><div class="col-xl-3 col-md-6 mb-4"><div class="card border-left-warning shadow h-100 py-2"><div class="card-body"><div class="row no-gutters align-items-center"><div class="col mr-2"><divclass="font-weight-bold text-warning text-uppercase mb-1">制片最多国家</div><div class="h5 mb-0 font-weight-bold text-gray-800">{{ movie_stats['most_common_country'] }}</div></div><div class="col-auto"><i class="fas fa-comments fa-2x text-gray-300"></i></div></div></div></div></div></div><!-- Content Row --><div class="row"><!-- Area Chart --><div class="col-xl-6 col-lg-6"><div class="card shadow mb-4"><!-- Card Header - Dropdown --><divclass="card-header py-3 d-flex flex-row align-items-center justify-content-between"><h6 class="m-0 font-weight-bold text-primary">电影分类统计</h6></div><!-- Card Body --><div class="card-body"><divid="movie_type_chart"style="width: 100%; height: 450px"></div><!-- <div class="chart-area"></div> --></div></div></div><!-- Line Chart --><div class="col-xl-6 col-lg-6"><div class="card shadow mb-4"><!-- Card Header - Dropdown --><divclass="card-header py-3 d-flex flex-row align-items-center justify-content-between"><h6 class="m-0 font-weight-bold text-primary">电影评分统计</h6><div class="dropdown no-arrow"><aclass="dropdown-toggle"href="#"role="button"id="dropdownMenuLink"data-toggle="dropdown"aria-haspopup="true"aria-expanded="false"><iclass="fas fa-ellipsis-v fa-sm fa-fw text-gray-400"></i></a><divclass="dropdown-menu dropdown-menu-right shadow animated--fade-in"aria-labelledby="dropdownMenuLink"><div class="dropdown-header">Dropdown Header:</div><a class="dropdown-item" href="#">Action</a><a class="dropdown-item" href="#">Another action</a><div class="dropdown-divider"></div><a class="dropdown-item" href="#">Something else here</a></div></div></div><!-- Card Body --><div class="card-body"><divid="movie_score_chart"style="width: 100%; height: 450px"></div></div></div></div></div><!-- Content Row --></div><!-- /.container-fluid --></div><!-- End of Main Content --><!-- Footer --><footer class="sticky-footer bg-white"><div class="container my-auto"><div class="copyright text-center my-auto"><span>@Laoxu Open Source.<atarget="_blank"href="https://github.com/mudfish">Github</a></span></div></div></footer><!-- End of Footer --></div><!-- End of Content Wrapper --></div><!-- End of Page Wrapper --><!-- Scroll to Top Button--><a class="scroll-to-top rounded" href="#page-top"><i class="fas fa-angle-up"></i></a><!-- Logout Modal--><divclass="modal fade"id="logoutModal"tabindex="-1"role="dialog"aria-labelledby="exampleModalLabel"aria-hidden="true"><div class="modal-dialog" role="document"><div class="modal-content"><div class="modal-header"><h5 class="modal-title" id="exampleModalLabel">Ready to Leave?</h5><buttonclass="close"type="button"data-dismiss="modal"aria-label="Close"><span aria-hidden="true">×</span></button></div><!-- <div class="modal-body">Select "Logout" below if you are ready to end your current session.</div> --><div class="modal-footer"><buttonclass="btn btn-secondary"type="button"data-dismiss="modal">Cancel</button><a class="btn btn-primary" href="/logout">Logout</a></div></div></div></div><!-- Bootstrap core JavaScript--><script src="/static/vendor/jquery/jquery.min.js"></script><script src="/static/vendor/bootstrap/js/bootstrap.bundle.min.js"></script><!-- Core plugin JavaScript--><script src="/static/vendor/jquery-easing/jquery.easing.min.js"></script><!-- Custom scripts for all pages--><script src="/static/js/sb-admin-2.min.js"></script><!-- Page level plugins --><script src="/static/vendor/chart.js/Chart.min.js"></script><!-- Page level custom scripts --><script src="/static/js/demo/chart-area-demo.js"></script><script src="/static/js/demo/chart-pie-demo.js"></script><script src="/static/js/echarts.min.js"></script><script>var chartDom = document.getElementById("movie_type_chart");var myChart = echarts.init(chartDom);var option;var movieTypeData = {{ movie_type_distribution|tojson }};// console.log(movieTypeData)option = {title: {text: "",subtext: "来源:豆瓣数据",left: "center",},tooltip: {trigger: "item",},legend: {orient: "vertical",left: "left",},series: [{name: "Access From",type: "pie",radius: "50%",data: movieTypeData,emphasis: {itemStyle: {shadowBlur: 10,shadowOffsetX: 0,shadowColor: "rgba(0, 0, 0, 0.5)",},},},],};option && myChart.setOption(option);</script><script>var chartDom = document.getElementById("movie_score_chart");var myChart = echarts.init(chartDom);var option;var ratingData = {{ movie_rating_distribution|tojson }};console.log(ratingData)option = {title: {text: "",subtext: "来源:豆瓣数据",left: "center",},xAxis: {type: "category",boundaryGap: false,data: ratingData.map(item => item[0]),},yAxis: {type: "value",},series: [{data: ratingData.map(item => item[1]),type: "line",areaStyle: {},},],tooltip: {trigger: 'axis', //坐标轴触发,主要在柱状图,折线图等会使用类目轴的图表中使用axisPointer: {// 坐标轴指示器,坐标轴触发有效type: 'shadow' // 默认为直线,可选为:'line' | 'shadow'}},};option && myChart.setOption(option);</script></body>
</html>

相关文章:

【开源】2024最新python豆瓣电影数据爬虫+可视化分析项目

项目介绍 【开源】项目基于pythonpandasflaskmysql等技术实现豆瓣电影数据获取及可视化分析展示&#xff0c;觉得有用的朋友可以来个一键三连&#xff0c;感谢&#xff01;&#xff01;&#xff01; 项目演示 【开源】2024最新python豆瓣电影数据爬虫可视化分析项目 项目截图…...

[JDK工具-5] jinfo jvm配置信息工具

文章目录 1. 介绍2. 打印所有的jvm标志信息 jinfo -flags pid3. 打印指定的jvm参数信息 jinfo -flag InitialHeapSize pid4. 启用或者禁用指定的jvm参数 jinfo -flags [|-]HeapDumpOnOutOfMemoryError pid5. 打印系统参数信息 jinfo -sysprops pid6. 打印以上所有配置信息 jinf…...

【Linux系统编程】进程概念、进程排队、进程标识符、进程状态

目录 什么是进程&#xff1f; 浅谈进程排队 简述进程属性 进程属性之进程标识符 进程操作之进程创建 初识fork fork返回值 原理角度理解fork fork的应用 进程属性之进程状态 再谈进程排队 进程状态 运行状态 阻塞状态 挂起状态 Linux下的进程状态 “R”(运行状…...

Java与GO语言对比分析

你是不是总听到go与java种种对比&#xff0c;其中在高并发的服务器端应用场景会有人推荐你使用go而不是 java。 那我们就从两者运行原理和基本并发设计来对比分析&#xff0c;看看到底怎么回事。 运行原理对比 java java 中 jdk 已经帮我们屏蔽操作系统区别。 只要我们下载并…...

Linux文件系统原理

Linux文件系统 冯诺依曼在1945年提出计算机的五大组成部分 运算器&#xff1a;CPU 控制器&#xff1a;CPU 存储器&#xff1a;内存和硬盘 输入设备&#xff1a;鼠标、硬盘 输出设备&#xff1a;显示器一、硬盘结构 机械硬盘结构 扇区&#xff1a;硬盘的最小存储单位&#xff…...

初识Spring Cache:如何简化你的缓存处理?

文章目录 1、Spring Cache介绍2、 常用注解3、 使用案例 1、Spring Cache介绍 Spring Cache 是一个框架&#xff0c;实现了基于注解的缓存功能&#xff0c;只需要简单地加一个注解&#xff0c;就能实现缓存功能。 Spring Cache 提供了一层抽象&#xff0c;底层可以切换不同的…...

攻防世界[GoodRe]

攻防世界[GoodRe] 学到知识&#xff1a; 逆向的精髓&#xff1a;三分懂&#xff0c;七分蒙。TEA 算法快速识别&#xff08;蒙&#xff09;&#xff1a; 数据处理的形式&#xff1a;进入加密时的数据和加密结束后的数据&#xff0c;处理时数据的分组等等&#xff0c;都能用来…...

IntelliJ IDEA实用插件:轻松生成时序图和类图

IntelliJ IDEA生成时序图、类图 一、SequenceDiagram1.1 插件安装1.2 插件设置1.3 生成时序图 二、PlantUML Integration2.1 插件安装2.2 插件设置2.3 生成类图 在软件建模课程的学习中&#xff0c;大家学习过多种图形表示方法&#xff0c;这些图形主要用于软件产品设计。在传统…...

SpringBoot + Mybatis-Plus中乐观锁实现

悲观锁 悲观锁是一种悲观思想&#xff0c;它认为数据很可能会被别人所修改 所以总会对数据进行上锁&#xff0c;读操作和写操作都会上锁&#xff0c;性能较低&#xff0c;使用较少&#xff01; 乐观锁 乐观锁是一种乐观思想&#xff0c;它认为数据并不一定会被别人所修改 所以…...

设计模式深度解析:分布式与中心化,IT界两大巨头“华山论剑”

​&#x1f308; 个人主页&#xff1a;danci_ &#x1f525; 系列专栏&#xff1a;《设计模式》《MYSQL应用》 &#x1f4aa;&#x1f3fb; 制定明确可量化的目标&#xff0c;坚持默默的做事。 ✨IT界的两大巨头交锋✨ &#x1f44b; 在IT界的广阔天地中&#xff0c;有两座…...

转行一年了

关注、星标公众号&#xff0c;直达精彩内容 ID&#xff1a;技术让梦想更伟大 整理&#xff1a;李肖遥 来公司一年了。 说是转行其实还是在半导体行业&#xff0c;熟悉我的朋友知道 &#xff0c;我在18年开始进入半导体行业&#xff0c;那个时候想着行业很重要&#xff0c;站对了…...

【LeetCode 151】反转字符串中的单词

1. 题目 2. 分析 这题要是用Python写&#xff0c;就非常简单了。 3. 代码 class Solution:def reverseWords(self, s: str) -> str:s " ".join(reversed(s.strip().split()))return s...

Behind the Code:Polkadot 如何重塑 Web3 未来

2024 年 5 月 17 日 Polkadot 生态 Behind the Code 第二季第一集 《创造 Web3 的未来》正式上线。第一集深入探讨了 Polkadot 和 Web3 技术在解决数字身份、数据所有权和去中心化治理方面的巨大潜力。 &#x1f50d; 查看完整视频&#xff1a; https://youtu.be/_gP-M5nUidc?…...

for循环里如果std::pair的类型写不对,可能会造成性能损失

第一版 std::map<int, int> t;t.emplace(1, 1);for (const std::pair<int,int>& data : t){int i 0;std::ignore i;}中间留一些空格&#xff0c;是因为ms在调试的时候&#xff0c;尤其是模板比较多的时候&#xff0c;经常断点的行号有问题。比如第5行的断点&…...

【Linux】Linux的基本指令_2

文章目录 二、基本指令8. man9. nano 和 cat10. cp11. mv12. echo 和 > 和 >> 和 <13. more 和 less14. head 和 tail 和 | 未完待续 二、基本指令 8. man Linux的命令有很多参数&#xff0c;我们不可能全记住&#xff0c;我们可以通过查看联机手册获取帮助。访问…...

Effective C++(3)

3.资源管理 条款13&#xff1a;以对象管理资源 以对象管理资源对于传统的堆资源管理&#xff0c;我们需要使用成对的new和delete&#xff0c;这样若忘记delete就会造成内存泄露。因此&#xff0c;我们应尽可能以对象管理资源&#xff0c;并采用RAII&#xff08;Resource Acqu…...

自定义RedisTemplate序列化器

大纲 RedisSerializerFastJsonRedisSerializer自定义二进制序列化器总结代码 在《RedisTemplate保存二进制数据的方法》一文中&#xff0c;我们将Java对象通过《使用java.io库序列化Java对象》中介绍的方法转换为二进制数组&#xff0c;然后保存到Redis中。实际可以通过定制Red…...

Flutter 中的 CupertinoContextMenuAction 小部件:全面指南

Flutter 中的 CupertinoContextMenuAction 小部件&#xff1a;全面指南 在 Flutter 中&#xff0c;CupertinoContextMenuAction 是一个专门用于构建 iOS 风格的上下文菜单选项的组件。它为用户提供了一种便捷的方式来执行与特定项目相关的操作&#xff0c;例如在列表项上长按可…...

Element-Ul快速入门

引言 Element UI是一个vue.js的桌面UI库。它提供了一套丰富、灵活和实用的UI组件&#xff0c;使开发者能以最少的时间和代码量完成复杂的界面设计。本文将会介明如何快速上手Element UI。 安装和基本使用 首先&#xff0c;你需要在你的项目中安装Element UI。如果你已经安装…...

Django的模型层——2模型实例

1. 类的属性 objects&#xff1a;是Manager类型的对象&#xff0c;用于与数据库进行交互 当定义模型类时没有指定管理器&#xff0c;则Django会为模型类提供一个名为objects的管理器 支持明确指定模型类的管理器 class BookInfo(models.Model):...books models.Manager()当为…...

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)

题目&#xff1a;3442. 奇偶频次间的最大差值 I 思路 &#xff1a;哈希&#xff0c;时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况&#xff0c;哈希表这里用数组即可实现。 C版本&#xff1a; class Solution { public:int maxDifference(string s) {int a[26]…...

深入浅出Asp.Net Core MVC应用开发系列-AspNetCore中的日志记录

ASP.NET Core 是一个跨平台的开源框架&#xff0c;用于在 Windows、macOS 或 Linux 上生成基于云的新式 Web 应用。 ASP.NET Core 中的日志记录 .NET 通过 ILogger API 支持高性能结构化日志记录&#xff0c;以帮助监视应用程序行为和诊断问题。 可以通过配置不同的记录提供程…...

Linux链表操作全解析

Linux C语言链表深度解析与实战技巧 一、链表基础概念与内核链表优势1.1 为什么使用链表&#xff1f;1.2 Linux 内核链表与用户态链表的区别 二、内核链表结构与宏解析常用宏/函数 三、内核链表的优点四、用户态链表示例五、双向循环链表在内核中的实现优势5.1 插入效率5.2 安全…...

家政维修平台实战20:权限设计

目录 1 获取工人信息2 搭建工人入口3 权限判断总结 目前我们已经搭建好了基础的用户体系&#xff0c;主要是分成几个表&#xff0c;用户表我们是记录用户的基础信息&#xff0c;包括手机、昵称、头像。而工人和员工各有各的表。那么就有一个问题&#xff0c;不同的角色&#xf…...

2021-03-15 iview一些问题

1.iview 在使用tree组件时&#xff0c;发现没有set类的方法&#xff0c;只有get&#xff0c;那么要改变tree值&#xff0c;只能遍历treeData&#xff0c;递归修改treeData的checked&#xff0c;发现无法更改&#xff0c;原因在于check模式下&#xff0c;子元素的勾选状态跟父节…...

从零开始打造 OpenSTLinux 6.6 Yocto 系统(基于STM32CubeMX)(九)

设备树移植 和uboot设备树修改的内容同步到kernel将设备树stm32mp157d-stm32mp157daa1-mx.dts复制到内核源码目录下 源码修改及编译 修改arch/arm/boot/dts/st/Makefile&#xff0c;新增设备树编译 stm32mp157f-ev1-m4-examples.dtb \stm32mp157d-stm32mp157daa1-mx.dtb修改…...

uniapp微信小程序视频实时流+pc端预览方案

方案类型技术实现是否免费优点缺点适用场景延迟范围开发复杂度​WebSocket图片帧​定时拍照Base64传输✅ 完全免费无需服务器 纯前端实现高延迟高流量 帧率极低个人demo测试 超低频监控500ms-2s⭐⭐​RTMP推流​TRTC/即构SDK推流❌ 付费方案 &#xff08;部分有免费额度&#x…...

安卓基础(aar)

重新设置java21的环境&#xff0c;临时设置 $env:JAVA_HOME "D:\Android Studio\jbr" 查看当前环境变量 JAVA_HOME 的值 echo $env:JAVA_HOME 构建ARR文件 ./gradlew :private-lib:assembleRelease 目录是这样的&#xff1a; MyApp/ ├── app/ …...

JVM虚拟机:内存结构、垃圾回收、性能优化

1、JVM虚拟机的简介 Java 虚拟机(Java Virtual Machine 简称:JVM)是运行所有 Java 程序的抽象计算机,是 Java 语言的运行环境,实现了 Java 程序的跨平台特性。JVM 屏蔽了与具体操作系统平台相关的信息,使得 Java 程序只需生成在 JVM 上运行的目标代码(字节码),就可以…...

C语言中提供的第三方库之哈希表实现

一. 简介 前面一篇文章简单学习了C语言中第三方库&#xff08;uthash库&#xff09;提供对哈希表的操作&#xff0c;文章如下&#xff1a; C语言中提供的第三方库uthash常用接口-CSDN博客 本文简单学习一下第三方库 uthash库对哈希表的操作。 二. uthash库哈希表操作示例 u…...