Python三百行代码实现一简约个人博客网站(全网最小巧)

这是全互联网最小巧的博客,没有比这更小的了。虽然小巧,但功能一点儿也不弱,支持文章的分页展示,文章表格,图片和代码语法高亮。文章无限制分类,访问量统计,按时间和按点击量排序,展示最新文章,最热文章,文章留言评论等功能。

前言

如果你也想拥有一个属于自己的个性博客,这种尝试将大幅降低准入门槛,让你看到实现一个个人博客网站是多么的简单。其它的又是建库建表的,或是需要登录管理后台管理,我还是觉得不够简单好用。

用这种写好的markdown文档的形式,你可以直接把markdown笔记变成动态的博客展示出来。后续可基于微信小程序做个入口,如果想要发布文章,则直接把编写好的markdown文件提交发送过去就可以啦,操作使用上更加简单和快捷。这才应该是现在博客该有的特色和创新,原有的旧的登录网站后台编辑和使用的方式,太落后了。

况且使用这种方式还有个好处,可以方便多人同时使用。比如可以在公司内部搭建一个公共博客平台,做个简单入口界面,让每个人都可以往上面提交文档,这也是个不错的内部方案交流平台和技术分享平台。相比传统word文档的方式优点很多,方便文档的查看、归档和线上展示及分享,连留言评论都有啦。

项目开源地址:

tiny-blog: 极小的个人博客,虽然很小,但是很全。使用python+flask+html实现。

体验地址:

我的个人博客

实现原理

其实就是一个基于markdown的轻量级博客,需要按一定格式编写好markdown文件,提交到后台服务。当用户访问网页时由后台读取文件内容并经由流行的markdown-it组件渲染。

后台使用python的flask框架,整个代码仅三百多行。相当的小巧,很容易根据需要修改源码去增加一些其他的功能。当然一个css或js文件都不可能这么短,这里仅指的是后台代码。网页使用了流行的markdown-it(MarkDown渲染),highlight.js(语法高亮)和mermaid.js(画流程图、时序图等的js库)组件。留言评论功能,使用比较火的Valine博客评论系统。

网站模板我是从素材火网站上找了一个好看的博客网站模板。如果你有中意的其他博客网站模板,也可以很容易的改造过来用。文末介绍和分享几个好看的博客模板。

效果展示:

Flask介绍

Flask是一个轻量级的Python Web框架,用于构建Web应用程序和API。它基于Werkzeug工具箱和Jinja2模板引擎,并且具有灵活性和可扩展性。

Flask提供了一些基本的功能,例如路由、请求和响应处理、会话管理等,同时支持各种扩展,可以轻松添加身份验证、数据库集成、邮件发送等功能。由于其简单的学习曲线和活跃的社区支持,Flask已成为最受欢迎的Python Web框架之一。

源码实现

源码实现很简单,仅有三个文件,总代码量三百多行。为了提高访问速度,设计了一种基于字典map的简单数据结构。只有应用启动时加载一次文件,后续文章访问直接从字典数据中取数据,避免每次访问都读文件,提高访问效率。为了方便的查看数据结构,加载完文件后保存了几个json格式的文件。通过json文件很容易看出来。

main.py

# encoding: utf-8
# author:yangyongzhen
from flask import  Flask,render_template,request,redirect
import articles
import atexit
import json
import sys

app=Flask(__name__,template_folder="templates", static_folder="static", static_url_path="/static")

# 首页
@app.route('/')
def index():
    articles.Stat.totalVisit += 1
    page = 1
    page = request.args.get('page',1,int)
    print(page)
    nums = len(articles.AllArts)
    print(nums)
    allpage = nums / 5
    if nums %5 != 0:
        allpage = int(nums/5) + 1
    print(allpage)

    curArts = articles.AllArts
    if (page * 5) < nums :
        curArts = articles.AllArts[(page-1)*5 : page*5]
    else:
        curArts = articles.AllArts[(page-1)*5 : nums]
    #分页表
    tabs = []
    for i in range(0,allpage):
        print(i)
        tabs.append(i)
    print(tabs)
    return render_template("index.html",arts=curArts,news=articles.NewArts[:9],hots=articles.HotArts[:9],items=articles.ItemList,curPage=page,tab=tabs)  #加入变量传递

