利用zabbix生成awstats日志分析图表并用Python调用zabbix API批量添加item

awstats作为一款日志分析软件,功能不错,但是界面过于简单,也没有图表功能,这里我采取了一种变通的方法,将awstats的分析结果(pv、hits(文件数)、bandwidth、visits(独立ip))添加到zabbix,并通过zabbix生成趋势图表。

在前两篇文章中,我们队awstats的使用及其工作方式进行了简明扼要的介绍:awstats对每个站点进行分析之后,会生成一个“awstats012016.txt”格式的“数据库”文件;awstats的展示页面便是从该文件中取数据生成的。

  1. 多server多站点情况下awstats日志分析:http://kaifly.blog.51cto.com/3209616/1719248

  2. awstats CGI模式下动态生成页面缓慢的改进:http://blog.51cto.com/kaifly/1770137

这篇文章的思路就是从这个文本格式的‘数据库文件’中取得我们想要的数据,然后通过自定义的脚本将其添加到zabbix中,最终满足我们生成pv趋势图表的需求。

而完成此任务的关键就是分析似‘awstats052016.txt’的数据文件的内容格式(ps:以笔者“多年”shell经验来看,”分析源文件格式“和“生成目标文件格式”这俩“格式”在日常的shell编程中占用了很大一部分时间。扯远了O(∩_∩)O~)

首先是自定义脚本作为zabbix的key,从对应的‘数据文件’中取得pv、hits、bandwidth、visits的值。用shell实现如下

cat web_pv.sh

#!/bin/sh
#从例如api/awstats052016.txt这样的awstats数据库文件里取得昨天的pv等统计(因为awstats本身就是统计到昨天的日志)
#by  ljk  20160506
#blog    http://kaifly.blog.51cto.com/

#shell脚本的$1 $2分别代表站点名称(格式如www或bbs)和统计项(pv 文件数 字节 独立ip)

basedir='/usr/local/awstats-7.4/result'
date_f1=$(date +%m%Y -d '1 day ago')
date_f2=$(date +%Y%m%d -d '1 day ago')

cd $basedir/$1
#下面关于awk的用法中有一个小技巧,匹配到指定的项之后,停止继续搜索余下的内容。这对于体积较大的文件可以节约不少时间
content=`awk '$1 == "'$date_f2'" {{print} {exit}}' awstats$date_f1.txt`
case $2 in
    "pages")
        echo $content|awk '{print $2}';;    #pv
    "hits")
        echo $content|awk '{print $3}';;    #hits/文件数
    "bandwidth")
        echo $content|awk '{print $4}';;    #bandwidth/字节
    "visits")
        echo $content|awk '{print $5}';;    #visits/独立ip
    *)
        echo "unknow value";;
esac

然后在awstats所在的server的zabbix的‘userparameter.conf’文件中添用户自定义key,并重启zabbix_agentd

UserParameter=web_pv[*],/bin/sh /usr/local/zabbix/etc/zabbix_agentd.conf.d/web_pv.sh $1 $2

接着在zabbix_server端通过zabbix_get命令尝试获取这些值,key格式为“web_pv[站点名,监控项]”,例如

未分类

能取到值,说明自定义key是ok的。

接下来就是在zabbix里添加各站点的item了,这里通过Python实现(zbx接口通过json传递数据,处理json python比shell方便太多了)

这里需要仔细阅读下zabbix的api文档https://www.zabbix.com/documentation/3.0/manual/api和查看zabbix数据库结构(确保万无一失嘛)

首先在zabbix里创建一个template,名为Template site PV,这一步手动创建即可

然后开始通过Python自动化添加items

cat shells/add_web-pv_item_to_zabbix.py

#!/bin/env python3
"""
将各站点的4种(pages,hits,bandwidth,visits)item添加/更新到zabbix的 'Template Site-PV'
by ljk  20160507
"""

import os,requests

basedir='/usr/local/services/awstats-7.4/result/'
items=['pages','hits','bandwidth','visits']

url='http://192.168.1.199/api_jsonrpc.php'
zbx_api_headers={'Content-Type':'application/json-rpc'}    #定义通过zabbix api操作时必带的header

#取得用于zabbix api认证的token,通过用户名密码请求api生成
#生成方式请参考api文档,有个这个token,可以省去账号密码认证
api_auth="738024dfda33cc6020fb1f5e3617" 

#这里我在前期实验的时候,手动添加了几个item了,所以这里先取出template里已经存在的item,以便后期创建时过滤掉这些item
exist_items_filter={    #通过zabbix api查询已经存在的web_pv[*,*]的item,这里是json格式的过滤条件
    "jsonrpc": "2.0",
    "method": "item.get",
    "params": {
        "output":[
            "name",
        ],
        "search": {
            "key_":"web_pv"
        }
    },
    "auth":api_auth,
    "id": 0
}
exist_items=requests.post(url,headers=zbx_api_headers,json=exist_items_filter)

os.chdir(basedir)
sites=os.listdir(path='.')

