ISE头条号海报生成器

完整源码可在公众号:「01二进制」后台回复:「海报生成器」获取 最近自闭了一段时间,仔细思考一番后还是决定要把自己心中所想坚持下去。今天来分享一个日常生活中经常见到,但是制作起来又可能会一时没有思路的东西,主要功能就是生成带二维码的卡片或者海报。 之前莫名其妙的被导师安排负责管理实验室的头条号,任务不难,就是接收实验室学长学姐翻译转述的论文,然后再发布到今日头条的头条号上,最后再生成如下所示的宣传图即可: 当时觉得,不就是发发文章,然后再用ps做个图这么简单吗。可接手之后才发现我毕竟图样图森破啊,从去年11月我开始发文章到今天,期间从未有一天断过,但是这头条号的编辑器也从未更新过,一个这么大的自媒体企业,文章的编辑器竟然烂的跟坨💩一样,不支持外部图片,不支持markdown,不支持数学公式,不支持多级标题。(别跟我说什么可以把markdown转成html然后再复制进头条号的编辑器里面,样式都变成鬼了) 扯远了扯远了,回到正题。之前这么多天实现上述需要的主要流程如下: (采取各种方式优化排版)把文章发布到(不支持各种常用功能的)头条号上 文章发布后,获取其文章链接,并到草料二维码生成器网站,上传实验室logo后生成二维码下载至本地 利用PhotoShop将封面图、文章标题和文章二维码合成在一起后发给老师。 在经历了100天上述这样重复的操作之后,我厌烦了。难道就没有一个工具可以让我只输入文章链接和标题就自动生成海报的吗? 苦苦寻觅半天无果,也罢,有条件要上,没条件创造条件也要上。没有现成的轮子,那就只能自己打造一个了,Python无疑是开发这个小工具的首选。 一般用于推广的海报或卡片样式都差不多,需要改变的主要就是二维码,所以只需要准备好海报的背景图,然后根据用户提供的二维码,将其贴在海报指定的位置上即可。 此次实验的项目结构如下: assets文件夹中包含一些资源文件,例如msyhl.ttc(字体文件)、template.jpg(背景模版图片)。output是生成的海报存放的路径 生成带logo的二维码 本次生成二维码依赖于 PIL 模块和 qrcode 库,官方地址为:https://pypi.org/project/qrcode/5.1/,这里不解释用法,感兴趣的自己去官方文档下了解。这里就直接上代码了,具体代码的用意详见注释: # 生成一个带logo的二维码 def generateQRCode(url): # 初始化 qr = qrcode.QRCode( version=5, error_correction=qrcode.constants.ERROR_CORRECT_H, box_size=8) # 添加内容 qr.add_data(url) qr.make(fit=True) img = qr.make_image() img = img.convert("RGBA") # 读取logo icon = Image.open("assets/logo.jpg") # 设置logo img_w, img_h = img.size factor = 4 size_w = int(img_w / factor) size_h = int(img_h / factor) icon_w, icon_h = icon....

mac下利用pyenv管理多个版本的python

前言 经常遇到这样的情况: 系统自带的Python是2.x,自己需要Python 3.x; 某些机器学习的框架(如PaddlePaddle/Tensorflow)需要的版本是python3.5,但是你的系统支持的python版本较高,且无法删除(因为某些软件会和python产生依赖) 此时需要在系统中安装多个Python,但又不能影响系统自带的Python,即需要实现Python的多版本共存。pyenv就是这样一个Python版本管理器。 ...

pyenv下使用python matplotlib模块的问题解决

错误信息 先来描述一下我遇到的问题,在进行matplotlib学习时,plot.show()总是无法成功运行,总是会报一个错: RuntimeError: Python is not installed as a framework. The Mac OS X backend will not be able to function correctly if Python is not installed as a framework. See the Python documentation for more information on installing Python as a framework on Mac OS X. Please either reinstall Python as a framework, or try one of the other backends. If you are using (Ana)Conda please install python.app and replace the use of ‘python’ with ‘pythonw’. See ‘Working with Matplotlib on OSX’ in the Matplotlib FAQ for more information. 其实意思很简单,就是我用的python并不是一个作为系统框架存在的,因为我为了方便管理python的版本,选择了pyenv这个管理工具,是一个独立出来的python环境。 ...

Python 管理哪家强?