@app.route('/about')
def about():
    msg="my name is caojianhua, China up!"
    return render_template("about.html",data=msg)  #加入变量传递

#分类页
@app.route('/items')
def items():
    try:
        id = request.args.get('id')
        print(id)
        allArts = []
        allMaps = articles.ItemMap[id]
        #遍历 hash
        for v in allMaps.values():
           allArts.append(v) 
        #按日期排序
        allArts.sort(key=lambda x: x['date'],reverse=True)
        #print(allArts)
        page = 1
        page = request.args.get('page',1,int)
        print(page)
        nums = len(allArts)
        print(nums)
        allpage = int(nums / 5)
        if nums %5 != 0:
            allpage = int(nums/5) + 1
        print(allpage)
        curArts = allArts
        if (page * 5) < nums :
            curArts = allArts[(page-1)*5 : page*5]
        else:
            curArts = allArts[(page-1)*5 : nums]
        #分页表
        tabs = []
        for i in range(0,allpage):
            #print(i)
            tabs.append(i)
        #print(tabs)
        return render_template("items.html",arts=curArts,item=id,news=articles.NewArts[:9],hots=articles.HotArts[:9],curPage=page,tab=tabs) 
    except Exception as e:
        print("Exception occured")
        print(e)
        return render_template('404.html')

# 文章详情页
@app.route('/article_detail')
def article_detail():
    art = articles.Article("","","","","","","","",0,0)
    item_index = 0
    try:
        id = request.args.get('id')
        #print(id)
        #取出分类
        item = articles.ArtRouteMap[id]['item']
        print(item)
        art = articles.ItemMap[item][id]  
        #art_index  = NewPosts.index(id)
        articles.Stat.artStat[id]['visitCnt'] += 1
        articles.Stat.totalVisit += 1
        articles.ItemMap[item][id]['visitCnt'] = articles.Stat.artStat[id]['visitCnt']
        #print(art)
        #print(item_index)
        #print(art_index)
        return render_template("article_detail.html",data=art,news=articles.NewArts[:9],hots=articles.HotArts[:9] ) 
    except Exception as e:
        print("Exception occured")
        return render_template('404.html')
   
# 说说页面  
@app.route('/moodList')
def moodList():
    msg="my name is caojianhua, China up!"
    return render_template("moodList.html",data=msg) 

# 留言页面 
@app.route('/comment')
def comment():
    msg="my name is caojianhua, China up!"
    return render_template("comment.html",data=msg) 

@app.route('/404')
def error_404():
    print("error_404")
    return render_template("404.html") 

@app.errorhandler(404)
def page_not_found(e):
    print("page_not_found")
    print(e)
    return render_template('404.html'), 404

@app.errorhandler(Exception)
def handle_exception(e):
    # 捕获其他异常
    print("handle_exception")
    print(e)
    return render_template('404.html'), 500
 
def saveData():
    #保存访问量数据       
    with open('statistic.json1', 'w',encoding='utf-8') as f:
        json.dump(articles.Stat.__dict__, f,ensure_ascii=False)
           
# 监控退出时保存统计信息
@atexit.register
def exit_handler():
    print("应用程序退出")
    saveData()

if __name__=="__main__":
    #启动时加载访问量数据
    articles.getPosts()
    
    app.run(port=8000,host="127.0.0.1",debug=False)
    print("over")

articles.py

# encoding: utf-8
# author:yangyongzhen
import glob
import os
import pprint
import hashlib
import json
import statistic

#访问量阅读量统计信息
Stat = statistic.AllStat()

# AllArts 总的文章,(按时间排过序的)
AllArts = []
# NewArts 最新文章
NewArts = []
# HotArts 热门文章
HotArts = []
# 文章分类信息
ItemList = []

ItemMap = {}
ArtRouteMap = {}