def create_item():
    for site in sites:
        for item in items:
            if site+'-'+item not in exist_items.text:
                #先给不同情况下的units和multiplier赋值
                if item=='pages' or item=='hits':
                    units='万'
                    multiplier=0.0001
                elif item=='bandwidth':
                    units='B'
                    multiplier=1
                else:
                    units=''
                    multiplier=1
                #定义创建item的json数据格式
                num=10
                create_item_post={
                    "jsonrpc": "2.0",
                    "method": "item.create",
                    "params": {
                        "name": site+','+item,
                        "key_": "www_pv["+site+','+item+"]",
                        "hostid": "10134",
                        "type": 0,
                        "value_type": 3,
                        "history": 7,
                        "delay": 28800,
                        "units": units,
                        "applications": [774],
                        "interfaceid": "0",
                        "formula": multiplier
                    },
                    "auth": api_auth,
                    "id": num
                }
                try:

                    create_item_result=requests.post(url,headers=zbx_api_headers,json=create_item_post)            
                    #打印处理每个条目的结果
                    print('{}-{}: return_code {} details {}'.format(site,item,create_item_result.status_code,create_item_result.json))
                    num+=1
                except:
                    print('{}-{}: error'.format(site,item))
                    import sys
                    sys.exit(255)

#create_item()

#update函数,其实是我在执行create_item()的时候将key的名字写错了,无奈在写一个update_item()吧
def update_item():
    num=100    #对应zbx api中的id字段,随意指定,确保每次调用api时该值不同即可(这里用自增的方式)

    #定义更新item的json数据格式
    update={
        "jsonrpc": "2.0",
        "method": "item.update",
        "params": {
            "itemid": "",
            "key_": ""
        },
        "auth": api_auth,
        "id": num
    }

    #取得site pv模板下所有错误的item(key以www_py开头的),hostid的值实际为template site PV模板的templateid
    wrong_items_filter={
            "jsonrpc": "2.0",
            "method": "item.get",
            "params": {
               "output":["key_","hostid"],
                "search": {"hostid":"10134","key_":"www_pv"}
            },
            "auth": api_auth,
            "id": 0
        }

    wrong_items=requests.post(url,headers=zbx_api_headers,json=wrong_items_filter).json()['result']    #wrong_items为list

    for wrong_item in wrong_items:
        if wrong_item['hostid'] != '10119':    #img2从template site pv继承而来 所以这里每个item对应两条记录对应template site pv的hostid:10134和img2的hostid:10119,所以不需要修改img2的
            update['params']['itemid']=wrong_item['itemid']
            update['params']['key_']=wrong_item['key_'].replace('www','web',1)            
            try:
                update_item_result=requests.post(url,headers=zbx_api_headers,json=update)
                print('{} ---- details {}'.format(wrong_item['key_'],update_item_result.json()))
                num+=1
            except:
                print('{}-{}: error'.format(site,item))
                import sys
                sys.exit(255)
#update_item()

后续的批量生成image和生成screen都可以通过zbx 的API来完成,这里就不再列举了

ok,最后看两张zabbix生成的靓图吧

未分类

未分类

这个Python资源在GitHub上标星超8000,现在被翻译成了中文

未分类

最近,GitHub上一个关于Python的工程完工了。

一个名为“暮晨”的贡献者,把一个非常有趣的Python项目,翻译成了中文版。

这个项目是《What the f*ck Python!》,专门介绍 Python 里面那些奇奇怪怪的语言坑。

未分类

关于项目

项目的主体构成部分就是示例,一共分为5个部分,分别是:

Strain your brain!/大脑运动!

未分类

Appearances are deceptive!/外表是靠不住的!

未分类

Watch out for the landmines!/小心地雷!

未分类

The Hidden treasures!/隐藏的宝藏!

未分类

Miscellaneous/杂项

未分类

以上,总计51个示例。

每一个示例的结构都是一样的,以“Mutating the immutable!/强人所难”为例:

首先,会给出代码:

some_tuple = ("A", "tuple", "with", "values")
another_tuple = ([1, 2], [3, 4], [5, 6])

然后,给出Output( Python version):

>>> some_tuple[2] = "change this"
TypeError: 'tuple' object does not support item assignment
>>> another_tuple[2].append(1000) # 这里不出现错误
>>> another_tuple
([1, 2], [3, 4], [5, 6, 1000])
>>> another_tuple[2] += [99, 999]
TypeError: 'tuple' object does not support item assignment
>>> another_tuple
([1, 2], [3, 4], [5, 6, 1000, 99, 999])

然后,对意外输出的结果进行简短的描述,在这个示例中,就是:

我还以为元组是不可变的呢…

接下来,就会对示例进行说明,简要叙述发生了什么以及为什么会发生。如有必要, 也会举例说明。

在这个示例中是这样的:

  • 引用 https://docs.python.org/2/reference/datamodel.html
不可变序列 不可变序列的对象一旦创建就不能再改变。(如果对象包含对其他对象的引用,则这些其他对象可能是可变的并且可能会被修改; 但是,由不可变对象直接引用的对象集合不能更改。)
  • += 操作符在原地修改了列表. 元素赋值操作并不工作, 但是当异常抛出时, 元素已经在原地被修改了。

有些地方,贡献者还会给出译注,比如整个示例中就是:

对于不可变对象, 这里指tuple, +=并不是原子操作, 而是extend和=两个动作, 这里=操作虽然会抛出异常, 但 extend 操作已经修改成功了。

其他还有50个示例,等你来看~

怎么使用?

当然,要学习一下怎么使用这个资源。项目贡献者在用法部分表示,最好依次阅读下面的示例。