之前介绍过《利用pyenv管理多个版本的python》,pyenv 是一个非常好用的 Python 版本管理工具,利用它我们可以在同一台电脑上安装多个版本的 Python ,这个过程非常简单。Mac系统的电脑一行命令就可以安装了: brew install pyenv pyenv 的安装和使用详见开篇提到的文章,这里不再赘述。 今天主要是想介绍另一个非常好用的 Python 工具——“Pipenv” Pipenv是什么? Pipenv is a tool that aims to bring the best of all packaging worlds (bundler, composer, npm, cargo, yarn, etc.) to the Python world. Windows is a first-class citizen, in our world. It automatically creates and manages a virtualenv for your projects, as well as adds/removes packages from your Pipfile as you install/uninstall packages....

plainify

为什么不在 for 循环里捕获异常?

在回答标题这个问题之前,我们先试想一下,在没有 try…catch 的情况下,如果想要对函数的异常结果进行判断,我们应该怎么做? 异常 第一个想法肯定就是 if…else 了,一般情况下,相关的代码段我们都是放在一起的,如果此时你的程序中有大量的代码段要做这做判断,这就意味着后面执行的逻辑会依赖你前面语句的执行情况,也就意味着你每调用一个可能会出现错误的函数的时候,都要先判断是否成功,然后再继续执行后面的语句。这就会导致你的代码中会充斥着大量的 if…else。 Java 是一门工程性的语言,而工程也是一种艺术,因此采用这样的做法显然是很不优雅的。《Thinking in Java》中提到“badly formed code will not be run.”,意思是结构不优雅的代码不应该被执行,于是一个适用于 Java 的异常处理机制便应运而生了。 Java 的异常处理其目的在于通过使用少于目前数量的代码来简化大型程序,举个简单的例子 🌰 不用 try…catch FileReader fr = new FileReader("path"); if (fr == null) { System.err.println("Open File Error"); } else { BufferedReader br = new BufferedReader(fr); while (br.ready()) { String line = br.readLine(); if (line == null) { System.err.println("Read Line Error"); } else { System.out.println(line); } } } 用了 try…catch...

plainify

为什么我们需要批量操作?

背景 实习的时候被问过一个问题,为什么 redis 会有 pipline,mysql 会有 batch,这些东西都具有批量操作的共性,是什么原因让我们在处理数据时需要批量操作? 这么说可能有些抽象,举一个和 API 调用有关的例子 🌰: 现有三个服务 service A、service B 和 service C。因业务需要,我们需要在 service A 中调用 service B 获取一组 id,然后根据 id 从 service C 中读取最终内容。然后组织成结果返回前端。由于 service C 只提供了单个 id 查询内容的 API,所以如果我们想要获取批量的信息,最先想到的办法是通过 for 循环多次调用 service C。但是这样的办法是极其不优雅的,接下来我们从以下两个方面来分析。 网络通信 鉴于现在的分布式架构,每个 service 都分布在不同的服务、不同的机器中,所以我们每次调用都要通过 RPC 来实现,这就要求我们不得不构造同等数量的请求来获取数据。这样就会导致了一些效率问题。如下图所示: 所以我们通常会通过在 service C 中提供一个批量查询的接口来解决多次通信的问题。如下图所示 👇 我们知道,并不是每一次网络传输都非常稳定,中途可能会遇到丢包等一系列问题,而用批量查询代替 for 循环单个查询,这样做的好处是,我们可以减少网络通信的次数,一定程度上可以增加整个系统的健壮性。 数据查询 解释完多次 rpc 调用可能造成的网络延迟的问题后,我们再往深一点的地方看。 一般情况下,数据都是存放在数据库中的,所以无论是单个查询还是批量查询,我们最终都是要访问到数据库的。 现假设,我们需要从数据库中查询一个 id 为 123 的用户信息,我们可以用类似下面这样的代码。 long id = 123; Person p = serviceA....

plainify

为什么我建议你去写博客?