#文章信息类定义
class Article(object):
    def __init__(self, id, item, title, date, summary, body, imgFile, author, cmtCnt, visitCnt):
        self.id = id
        self.item = item
        self.title = title
        self.date = date
        self.summary = summary
        self.body = body
        self.imgFile = imgFile
        self.author = author
        self.cmtCnt = cmtCnt
        self.visitCnt = visitCnt
    
    def mPrint(self):
        print(self.id)
        print(self.item)
        print(self.title)
        print(self.date)
        print(self.summary)
        print(self.body)
        print(self.imgFile)
        print(self.author)


class ArticlesData():
    def __init__(self):
        self.item = ""
        self.articlesMap = {}


# ArticleRoute 文章的分类和路径信息
class ArticleRoute:
    def __init__(self, item, name):
        self.item = item
        self.name = name

#文章分类 是个集合类型,无重复元素
class ItemCfg:
    def __init__(self):
        self.items = set()
        
        
def strTrip(src):
    str = src.replace(" ", "")
    str = str.replace("\r", "")
    str = str.replace("\n", "")
    return str


#从文件中读取信息,并返回itemMap,artRouteMap,items
def getPosts():
    global ItemMap,ArtRouteMap,ItemList,NewArts
    # 打开访问量统计JSON文件并读取内容
    with open('statistic.json1', 'r',encoding='utf-8') as file:
        json_data = file.read()
        # 将JSON字符串反序列化为字典对象
        Stat.__dict__ = json.loads(json_data)
        print(Stat.totalVisit)
    # 获取"posts/"目录下的所有文件
    files = glob.glob("posts/*")
    # 按修改日期进行排序
    files = sorted(files, key=lambda x: os.path.getmtime(x))
    articleMap = {}
    itemMap = {}
    artRouteMap = {}
    #文章分类,是个集合类型,无重复
    items = set()
    # 遍历文件列表
    for i, f in enumerate(files):
        #print(i)
        #print(f)

        file = f
        file = os.path.basename(file) # 转换路径分隔符
        print(file)
        file = os.path.splitext(file)[0]  # 移除".md"后缀
        fileread = open(f, 'r',encoding='utf-8').read()
        lines = fileread.split('\n')
        #print(lines)
        title = lines[0].strip()
        date = strTrip(lines[1].strip())
        summary = lines[2].strip()
        imgfile = lines[3].strip()
        id = hashlib.md5(file.encode(encoding='UTF-8'))
        id = id.hexdigest()
        #print(id.hexdigest())
        item = strTrip(lines[4].strip())
        author = lines[5].strip()
        imgfile = strTrip(imgfile)
        body = '\n'.join(lines[6:])  # 获取第6行及以后的行
        ar = ArticleRoute(item, title)
        artRouteMap[id] = ar.__dict__
        visitCnt = 0
        if id in Stat.artStat:
           visitCnt = Stat.artStat[id]['visitCnt']
           #print(visitCnt)
        else:
            Stat.artStat[id] = statistic.ArtStat(title,visitCnt,0).__dict__
        post = Article(id,item,title, date, summary, body, imgfile, author, 0,visitCnt)
        articleMap[id] = post
        items.add(item)
    #json_data = json.dumps(posts,ensure_ascii=False)
    #print(json_data)
    itemList = []
    for itm in items:
        itmMp= {}
        for v in articleMap.values():
            if(v.item == itm):
                itmMp[v.id] = v.__dict__
        itemMap[itm] = itmMp
        itemList.append(itm)
            
        
    #保存为json文件
    with open('Articles.json1', 'w',encoding='utf-8') as f:
        json.dump(itemMap, f,ensure_ascii=False)
        
    with open('artRouteMap.json1', 'w',encoding='utf-8') as f:
        json.dump(artRouteMap, f,ensure_ascii=False)
    itemList.sort()
    
    #遍历字典
    for key, val in itemMap.items():
        for idx,art in val.items():
            AllArts.append(art)
            HotArts.append(art)        
    #按日期排序
    AllArts.sort(key=lambda x: x['date'],reverse=True)
    #按访问量排序
    HotArts.sort(key=lambda x: x['visitCnt'],reverse=True)
    NewArts = AllArts
    ItemList = itemList
    #print((HotArts[0]))
    ItemMap = itemMap
    ArtRouteMap = artRouteMap
    return itemMap,artRouteMap,itemList