然后,在阅读每一个示例的时候,这样做:

仔细阅读设置例子最开始的代码。阅读输出结果。确认结果是否如你所料。确认你是否知道这背后的原理。如果不知道, 深呼吸然后阅读说明 (如果你还是看不明白, 别沉默!可以提问题)。如果知道, 给自己点奖励, 然后去看下一个示例。

此外,还可以在命令行阅读 WTFpython,有 pypi 包 和 npm 包(支持代码高亮),不过都是英文版的。

关于作者

这个项目的原作者,是一个名为Satwik Kansal的印度小哥。

未分类

GitHub上的介绍称,在深度学习和去中心化应用方面是一个“老司机”。

目前,英文版资源,标星已经8.3k了。

未分类

传送门

中文版:

https://github.com/leisurelicht/wtfpython-cn

英文原版:

https://github.com/satwikkansal/wtfpython

— 完 —

python玩转街机游戏,操作亲民!

未分类

这是一个允许你在几乎任何街机游戏中训练你的强化学习算法的Python库,它目前在Linux系统上可用。通过这个工具包,你可以定制算法逐步完成游戏过程,同时接收每一帧的数据和内部存储器地址值以跟踪游戏状态,以及发送与游戏交互的动作。

安装

GitHub地址:github.com/M-J-Murray/MAMEToolkit/blob/master/README.md

你可以用pip安装这个库,只需运行以下命令:

pip install MAMEToolkit

演示:街霸

未分类

街霸是史上最经典的游戏之一。现在工具包内包含的街霸版本是街头霸王3:三度冲击(Japan 990608, NO CD),我们以此为例,用以下代码写一个随机智能体:

import random

from MAMEToolkit.sf_environment import Environment

roms_path = "roms/"

env = Environment("env1", roms_path)

env.start()

while True:

   move_action = random.randint(0, 8)

   attack_action = random.randint(0, 9)

   frames, reward, round_done, stage_done, game_done = env.step(move_action, attack_action)

   if game_done:

       env.new_game()

   elif stage_done:

       env.next_stage()

   elif round_done:

       env.next_round()

支持hogwild!

hogwild!? Niu等人引入了一个叫做 Hogwild! 的更新策略,可以使 SGD 可以在多 CPU 上并行更新。处理器在无需对参数加锁的情况下就可以访问共享内存。但仅在输入的是稀疏数据时才有效,因为每次更新仅修改所有参数的一小部分。他们展示了在这种情况下,更新策略几乎可以达到一个最优的收敛率,因为处理器不太可能覆盖掉有用的信息。

from threading import Thread

import random

from MAMEToolkit.sf_environment import Environment

def run_env(env):

   env.start()

   while True:

       move_action = random.randint(0, 8)

       attack_action = random.randint(0, 9)

       frames, reward, round_done, stage_done, game_done = env.step(move_action, attack_action)

       if game_done:

           env.new_game()

       elif stage_done:

           env.next_stage()

       elif round_done:

           env.next_round()

def main():

   workers = 8

   # Environments must be created outside of the threads

   roms_path = "roms/"

   envs = [Environment(f"env{i}", roms_path) for i in range(workers)]

   threads = [Thread(target=run_env, args=(envs[i], )) for i in range(workers)]

   [thread.start() for thread in threads]

建立自己的游戏环境

这个工具包之所以易于上手,是因为它和模拟器本身不需要太多交互,只需注意两点——一是查找你关注的内部状态相关联的内存地址值,二是用选取的环境跟踪状态。你可以用MAME Cheat Debugger,它会反馈游戏的内存地址值如何随时间变化。如果要创建游戏模拟,你得先获得正在模拟的游戏的ROM,并知道MAME使用的游戏ID,比如街霸的ID是’sfiii3n’。

游戏ID

你可以通过运行以下代码找到游戏的ID

from MAMEToolkit.emulator import Emulator

emulator = Emulator("env1", "", "", memory_addresses)

这个命令会打开MAME仿真器。你可以搜索游戏列表以找到想要的游戏,游戏的ID位于游戏标题末尾的括号中。

内存地址

如果获得了ID,也有了想要跟踪的内存地址,你可以开始模拟:

from MAMEToolkit.emulator import Emulator

from MAMEToolkit.emulator import Address

roms_path = "roms/"

game_id = "sfiii3n"

memory_addresses = {

       "fighting": Address('0x0200EE44', 'u8'),

       "winsP1": Address('0x02011383', 'u8'),

       "winsP2": Address('0x02011385', 'u8'),

       "healthP1": Address('0x02068D0B', 's8'),

       "healthP2": Address('0x020691A3', 's8')

   }

emulator = Emulator("env1", roms_path, "sfiii3n", memory_addresses)

这会启动仿真器,并在工具包连接到模拟器进程时暂停。

分步运行仿真器

连接工具箱后,你可以分步运行仿真器:

data = emulator.step([])

frame = data["frame"]

is_fighting = data["fighting"]

player1_wins = data["winsP1"]

player2_wins = data["winsP2"]

player1_health = data["healthP1"]

player2_health = data["healthP2"]

step函数会把帧数据作为NumPy矩阵返回,同时,它也会返回该时间步长的所有内存地址整数值。

如果要向仿真器输入动作,你还需要确定游戏支持的输入端口和字段。比如玩街霸需要先投币,这个代码是:

from MAMEToolkit.emulator import Action

insert_coin = Action(':INPUTS', 'Coin 1')

data = emulator.step([insert_coin])

要确定哪些端口可用,请使用list actions命令:

from MAMEToolkit.emulator import list_actions

roms_path = "roms/"

game_id = "sfiii3n"

print(list_actions(roms_path, game_id))

下面这个返回的列表就包含街霸环境中可用于向步骤函数发送动作的所有端口和字段:

[

   {'port': ':scsi:1:cdrom:SCSI_ID', 'field': 'SCSI ID'},

   {'port': ':INPUTS', 'field': 'P2 Jab Punch'},

   {'port': ':INPUTS', 'field': 'P1 Left'},

   {'port': ':INPUTS', 'field': 'P2 Fierce Punch'},

   {'port': ':INPUTS', 'field': 'P1 Down'},

   {'port': ':INPUTS', 'field': 'P2 Down'},

   {'port': ':INPUTS', 'field': 'P2 Roundhouse Kick'},

   {'port': ':INPUTS', 'field': 'P2 Strong Punch'},

   {'port': ':INPUTS', 'field': 'P1 Strong Punch'},

   {'port': ':INPUTS', 'field': '2 Players Start'},

   {'port': ':INPUTS', 'field': 'Coin 1'},

   {'port': ':INPUTS', 'field': '1 Player Start'},

   {'port': ':INPUTS', 'field': 'P2 Right'},

   {'port': ':INPUTS', 'field': 'Service 1'},

   {'port': ':INPUTS', 'field': 'Coin 2'},

   {'port': ':INPUTS', 'field': 'P1 Jab Punch'},

   {'port': ':INPUTS', 'field': 'P2 Up'},

   {'port': ':INPUTS', 'field': 'P1 Up'},

   {'port': ':INPUTS', 'field': 'P1 Right'},

   {'port': ':INPUTS', 'field': 'Service Mode'},

   {'port': ':INPUTS', 'field': 'P1 Fierce Punch'},

   {'port': ':INPUTS', 'field': 'P2 Left'},

   {'port': ':EXTRA', 'field': 'P2 Short Kick'},

   {'port': ':EXTRA', 'field': 'P2 Forward Kick'},

   {'port': ':EXTRA', 'field': 'P1 Forward Kick'},

   {'port': ':EXTRA', 'field': 'P1 Roundhouse Kick'},

   {'port': ':EXTRA', 'field': 'P1 Short Kick'}

]

仿真器类还有一个frame_ratio参数,可用于调整算法所见的帧速率。默认情况下,MAME以每秒60帧的速度生成帧,如果你觉得这太多了,想把它改成每秒20帧,可以输入以下代码:

from MAMEToolkit.emulator import Emulator

emulator = Emulator(roms_path, game_id, memory_addresses, frame_ratio=3)

未分类

MAME性能基准测试

目前这个工具包的开发和测试已在8核AMD FX-8300 3.3GHz CPU以及3GB GeForce GTX 1060 GPU上完成。在使用单个随机智能体的情况下,街头霸王环境可以以正常游戏速度的600%+运行。而如果是用8个随机智能体进行hogwild!训练,环境可以以正常游戏速度的300%+运行。

ConvNet智能体

为了确保工具包能够训练算法,作者还设置了一个简单的5层ConvNet,只需少量调整,你就可以用它进行测试。在街霸实验中,这个算法能够成功学习到游戏的一些简单技巧,比如连击(combo)和格挡(blocking)。街霸本身的游戏机制是分成10个关卡(难度递增),玩家在每个关卡都要迎战不同的对手。刚开始的时候,这个智能体平均只能打到第2关。但在经过2200次训练后,它平均能打到第5关。

至于智能体的学习率,它是用每一局智能体所造成的净伤害和所承受的伤害来计算的。

python安装教程(Windows系统,python3.7为例)

1. 在python的官网下载python对应版本:https://www.python.org/downloads/windows/

64位下载Windows x86-64 executable installer 版本

32位下载Windows x86 executable installer 版本

打开链接如下图,版本会一直更新,选择任意一个适合自己电脑的版本就好

未分类

2. 勾选 Add python to PATH 添加路径

安装界面点击Customize installation 自定义安装

未分类

3. 不改变默认进行Next下一步

未分类

4. 选择一个自己喜欢的安装位置

点击Install开始安装

未分类

5. 等待进度条加载完毕

未分类

6. 安装完毕,点击Close关闭

若方框位置出现管理员字样则点击授权再关闭

未分类

7. 验证:运行cmd

进入到自己的安装目录下,运行语句:python -V

若显示出Python对应版本则表示安装成功

未分类

让你事半功倍的小众Python库

Python 是世界上发展最快的编程语言之一。它一次又一次地证明了自己在开发人员和跨行业的数据科学中的实用性。Python 及其机器学习库的整个生态系统使全世界的用户(无论新手或老手)都愿意选择它。Python 成功和受欢迎的原因之一是存在强大的库,这些库使 Python 极具创造力且运行快速。然而,使用 Pandas、Scikit-learn、Matplotlib 等常见库在解决一些特殊的数据问题时可能并不实用,本文介绍的这些非常见库可能更有帮助。

WGET