每次有学弟学妹问我如何学编程的时候,我都会在最后告诉他们最好写篇博客记录下。现在是 2020 年的 11 月,我自己写博客也已经有 3 年多了,零零散散也写了有 200 多篇了,虽然不如一些大佬写的多且快,但自己佛系更新倒也开心。刚开始写的时候,也没想着能坚持到现在,现在写了几年,渐渐也成了一种习惯,今后应该还会继续写下去。 维基百科对于博客的解释是: 博客(英语:Blog)是一种在线日记型式的个人网站,借由张帖子章、图片或影片来记录生活、抒发情感或分享信息。博客上的文章通常根据张贴时间,以倒序方式由新到旧排列。 说白了就是记录自己的一些想法、学习心得、总结之类的,主要还是看自己想写什么。 我是一个文笔很差的人,高考语文也是勉强及格,所以如果一开始你告诉我,我的文字将会对我产生很大的影响,我肯定是不相信的。直到后来本科学了软件工程之后,想着要整理一些自己的学习笔记,但是代码也不方便用纸记下来,这便开始有了用电脑做笔记的想法。当时的做法也很土,就是新建一个 word 文档记笔记,然后用一个文件夹收录,后来经学长提点,索性就把笔记整理到 csdn 上,这样就不用每次记笔记还要新建一个 word 文档了。 再之后,看到了阮一峰、池建强的博客网站,也学到了很多有用的知识,也萌生出弄一个自己的博客的想法。期间也尝试了很多,有在掘金、简书等第三方平台上发布博客,也自己玩了玩 wordpress、hexo 这样的自建博客,现在也算是确定了写作的位置,最终选择了自建博客(hexo)+掘金/简书/公众号的搭配。掘金和简书主要是发布一些技术性的文章,例如实战教程这些,公众号吹水的比较多,科普一些我学到的技术、聊一聊我的想法之类的,然后所有的这些都存放到我的自建博客中去。 之所以会选择 hexo 这种自建博客,一方面是因为他的颜值比较高(虽然 wordpress 也可以安装各种主题),只要下载别人的主题简单的配置下就可以弄出一个好看的博客了。另一个原因就是部署、同步相较于 wordpress 更加方便,hexo 是用 markdown 的形式进行写作,这样的好处就是我可以无缝迁移到简书、掘金、公众号等平台,而且和 wordpress 这种需要自己购买服务器的自建博客相比,hexo 可以依赖 GitHubPages 免费使用,这对于我这种白嫖党来说无疑是最好的选择。 其实写博客的这几年也有人问过我,你又不接广告,也没什么人打赏,还要花那么多时间来写博客,不觉得累吗?为什么还坚持写了几年? 说实话,写博客确实是很花时间的,但是我认为和单纯的学习笔记相比,博客是对笔记的又一种成体系的整理,一方面可以加深记忆,另一方面也方便日后的查找翻阅。 不仅如此,如果你的博客内容质量很高,在一定程度上是可以提高自己的影响力。在如今这个浮躁的社会,很多人的文章都是东拼西凑,如果你的内容有足够的深度,那么物以稀为贵,你会更加容易、持久的建立起自己的影响力。 而且就算你的文笔不够好,也可以在写博客的过程中锻炼自己的思维能力、知识储备能力,以及思维的严谨程度。我相信,在写作过程中得到的锻炼,对于你在其他领域的工作,依然会有所帮助。 功利点说,如果你的内容质量非常高,也是可以通过写作赚钱的。我们正处在一个“知识付费”的年代,写达人课、写书、写推广文、写公众号,这些赚钱方式不一而足。而且不同于工作,你在写作上所花费时间可以被多次售卖,你可以通过你的写作,构建出属于自己的**「睡后收入」**。 当然了,博客也不单单可以用来整理学习笔记,我时常会通过博客来帮助我探索、梳理和记录生活。写一篇博客所花费的时间,比整理笔记要多得多,但另一方面,我们又会浪费很多时间。坚持抽一些时间写一篇博客,一定程度上可以让自己学会管理时间,毕竟谁不希望可以成为一个“时间管理大师”呢? 以上就是我对于写博客这件事的一些简单想法,就个人而言,写博客的这几年,我的知识储备得到了提升,也获得了一些收入,还通过博客认识到了一些有趣的人。当然,如果你觉得你想说的东西不适宜让他人知道,其实也可以在自己的电脑里写,不用放到网上。但我还是强烈建议,每一个朋友(尤其是计算机专业),都应该有一个属于自己的 Blog,尝试将自己的生活和想法记录下来,留下一些印记,说不定未来的某一天你的博客就让你的人生有了一些变化,毕竟,我女朋友就是写博客认识的(逃)。

plainify

为什么非对称加密比对称加密慢?