if __name__=="__main__":
    p,p1,items = getPosts()
    #print(p)
    print(type(p))
    print(type(p1))
    print(p['go学习笔记'])
    print(p1['3eaf98ad2b949b3f93d16aeaa1f45ab0'])
    print(items)

statistic.py

# encoding: utf-8
# author:yangyongzhen
# 文章和总阅读量统计

#文章访问量统计
#param:名称,访问量,评论量
class ArtStat:
    def __init__(self, title,visitCnt,cmtCnt):
        self.title = title
        self.visitCnt = visitCnt
        self.commentCnt = cmtCnt
  
#总的统计        
class AllStat:
    def __init__(self):
        #总访问量
        self.totalVisit = 0
        self.artStat = {}


if __name__=="__main__":
    pass

如何使用

除了flask,无其它依赖。下载源码,pip install flask安装好依赖。然后python main.py即可运行起来。编写新文章,需要按照特定格式写前面几行。因为文章作者,文章分类和日期等信息,都在一个文件里写的。

文章内容格式如下(test.md):

This is a title!
2020-10-22
你好aaaaaaaasssssssssssssssss! 这是你第一次使用 **Markdown编辑器** 所展示的欢迎页。如果你想学习如何使用Markdown编辑器, 可以仔细阅读这篇文章,了解一下Markdown的基本语法知识。
08.jpg
感悟
yangyongzhen


This is the main post!

# Markdown1!
## Markdown2!
### 欢迎使用Markdown编辑器

Name    | Age
--------|------
Bob     | 27
Alice   | 23

你好! 这是你第一次使用 **Markdown编辑器** 所展示的欢迎页。如果你想学习如何使用Markdown编辑器, 可以仔细阅读这篇文章,了解一下Markdown的基本语法知识。

```golang
package main

import "fmt"

func main() {
	fmt.Println("hello ")
}
```

网页前端小技巧 

导航栏选中高亮

网站头部导航栏根据选择自动高亮显示,代码在silder.js中实现:

var obj=null;
var As=document.querySelector(".w_header_nav").getElementsByTagName('a');
obj = As[0];
for(i=1;i<As.length;i++){if(window.location.href.indexOf(As[i].href)>=0)
obj=As[i];}
console.log(obj)
// 添加class属性
obj.classList.add("active");

返回到顶部

返回到顶部,可复用js代码:

var $backToTopEle=$('<a href="javascript:void(0)" class="Hui-iconfont toTop" title="返回顶部" alt="返回顶部" style="display:none">^^</a>').appendTo($("body")).click(function(){
	$("html, body").animate({ scrollTop: 0 }, 120);
});
var backToTopFun = function() {
	var st = $(document).scrollTop(), winh = $(window).height();
	(st > 0)? $backToTopEle.show(): $backToTopEle.hide();
	/*IE6下的定位*/
	if(!window.XMLHttpRequest){
		$backToTopEle.css("top", st + winh - 166);
	}
};
	$(function(){
		$(window).on("scroll",backToTopFun);
		backToTopFun();
	});

分页显示js代码 :