提取数据,特别是从网络中提取数据是数据科学家的重要任务之一。Wget 是一个免费的工具,用于以非交互式方式从 Web 上下载文件。它支持 HTTP、HTTPS 和 FTP 协议,通过 HTTP 代理进行检索。由于它是非交互式的,即使用户没有登录,它也可以在后台工作。所以,如果你想下载一个网站或一个页面上的所有图片,wget 会帮助你。

安装:

$ pip install wget

示例:

import wget
url = 'http://www.futurecrew.com/skaven/song_files/mp3/razorback.mp3'
filename = wget.download(url)
100% [................................................] 3841532 / 3841532
filename
'razorback.mp3'

对于那些在 python 中被处理datetimes困扰的人来说,Pendulum 是个好选择。它是一个 Python 包,用于简化 datetimes 操作。它是 Python「本机」类(native class)的代替。更多内容,请参阅文档:https://um.eustace.io/docs/# installation。

安装:

$ pip install pendulum

示例:

import pendulum
dt_toronto = pendulum.datetime(2012, 1, 1, tz='America/Toronto')
dt_vancouver = pendulum.datetime(2012, 1, 1, tz='America/Vancouver')
print(dt_vancouver.diff(dt_toronto).in_hours())
3

可以看出,当每个类的样本数量相等即平衡时,大多数分类算法的工作效果最好。但现实生活中充满了不平衡的数据集,这些数据集对机器学习的学习阶段和后续预测都有影响。创建这个库是为了解决这个问题。它与 scikit-learn 兼容,并且是 scikit-learn-contrib 项目的一部分。下次遇到不平衡的数据集时,可以尝试一下。

安装:

pip install -U imbalanced-learn

# or

conda install -c conda-forge imbalanced-learn

示例:

有关用法和示例,请参考:http://imbalancedlearn.org/en/stable/api.html。

FLASHTEXT

在 NLP 任务中,清理文本数据通常需要替换句子中的关键词或从句子中提取关键词。通常,这样的操作可以用正则表达式来完成,但是如果要搜索的词汇量过大,操作就会变得麻烦。Python 中基于 FlashText 算法的 FlashText 模块,为这种情况提供了一个合适的替代方案。FlashText 最大的优点是搜索词数量不影响运行时长。更多相关信息请见:https://flashtext.readthedocs.io/en/latest/#。

安装:

$ pip install flashtext

示例

提取关键词:

from flashtext import KeywordProcessor
keyword_processor = KeywordProcessor()
# keyword_processor.add_keyword(<unclean name>, <standardised name>)
keyword_processor.add_keyword('Big Apple', 'New York')
keyword_processor.add_keyword('Bay Area')
keywords_found = keyword_processor.extract_keywords('I love Big Apple and Bay Area.')
keywords_found
['New York', 'Bay Area']

替换关键词:

keyword_processor.add_keyword('New Delhi', 'NCR region')
new_sentence = keyword_processor.replace_keywords('I love Big Apple and new delhi.')
new_sentence
'I love New York and NCR region.'

更多使用示例,请参阅官方文档。

FUZZYWUZZY

虽然名字听起来很奇怪,但涉及到字符串匹配时,fuzzywuzzy 是一个非常有用的库,可以很容易地实现诸如字符串比较比率、token 比率等操作。对于匹配不同数据库中的记录也很方便。

安装:

$ pip install fuzzywuzzy

示例:

from fuzzywuzzy import fuzz
from fuzzywuzzy import process
# Simple Ratio
fuzz.ratio("this is a test", "this is a test!")
97
# Partial Ratio
fuzz.partial_ratio("this is a test", "this is a test!")
 100

更多有趣的例子可以在 GitHub 上找到:https://github.com/seatgeek/fuzzywuzzy。

PYFLUX

时间序列分析是机器学习领域最常见的问题之一。PyFlux 是 Python 中为处理时间序列问题而创建的开源库。该库有一系列极好的时间序列模型,包括但不限于 ARIMA、 GARCH 和 VAR 模型。简而言之,PyFlux 提供了一个时间序列建模的概率方法。值得尝试。

安装:

pip install pyflux

示例:

有关用法和示例,请参考:https://pyflux.readthedocs.io/en/latest/index.html。

IPYVOLUME

交流结果是数据科学的一个基本方面。能够将结果可视化是一个很大的优势。IPyvolume 是一个用于在 Jupyter notebook 中可视化 3d 体积和字形(如 3d 散点图)的 Python 库,只需少量配置即可。然而,它目前还处于前 1.0 版。IPyvolume 的 volshow 之于 3d 数组,就像 matplotlib 的 imshow 之于 2d 数组一样。更多相关信息请见:https://ipyvolume.readthedocs.io/en/latest/?badge=latest。

安装:

Using pip
$ pip install ipyvolume
Conda/Anaconda
$ conda install -c conda-forge ipyvolume

DASH

Dash 是一个用于构建 web 应用程序的高效 Python 框架。它写在 Flask、Plotly.js 和 React.js 之上,将下拉列表、滑块和图形等 UI 元素与你的分析性 Python 代码直接相连,无需 javascript。Dash 非常适合构建数据可视化应用程序。然后这些应用程序可以在 web 浏览器中进行渲染。用户指南请见:https://dash.plot.ly/。

安装:

pip install dash==0.29.0 # The core dash backend

pip install dash-html-components==0.13.2 # HTML components

pip install dash-core-components==0.36.0 # Supercharged components

pip install dash-table==3.1.3 # Interactive DataTable component (new!)

示例:

下图示例显示了具有下拉功能的高度交互图。当用户在下拉列表中选择一个值时,应用程序代码会动态地将 Google Finance 的数据导出为 Pandas DataFrame。资源:https://gist.github.com/chriddyp/3d2454905d8f01886d651f207e2419f0。

未分类

GYM

来自 OpenAI 的 Gym 是一个开发和对比强化学习算法的工具包。它兼容于任何数值计算库,如 TensorFlow 或 Theano。Gym 库是一个测试问题的集合,也被称为环境——可以用它来计算你的强化学习算法。这些环境有一个共享的接口,允许你写通用算法。

安装:

pip install gym

示例:

运行环境 CartPole-v0 的 1000 个时间步骤实例,在每个步骤渲染环境。

未分类

阅读其他环境请见:https://gym.openai.com/。

结论

这些是作者为数据科学挑选的实用 python 库,而非常见的 numpy、panda 等。值得一试。

Python的闭包

Python代码中,可以定义嵌套函数,即在函数中再定义一个函数。嵌套函数有什么特别之处吗?因为闭包。

简单说,闭包就是嵌套的内层函数能够记住外层函数的namespace,在外层函数返回之后,内层函数还可以正常访问外层的这些变量。看如下代码:

def outer():
    msg = 'hello world'
    def inner():
        print(msg)
    return inner
>>> func = outer()
>>> func()
hello world

闭包有2个特点:

  1. inner能访问outer及其祖先函数的命名空间内的变量(局部变量,函数参数)。
  2. 调用outer已经返回了,但是它的命名空间被返回的inner对象引用,所以还不会被回收。

这部分想深入可以去了解Python的LEGB规则。

Python有了闭包,就可以创建函数的装饰器了。

Python中fnmatch模块的使用

fnmatch()函数匹配能力介于简单的字符串方法和强大的正则表达式之间,如果在数据处理操作中只需要简单的通配符就能完成的时候,这通常是一个比较合理的方案。此模块的主要作用是文件名称的匹配,并且匹配的模式使用的Unix shell风格。源码很简单:

"""Filename matching with shell patterns.

fnmatch(FILENAME, PATTERN) matches according to the local convention.
fnmatchcase(FILENAME, PATTERN) always takes case in account.

The functions operate by translating the pattern into a regular
expression.  They cache the compiled regular expressions for speed.

The function translate(PATTERN) returns a regular expression
corresponding to PATTERN.  (It does not compile it.)
"""
import os
import posixpath
import re
import functools

__all__ = ["filter", "fnmatch", "fnmatchcase", "translate"]

def fnmatch(name, pat):
    """Test whether FILENAME matches PATTERN.

    Patterns are Unix shell style:

    *       matches everything
    ?       matches any single character
    [seq]   matches any character in seq
    [!seq]  matches any char not in seq

    An initial period in FILENAME is not special.
    Both FILENAME and PATTERN are first case-normalized
    if the operating system requires it.
    If you don't want this, use fnmatchcase(FILENAME, PATTERN).
    """
    name = os.path.normcase(name)
    pat = os.path.normcase(pat)
    return fnmatchcase(name, pat)

@functools.lru_cache(maxsize=256, typed=True)
def _compile_pattern(pat):
    if isinstance(pat, bytes):
        pat_str = str(pat, 'ISO-8859-1')
        res_str = translate(pat_str)
        res = bytes(res_str, 'ISO-8859-1')
    else:
        res = translate(pat)
    return re.compile(res).match

def filter(names, pat):
    """Return the subset of the list NAMES that match PAT."""
    result = []
    pat = os.path.normcase(pat)
    match = _compile_pattern(pat)
    if os.path is posixpath:
        # normcase on posix is NOP. Optimize it away from the loop.
        for name in names:
            if match(name):
                result.append(name)
    else:
        for name in names:
            if match(os.path.normcase(name)):
                result.append(name)
    return result

def fnmatchcase(name, pat):
    """Test whether FILENAME matches PATTERN, including case.

    This is a version of fnmatch() which doesn't case-normalize
    its arguments.
    """
    match = _compile_pattern(pat)
    return match(name) is not None