这个问题是一个读者面试时遇到的一个问题,准备过面试的人应该都记得,非对称加密与对称加密的区别之一就是非对称加密的速度慢,但是我们做业务开发的时候通常都是直接调用算法,对其原因并没有过多深究,因此如果有面试官问到了这个问题,的确会让人措手不及。正好借着这篇文章来说一说。 对称加密与非对称加密 首先我们先来说一下到底什么是对称加密,什么是非对称加密,这一节主要是用一些例子来介绍一下对称加密和非对称加密是什么,如果你已经了解了,可以跳过本节。 对称加密 高中生小明和小红是一对“地下情侣”,可偏偏他们一个坐在教室前,一个坐在教室后,所以晚自习的时候也只能通过纸条传情。这时一个很尴尬的事情就出现了,由于无法直接将纸条交给对方,因此纸条必须要经过多个人的传递,可总有一两个八卦的人喜欢看纸条里写的什么。为了避免被班主任抓包以及被同学们窥视,他们两约定,用现代汉语词典当作“密码本”,以后传纸条时,纸条上的内容是要写的字在词典里的页码及顺序,这样即使纸条被别人看了,不知道密码本是什么的人也就不会得知纸条里的真正内容了。 在上述的例子中,纸条是承载信息的载体,纸条里的内容是信息,汉语词典是密钥,将文字映射到汉语词典的页码和顺序是加密方式(算法)。 类似于上面这种,在加密和解密时使用相同的密钥,或是使用两个可以简单地相互推算的密钥的加密方式就是对称密钥加密(Symmetric-key algorithm),简称对称加密。常见的对称加密算法有:AES、DES、3DES 所以你可以将对称加密简单理解为:一方通过密钥将信息加密后,把密文传给另一方,另一方通过这个相同的密钥将密文解密,转换成可以理解的明文。他们之间的关系如下图所示(这里借用一下@寒食君的图): 弊端 这种加密方式虽然简单,但是其弊端也是非常明显的。在上面的例子中,如果传递纸条的人知道了他们这种加密方式,那就同样可以通过查阅汉语词典解析出他们的纸条内容。如下图所示。这样为什么众多抗战片中会出现疯狂抢夺密码本这一情节也就很好理解了。 非对称加密 再举一个生活中非常常见的例子。小区里的小伙伴们经常可以在自家的邮箱里收到信件,比如你的录取通知书,当然更多可能是广告。不过,虽然说所有人都可以往里面扔邮件,但是只有你可以打开这个邮箱查看这个邮件。 上面这个过程就是一个很形象的非对称加密。 非对称加密不同于对称加密,它有一对秘钥,一个称为公钥(publicKey) ,另一个称为私钥(privateKey),并且***只知道公钥是无法推算出私钥**。*就和上面的例子中只知道邮箱位置却并不能打开邮箱是一个道理。常见的非对称加密算法有:RSA、DSA、ECC 另外,这种算法还有一个特别神奇的功能,那就是通过公钥加密的内容,只有私钥才可以解开,而通过私钥加密的内容,只有公钥才可以解开。 公钥/私钥的用法 第一种用法:公钥加密,私钥解密。—用于加解密 第二种用法:私钥签名,公钥验签。—用于签名 其实很容易理解: 既然是加密,那肯定是不希望别人知道我的消息,所以只有我才能解密,所以可得出公钥负责加密,私钥负责解密; 既然是签名,那肯定是不希望有人冒充我发消息,只有我才能发布这个签名,所以可得出私钥负责签名,公钥负责验证。 这里提一点:签名 ≠ 加密,通俗点说加密就是你哪怕看到了不该看到的东西,也理解不了。而签名就是你做了任何事,都抵赖不了。 为什么非对称加密比对称加密慢? 介绍了这两种加密方式后,我们终于可以回到本篇文章的开头了,为什么非对称加密会比对称加密慢? 这是因为对称加密主要的运算是位运算,速度非常快,如果使用硬件计算,速度会更快。以 AES 算法为例,如下图所示,其运算本质上来说就是位移和替换。 但是非对称加密计算一般都比较复杂,比如 RSA,它里面涉及到大数乘法、大数模等等运算。其加解密可以用下面的公式来表示: 我们知道,幂运算的本质是乘法,乘法的基础单位是加法,也就是我们最常见的整数加。学过数字逻辑电路的同学想必都知道,在电路上实现“加法”比异或(XOR)要麻烦的多,况且后面还有一个模运算。因此非对称加密的速度自然而然是比不过对称加密的。 当然,我想另外还有一个原因是,AES 中的许多中间计算过程是可以事先计算好的。加密数据时许多中间过程可以直接查表,而不需要实时地计算。 通常情况下,非对称加密(如 RSA)的解密速度会比加密速度更慢,详情可参考Why is RSA decryption slow? 时空性 这里另外提一点,我们在学习算法的时候,一定听过时间复杂度和空间复杂度这两个名词。鱼和熊掌不可兼得,通常情况下,一个算法如果运行比较快,那么空间消耗相对来说就会高一些,反之亦然。因此才会有拿空间换时间的说法。 从上一节我们可以知道,非对称加密运行起来通常比对称加密慢,那么这时就有一个问题了,对于密钥的存储情况也是这样吗?非对称加密对于密钥的存储会比对称加密的密钥存储少吗? 答案是的确如此,在对称加密中,当信息量大的时候,要求密钥量也要足够大,需要每两个人之间都有一个密钥,也就是对于 n 个人来说,一共需要 个密钥才能确保两两之间对话不被其他人知道。 而在非对称加密中,每个人都有公钥和私钥,对于 n 个人来说,一共要 个密钥,就能保证两两之间对话不被其他人知道。 什么?你问我这个公式怎么来的?数学归纳法了解一下? 这么看,非对称加密虽然效率低下,但是存储成本低且相对安全,这也就解释了为什么非对称加密应用如此广泛了。 HTTPS 既然无法做到既安全又快速的加解密,那我们在实际使用时只能尽量达到一个动态的平衡。 因此我们在项目中通常会采用如下这种将两种加密算法结合在一起的使用方式:...