/* 
*page plugin 1.0 
*/
(function ($) {
  //默认参数
  var defaults = {
    totalPages: 9,//总页数
    liNums: 9,//分页的数字按钮数(建议取奇数)
    activeClass: 'active' ,//active类
    firstPage: '首页',//首页按钮名称
    lastPage: '末页',//末页按钮名称
    prv: '«',//前一页按钮名称
    next: '»',//后一页按钮名称
    hasFirstPage: true,//是否有首页按钮
    hasLastPage: true,//是否有末页按钮
    hasPrv: true,//是否有前一页按钮
    hasNext: true,//是否有后一页按钮
    callBack : function(page){
        //回掉,page选中页数
    }
  };

  //插件名称
  $.fn.Page = function (options) {
    //覆盖默认参数
    var opts = $.extend(defaults, options);
    //主函数
    return this.each(function () {
      var obj = $(this);
      var l = opts.totalPages;
      var n = opts.liNums;
      var active = opts.activeClass;
      var str = '';
      var str1 = '<li><a href="javascript:" class="'+ active +'">1</a></li>';
      if (l > 1&&l < n+1) {
        for (i = 2; i < l + 1; i++) {
          str += '<li><a href="javascript:">' + i + '</a></li>';
        }
      }else if(l > n){
        for (i = 2; i < n + 1; i++) {
          str += '<li><a href="javascript:">' + i + '</a></li>';
        }
      }
      var dataHtml = '';
      if(opts.hasNext){
          dataHtml += '<div class="next fr">' + opts.next + '</div>';
      }
      if(opts.hasLastPage){
          dataHtml += '<div class="last fr">' + opts.lastPage + '</div>';
      }
          dataHtml += '<ul class="pagingUl">' + str1 + str + '</ul>';
      if(opts.hasFirstPage){
          dataHtml += '<div class="first fr">' + opts.firstPage + '</div>';
      }
      if(opts.hasPrv){
          dataHtml += '<div class="prv fr">' + opts.prv + '</div>';
      }
      
      obj.html(dataHtml).off("click");//防止插件重复调用时,重复绑定事件
      
      obj.on('click', '.next', function () {
        var pageshow = parseInt($('.' + active).html());
        var nums,flag;
        var a = n % 2;
        if(a == 0){
          //偶数
          nums = n;
          flag = true;
        }else if(a == 1){
          //奇数
          nums = (n+1);
          flag = false;
        }
        if(pageshow >= l) {
          return;
        }else if(pageshow > 0&&pageshow <= nums/2){
          //最前几项
          $('.' + active).removeClass(active).parent().next().find('a').addClass(active);
        }else if((pageshow > l-nums/2&&pageshow < l&&flag==false)||(pageshow > l-nums/2-1&&pageshow < l&&flag==true)){
          //最后几项
          $('.' + active).removeClass(active).parent().next().find('a').addClass(active);
        }else{
          $('.' + active).removeClass(active).parent().next().find('a').addClass(active);
          fpageShow(pageshow+1);
        }
        opts.callBack(pageshow+1);
      });
      obj.on('click', '.prv', function () {
        var pageshow = parseInt($('.' + active).html());
        var nums = odevity(n);
        if (pageshow <= 1) {
            return;
        }else if((pageshow > 1&&pageshow <= nums/2)||(pageshow > l-nums/2&&pageshow < l+1)){
          //最前几项或最后几项
          $('.' + active).removeClass(active).parent().prev().find('a').addClass(active);
        }else {
          $('.' + active).removeClass(active).parent().prev().find('a').addClass(active);
          fpageShow(pageshow-1);
        }
        opts.callBack(pageshow-1);
      });

      obj.on('click', '.first', function(){
        var activepage = parseInt($('.' + active).html());
        if (activepage <= 1){
          return
        }//当前第一页
        opts.callBack(1);
        fpagePrv(0);
      });
      obj.on('click', '.last', function(){
        var activepage = parseInt($('.' + active).html());
        if (activepage >= l){
          return;
        }//当前最后一页
        opts.callBack(l);
        if(l>n){
          fpageNext(n-1);
        }else{
          fpageNext(l-1);
        }
      });

      obj.on('click', 'li', function(){
        var $this = $(this);
        var pageshow = parseInt($this.find('a').html());
        var nums = odevity(n);
        opts.callBack(pageshow);
        if(l>n){
          if(pageshow > l-nums/2&&pageshow < l+1){
            //最后几项
            fpageNext((n-1)-(l-pageshow));
          }else if(pageshow > 0&&pageshow < nums/2){
            //最前几项
            fpagePrv(pageshow-1);
          }else{
            fpageShow(pageshow);
          }
        }else{
          $('.' + active).removeClass(active);
          $this.find('a').addClass(active);
        }
      });

          //重新渲染结构
        /*activePage 当前项*/
        function fpageShow(activePage){
          var nums = odevity(n);
          var pageStart = activePage - (nums/2-1);
          var str1 = '';
          for(i=0;i<n;i++){
            str1 += '<li><a href="javascript:" class="">' + (pageStart+i) + '</a></li>'
          }
          obj.find('ul').html(str1);
          obj.find('ul li').eq(nums/2-1).find('a').addClass(active);
        }
        /*index 选中项索引*/
        function fpagePrv(index){
          var str1 = '';
          if(l>n-1){
            for(i=0;i<n;i++){
              str1 += '<li><a href="javascript:" class="">' + (i+1) + '</a></li>'
            }
          }else{
            for(i=0;i<l;i++){
              str1 += '<li><a href="javascript:" class="">' + (i+1) + '</a></li>'
            }
          }
          obj.find('ul').html(str1);
          obj.find('ul li').eq(index).find('a').addClass(active);
        }
        /*index 选中项索引*/
        function fpageNext(index){
          var str1 = '';
          if(l>n-1){
            for(i=l-(n-1);i<l+1;i++){
              str1 += '<li><a href="javascript:" class="">' + i + '</a></li>'
            }
           obj.find('ul').html(str1);
           obj.find('ul li').eq(index).find('a').addClass(active);
          }else{
            for(i=0;i<l;i++){
              str1 += '<li><a href="javascript:" class="">' + (i+1) + '</a></li>'
            }
           obj.find('ul').html(str1);
           obj.find('ul li').eq(index).find('a').addClass(active);
          }
        }
        //判断liNums的奇偶性
        function odevity(n){
          var a = n % 2;
          if(a == 0){
            //偶数
            return n;
          }else if(a == 1){
            //奇数
            return (n+1);
          }
        }
    });
  }
})(jQuery);