def translate(pat):
    """Translate a shell PATTERN to a regular expression.

    There is no way to quote meta-characters.
    """

    i, n = 0, len(pat)
    res = ''
    while i < n:
        c = pat[i]
        i = i+1
        if c == '*':
            res = res + '.*'
        elif c == '?':
            res = res + '.'
        elif c == '[':
            j = i
            if j < n and pat[j] == '!':
                j = j+1
            if j < n and pat[j] == ']':
                j = j+1
            while j < n and pat[j] != ']':
                j = j+1
            if j >= n:
                res = res + '\['
            else:
                stuff = pat[i:j].replace('\','\\')
                i = j+1
                if stuff[0] == '!':
                    stuff = '^' + stuff[1:]
                elif stuff[0] == '^':
                    stuff = '\' + stuff
                res = '%s[%s]' % (res, stuff)
        else:
            res = res + re.escape(c)
    return r'(?s:%s)Z' % res

fnmatch的中的5个函数["filter", "fnmatch", "fnmatchcase", "translate"]

  • filter 返回列表形式的结果
def gen_find(filepat, top):
    """
    查找符合Shell正则匹配的目录树下的所有文件名
    :param filepat: shell正则
    :param top: 目录路径
    :return: 文件绝对路径生成器
    """
    for path, _, filenames in os.walk(top):
        for file in fnmatch.filter(filenames, filepat):
            yield os.path.join(path, file)
  • fnmatch
# 列出元组中所有的python文件
pyfiles = [py for py in ('restart.py', 'index.php', 'file.txt') if fnmatch(py, '*.py')]
# 字符串的 startswith() 和 endswith() 方法对于过滤一个目录的内容也是很有用的
  • fnmatchcase 区分大小写的文件匹配
# 这两个函数通常会被忽略的一个特性是在处理非文件名的字符串时候它们也是很有用的。 比如,假设你有一个街道地址的列表数据
address = [
    '5412 N CLARK ST',
    '1060 W ADDISON ST',
    '1039 W GRANVILLE AVE',
    '2122 N CLARK ST',
    '4802 N BROADWAY',
]
print([addr for addr in address if fnmatchcase(addr, '* ST')])
  • translate 这个似乎很少有人用到,前面说了fnmatch是Unix shell匹配风格,可以使用translate将其转换为正则表达式,举个栗子
shell_match = 'Celery_?*.py'
print(translate(shell_match))
# 输出结果:(?s:Celery_..*.py)Z

Celery_..*.py就是正则表达式的写法。

[译] 鲜为人知的数据科学 Python 库

Python 是一个很棒的语言。它是世界上发展最快的编程语言之一。它一次又一次地证明了在开发人员职位中和跨行业的数据科学职位中的实用性。整个 Python 及其库的生态系统使它成为全世界用户(初学者和高级用户)的合适选择。它的成功和流行的原因之一是它强大的第三方库的集合,这些库使它可以保持活力和高效。

在本文中,我们会研究一些用于数据科学任务的 Python 库,而不是常见的比如 panda、scikit-learn 和 matplotlib 等的库。尽管像 panda 和 scikit-learn 这样的库,是在机器学习任务中经常出现的,但是了解这个领域中的其它 Python 产品总是很有好处的。

Wget

从网络上提取数据是数据科学家的重要任务之一。Wget 是一个免费的实用程序,可以用于从网络上下载非交互式的文件。它支持 HTTP、HTTPS 和 FTP 协议,以及通过 HTTP 的代理进行文件检索。由于它是非交互式的,即使用户没有登录,它也可以在后台工作。所以下次当你想要下载一个网站或者一个页面上的所有图片时,wget 可以帮助你。

安装:

$ pip install wget

例子:

import wget
url = 'http://www.futurecrew.com/skaven/song_files/mp3/razorback.mp3'

filename = wget.download(url)
100% [................................................] 3841532 / 3841532

filename
'razorback.mp3'

Pendulum

对于那些在 python 中处理日期时间时会感到沮丧的人来说,Pendulum 很适合你。它是一个简化日期时间操作的 Python 包。它是 Python 原生类的简易替代。请参阅文档深入学习。

安装:

$ pip install pendulum

例子:

import pendulum

dt_toronto = pendulum.datetime(2012, 1, 1, tz='America/Toronto')
dt_vancouver = pendulum.datetime(2012, 1, 1, tz='America/Vancouver')

print(dt_vancouver.diff(dt_toronto).in_hours())

3

imbalanced-learn

可以看出,当每个类的样本数量基本相同时,大多数分类算法的效果是最好的,即需要保持数据平衡。但现实案例中大多是不平衡的数据集,这些数据集对机器学习算法的学习阶段和后续预测都有很大影响。幸运的是,这个库就是用来解决此问题的。它与 scikit-learn 兼容,是 scikit-lear-contrib 项目的一部分。下次当你遇到不平衡的数据集时,请尝试使用它。

安装:

pip install -U imbalanced-learn

# 或者

conda install -c conda-forge imbalanced-learn

例子:

使用方法和例子请参考文档 http://imbalanced-learn.org/en/stable/api.html

FlashText

在 NLP 任务中,清理文本数据往往需要替换句子中的关键字或从句子中提取关键字。通常,这种操作可以使用正则表达式来完成,但是如果要搜索的术语数量达到数千个,这就会变得很麻烦。Python 的 FlashText 模块是基于 FlashText 算法为这种情况提供了一个合适的替代方案。FlashText 最棒的一点是,不管搜索词的数量如何,运行时间都是相同的。你可以在这里了解更多内容。

安装:

$ pip install flashtext

例子:

提取关键字

from flashtext import KeywordProcessor
keyword_processor = KeywordProcessor()

# keyword_processor.add_keyword(<unclean name>, <standardised name>)

keyword_processor.add_keyword('Big Apple', 'New York')
keyword_processor.add_keyword('Bay Area')
keywords_found = keyword_processor.extract_keywords('I love Big Apple and Bay Area.')

keywords_found
['New York', 'Bay Area']

替换关键字

keyword_processor.add_keyword('New Delhi', 'NCR region')

new_sentence = keyword_processor.replace_keywords('I love Big Apple and new delhi.')

new_sentence
'I love New York and NCR region.'

更多实用案例,请参考官方文档。

Fuzzywuzzy

这个库的名字听起来很奇怪,但是在字符串匹配方面,fuzzywuzzy 是一个非常有用的库。可以很方便地实现计算字符串匹配度、令牌匹配度等操作,也可以很方便地匹配保存在不同数据库中的记录。

安装:

$ pip install fuzzywuzzy

例子:

from fuzzywuzzy import fuzz
from fuzzywuzzy import process

# 简单匹配度

fuzz.ratio("this is a test", "this is a test!")
97

# 模糊匹配度
fuzz.partial_ratio("this is a test", "this is a test!")
 100

更多有趣例子可以在 https://github.com/seatgeek/fuzzywuzzy 找到。

PyFlux

时间序列分析是机器学习领域中最常见的问题之一。PyFlux 是 Python 中的一个开源库,它是为处理时间序列问题而构建的。该库拥有一系列优秀的现代时间序列模型,包括但不限于 ARIMA、GARCH 和 VAR 模型。简而言之,PyFlux 为时间序列建模提供了一种概率方法。值得尝试一下。

安装

pip install pyflux

例子

详细用法和例子请参考官方文档 https://pyflux.readthedocs.io/en/latest/index.html

Ipyvolume

结果展示也是数据科学中的一个重要方面。能够将结果进行可视化将具有很大优势。IPyvolume 是一个可以在 Jupyter notebook 中可视化三维体和图形(例如三维散点图等)的 Python 库,并且只需要少量配置。但它目前还是 1.0 之前的版本阶段。用一个比较恰当的比喻来解释就是:IPyvolume 的 volshow 对于三维数组就像 matplotlib 的 imshow 对于二维数组一样好用。可以在这里获取更多。

使用 pip
$ pip install ipyvolume

使用 Conda/Anaconda
$ conda install -c conda-forge ipyvolume

例子

  • 动画

未分类

未分类

  • 体绘制

未分类

Dash

Dash 是一个高效的用于构建 web 应用程序的 Python 框架。它是在 Flask、Plotly.js 和 React.js 基础上设计而成的,绑定了很多比如下拉框、滑动条和图表的现代 UI 元素,你可以直接使用 Python 代码来写相关分析,而无需再使用 javascript。Dash 非常适合构建数据可视化应用程序。然后,这些应用程序可以在 web 浏览器中呈现。用户指南可以在这里获取。

安装

pip install dash==0.29.0  # 核心 dash 后端
pip install dash-html-components==0.13.2  # HTML 组件
pip install dash-core-components==0.36.0  # 增强组件
pip install dash-table==3.1.3  # 交互式 DataTable 组件(最新!)

例子

下面的例子展示了一个具有下拉功能的高度交互式图表。当用户在下拉菜单中选择一个值时,应用程序代码将动态地将数据从 Google Finance 导出到 panda DataFrame。源码在这里 https://gist.github.com/chriddyp/3d2454905d8f01886d651f207e2419f0

未分类

Gym

OpenAI 的 Gym 是一款用于增强学习算法的开发和比较工具包。它兼容任何数值计算库,如 TensorFlow 或 Theano。Gym 库是测试问题集合的必备工具,这个集合也称为环境 —— 你可以用它来开发你的强化学习算法。这些环境有一个共享接口,允许你进行通用算法的编写。

安装

pip install gym

例子

这个例子会运行 CartPole-v0 环境中的一个实例,它的时间步数为 1000,每一步都会渲染整个场景。

未分类

你可以在 https://gym.openai.com/ 获取其它环境的相关资料

总结

以上这些有用的数据科学 Python 库都是我精心挑选出来的,不是常见的如 numpy 和 pandas 等库。如果你知道其它库,可以添加到列表中来,请在下面的评论中提一下。另外别忘了先尝试运行一下它们。

MongoDB数据导入到ElasticSearch python代码实现

ElasticSearch对文本的搜索速度真的是神速呀,基本是毫秒级别的。对于大文本,简直就是秒飞MYSQL十条街。使用python实现:

es = Elasticsearch(['10.18.6.26:9200'])
ret = collection.find({})

# 删除mongo的_id字段,否则无法把Object类型插入到Elastic
map(lambda x:(del x['_id']),ret)

actions=

for idx,item in enumerate(ret):
    i={
        "_index":"jsl",
     "_type":"text",
     "_id":idx,
        "_source":{
            # 需要提取的字段
            "title":item.get('title'),
            "url":item.get('url')
        }
    }
    actions.append(i)


start=time.time()
helpers.bulk(es,actions)

end=time.time()-start
print(end)

运行下来,20W条数据,大概用了15秒左右全部导入ElasticSearch 数据库中。

python操作mongodb根据_id查询数据的实现方法

本文实例讲述了python操作mongodb根据_id查询数据的实现方法。分享给大家供大家参考。具体分析如下:

_id是mongodb自动生成的id,其类型为ObjectId,所以如果需要在python中通过_id查询,就需要转换类型

如果pymongo的版本号小于2.2,使用下面的语句导入ObjectId

from pymongo.objectid import ObjectId

如果pymongo的版本号大于2.2,则使用下面的语句

from bson.objectid import ObjectId

查询代码如下:

collection.find_one({'_id':ObjectId('50f0d76347f4ec148890ef1e')})