plainify

什么是环境变量?

前言 在初学 Java 时,相信大家下载安装完 JDK 后的第一件事就是 「配置环境变量」,几乎所有的教程都会告诉你当你在命令行工具中输入了 java 命令和 javac 命令后看到类似如下的结果就说明你的 Java 环境配置好了 👇 不知道你有没有思考过这个「环境变量」究竟是什么?为什么配置了之后就会显示这样的内容,为什么不配置,就会提示你一个错误:'javac' 不是内部命令或外部命令,也不是可运行的程序或批处理文件。 如果你也有这样的疑问,不要着急,我们今天就来一探究竟。 文内相关的演示,均在 Windows10 操作系统下执行 从打开软件的两种方式说起 我们平时打开一个应用程序,一般是双击桌面图标或在开始菜单链接,无论是桌面的快捷图标还是菜单链接都包含了应用程序的安装位置信息,打开它们的时候系统会按照这些位置信息找到安装目录然后启动程序,这里以 QQ 这个软件为例: 上面是我们最常用的打开软件的方式,当然了,既然知道了一个应用程序的安装目录位置,我们也可以通过命令行工具进入启动程序所在的文件,通过命令打开,如笔者 QQ 的位置为: "C:\Program Files (x86)\Tencent\QQ\Bin\QQScLauncher.exe" QQ 的启动程序名为 QQScLauncher,那么我们打开终端工具,使用 cd 命令进入该目录,再输入.\QQScLauncher.exe,即可通过命令启动 QQ。 做一点改进 如果想要炫技,每次都先进入安装目录再打开文件显然有些麻烦,那有没有什么简单的方式,直接在命令行工具中输入 QQScLauncher 甚至直接输入 QQ 就能打开软件呢? 当然是可以的,我们只需要在用户变量名Path中添加安装路径的字符,我们在命令行工具无需进入软件的安装路径即可打开软件了。 我们来试下直接在命令行工具中输入 QQScLauncher,果然可以直接打开软件了。 原因 为什么配置环境变量前,直接输入 QQScLauncher 无法打开软件呢? 这是因为操作系统并不知道你的 QQScLauncher.exe 这个文件在哪里,所以无法执行对应的文件。 你在命令行里输入的那几个符号,其实就是一些可执行程序的名字(标签、别名),是可以直接被当前系统直接执行的程序。如果是在 Windows 系统中,则这些被输入的符号就是可以直接被 windows 系统执行、后缀为'.exe’的程序(文件)。 那么为了能够让操作系统找到这个可执行文件,我们就需要把 QQScLauncher.exe 这个 可执行文件所在的目录作为 PATH 环境变量的一部分设置起来,这样当你在命令行输入一个命令的时候,操作系统就会自动搜索 PATH 变量中所指定的所有目录 了。...

代码情书——谁说程序员不懂爱

七夕佳节, 送你们一份来自直男的代码情书 代码情书——谁说程序员不懂爱 曾经有一份真挚的爱情摆在我眼前, 我没有珍惜, 等我失去的时候我才后悔莫及, 如果上天能给我一个再来一次的机会, 我会对那个女孩子说三个字我爱你, 如果非要在这份爱上加一个期限, 我希望是一万年。 来源: 电影《大话西游之大圣娶亲》 public class Love { public static void main(String[] args) { boolean love = true; while (love) { love = false; } me.regret(); if (god.getChance()) { me.sayToHer("我爱你"); if (me.getLoveTime() < 10000) { me.setLoveTime(10000); } } } } 你的一句明天见, 偷走了我整个夜晚的睡眠。 来源: https://www.zhihu.com/question/28314613 public class Love { public static void main(String[] args) { while (you.say("see you tomorrow")) { i....