使用方法,在需要分页展示的文章下方添加以下div标签:

<div class="page">
</div>

 在网页头部引入以下js:

<script type="text/javascript" src="plugin/fenye.page.js"></script>
<script type="text/javascript">
$(function(){
	$("#page").Page({
	  totalPages: 7,//分页总数
	  liNums: 5,//分页的数字按钮数(建议取奇数)
	  activeClass: 'activP', //active 类样式定义
	  callBack : function(page){
			//console.log(page)
	  }
  });
})
</script>

markdown文档渲染

<ul class="info>
<div class="md_render">
</div>
</ul>
	<script>
		var md;
		var defaults = {
		html: false, // Enable HTML tags in source
		xhtmlOut: false, // Use '/' to close single tags (<br />)
		breaks: false, // Convert '\n' in paragraphs into <br>
		langPrefix: 'language-', // CSS language prefix for fenced blocks
		linkify: true, // autoconvert URL-like texts to links
		typographer: true, // Enable smartypants and other sweet transforms
		// options below are for demo only
		_highlight: true,
		_strict: false,
		_view: 'html' // html / src / debug
		};
		defaults.highlight = function (str, lang) {
		var esc = md.utils.escapeHtml;
		
		if (lang && hljs.getLanguage(lang)) {
			try {
			return '<pre class="hljs"><code>' +
					hljs.highlight(lang, str, true).value +
					'</code></pre>';
			} catch (__) {}
		}
		return '<pre class="hljs"><code>' + esc(str) + '</code></pre>';
		};
		md = window.markdownit(defaults).use(window.markdownitCheckbox).use(window.markdownitEmoji).use(window.markdownitFootnote);
		var dat = document.querySelector('#enrolled_id').value;
		$('.md_render').html(md.render(dat));
	</script>

 这里有个坑需要注意,jinjia2模版是在后端渲染的,所以在网页的js代码中想使用模版变量不是那么美,不能像网页中{{data}}的方式使用。这里采用了一种取巧的方式,通过一个隐藏标签,先把需要的内容在html网页中渲染出来,再在js中通过操作dom的方式去获取。

<input type="hidden"  id="enrolled_id" value="{{ data.body }}">

其他资源

(自适应手机端)响应式个人博客网站模板

我的博客模版

JSON在线 | JSON解析格式化—SO JSON在线工具

风宇个人博客

丰富的计算机技术分享,多样化的互联网资源分享,第1页 - 吱吱工具箱butterPig

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

CPU虚拟化的过程

VMCS 是Virtual Machine Control Structure。是 Intel 实现 CPU 虚拟化&#xff0c;记录 vCPU 状态的一个关键数据结构。VMCS 数据结构主要包含以下信息。 Guest-state area&#xff0c;即 vCPU 的状态信息&#xff0c;包括 vCPU 的基本运行环境&#xff0c;例如寄存器等。Hos…

数据治理模型的三个模块

数据接入模块 大数据工程的数据来源包含企业内部数据和企业外部数据&#xff0c;其中企业内部数据由资源服务平台、综合资源库、各业务系统生产库中的结构化数据和文件服务器上的文本、图片等非结构化数据组成&#xff0c;其中包括人财物记录、财物报表、原材料、顾客信息、气…

启动kafka集群以及关闭

kafka操作 第一个窗口 cd /root/software/kafka bin/zookeeper-server-start.sh config/zookeeper.properties最后这种就是成功了 Zookeeper 启动&#xff1a; Zookeeper 是 Kafka 集群的协调服务&#xff0c;启动 Kafka 之前必须确保 Zookeeper 正在运行。 第二个窗口&am…

谨慎Apache-Zookeeper-3.5.5以后在CentOS7.X安装的坑

目录 前言 一、现场还原 二、问题诊断 三、问题原因 总结 前言 最近由于项目需要&#xff0c;在服务器上需要搭建Hbase完全分布式集群环境。开发环境&#xff0c;采用的是最小节点的方式进行搭建&#xff08;即3个节点的模式&#xff09;。资源环境列表如下&#xff1a; 序号…

CentOS7搭建Kubernetes集群

环境准备&#xff1a;配置好静态IP地址的Centos7&#xff08;2核、master内存3GB、slave内存2GB&#xff09;。 搭建概述&#xff1a;先将一台虚拟机搭建为master、随后克隆出两台虚拟机作为从节点。 虚拟机主机名和IP地址&#xff1a; 主机名IP地址master192.168.138.110sl…

python类的多重继承继承和查找顺序

1 python类的多重继承继承和查找顺序 python中&#xff0c;类的多重继承允许子类继承多个基类&#xff0c;子类可以访问多个基类的属性和方法。 1.1 多重继承基础 用法 class MulClass(BaseC1,BaseC2,...BaseCn):pass描述 Mulclass&#xff1a;子类&#xff08;或者称混合…

网络核心知识总结

计算机网络总结 基础 网络分层模型 OSI 七层模型是什么&#xff1f;每一层的作用是什么&#xff1f; OSI 体系结构是法律上的国家标准&#xff0c;从上往下讲分别是&#xff1a; 应用层 – 作用是 – 为计算机用户提供服务表示层 – 作用是 – 数据处理(编解码、加密解密、…

【数据结构】八大排序 (三)

目录 前言&#xff1a; 快速排序 快速排序非递归实现 快速排序特性总结 归并排序 归并排序的代码实现 归并排序的特性总结 计数排序 计数排序的代码实现 计数排序的特性总结 前言&#xff1a; 前文快速排序采用了递归实现&#xff0c;而递归会开辟函数栈帧&#xff0…

赴日开发做什么?日本签证很难拿?

日本的IT行业历史比较悠久&#xff0c;业务以上层前端业务为主&#xff0c;如设计和构建软件。日本IT公司组织庞大&#xff0c;行业内部有着严格的分工和部署&#xff0c;工作会被细分化。分配给个人的工作量不会太大&#xff0c;难度也不会很高。 在日本IT公司就业&#xff0…

【古月居《ros入门21讲》学习笔记】06_ROS常用命令行工具

目录 说明&#xff1a; 1. 回顾小海龟案例 终端1&#xff1a;启动ROS master 终端2&#xff1a;启动小海龟仿真器 终端3&#xff1a;启动海龟控制节点&#xff1a; 2. 系统计算图&#xff1a;rqt_graph 3. rosnode rosnode list&#xff1a;显示节点列表 rosnode info&…

LESS的叶绿素荧光模拟实现——任意波段荧光模拟

目录 前言一、任意波段荧光模拟的实现二、需要注意的输入参数 前言 此专栏默认您对LESS (LargE-Scale remote sensing data and image Simulation framework) 模型和叶绿素荧光(Sun-Induced chlorophyll Fluorescence, SIF)有一定的了解。当然&#xff0c;您也可以在这里下载中…

NCo3.1(08) - Nco3 服务器端编程

本篇博文不再重复ABAP调用外部服务器的基础&#xff0c;只介绍 NCo3 开发的过程和要点。需要了解相关知识点的小伙伴们自行参考&#xff1a; SAP接口编程 之JCo3.0系列(06) - Jco服务器端编程 PyRFC 服务器端编程要点 创建项目 新建一个 Console 项目&#xff0c;选择 .Net …

(亲测有效)解决windows11无法使用1500000波特率的问题

大家好&#xff01;我是编码小哥&#xff0c;欢迎关注&#xff0c;持续分享更多实用的编程经验和开发技巧&#xff0c;共同进步。 1、问题描述 从图1可以看出串口是正常的&#xff0c;安装的驱动是CP210xVCPInstaller_x64.exe&#xff0c;但是从图2可以看出&#xff0c;串口拒…

C# WPF 基础教程——触发器、行为、形状、变换与透明、路径和几何图形

触发器 简单触发器 单条件触发器 多条件触发器 事件触发器 行为 形状 矩形和椭圆 Viewbox缩放控件&#xff0c;直线&#xff0c;折线&#xff0c;多边形 画刷 普通画刷 线性渐变画刷 环形渐变画刷 位图画刷 虚拟画刷&#xff08;复制元素外观&#xff09; 位图缓存画刷 变换…

对二分搜索的理解 Go语言版

二分搜索大家都很熟悉&#xff0c;首先我们先来看看基本框架 func binarySearch(nums []int, target int) int {left, right : 0, ...for ... {mid : left (right-left)/2if nums[mid] target {...} else if nums[mid] < target {left ...} else if nums[mid] > targ…

探索测试开发工程师的通往成功的秘密路径!

「作者说」随着近几年国内IT行业高速发展&#xff0c;对测试工程师的要求也越来越高&#xff0c;其作用也越来越重要&#xff0c;但很多测试工程师也迎来了个人发展的瓶颈&#xff0c;下一步该向哪个方向发展&#xff0c;该如何发展&#xff1f;本文将概述测试工程师的现状及发…

使用MAT分析内存泄漏(mac)

前言 今天主要简单分享下Eclipse的Memory Analyzer在mac下的使用。 一、Mat&#xff08;简称&#xff09;干什么的&#xff1f; 就是分析java内存泄漏的工具。 二、使用步骤 1.下载 mac版的现在也分芯片&#xff0c;别下错了。我这里是M2芯片的&#xff0c;下载的Arch64的。 …

海康运行管理中心 RCE漏洞复现

0x01 产品简介 海康威视是以视频为核心的智能物联网解决方案和大数据服务提供商。海康运行管理中心是一款功能强大、易于使用的安防管理平台&#xff0c;能满足用户对视频监控、报警管理、设备配置和数据统计等方面的需求&#xff0c;帮助用户建立高效、智能的安防系统。 0x02…

tcpdump使用心得

参考原文 https://danielmiessler.com/p/tcpdump/ 几个用例 tcpdump -i eth0 显示eth0网卡当前所有的抓包情况eth0是网卡名&#xff0c;可以通过ifconfig获得&#xff0c;也可以通过 tcpdump -D 显示当前可以监听的网卡 -i 参数表示接口&#xff0c;后跟要监听的网卡 tcpdu…

MySQL 中的锁(三)

8.7. 死锁和空间锁 一般来说&#xff0c;只要有并发和加锁这两种情况的共同加持下&#xff0c;都会有死锁的身影。 死锁的具体成因&#xff0c;借用我们在并发编程中的内容&#xff1a; 8.7.1. 死锁 8.7.1.1. 概念 是指两个或两个以上的进程在执行过程中&#xff0c;由于竞…