标签: Python3

  • Python django migrate 和makemigrations的实际应用举例

    Python django migrate 和makemigrations的实际应用举例

    测试环境中生成迁移

    在你改动了 model.py的内容之后执行下面的命令:

    python manager.py makemigrations

    相当于 在该app下建立 migrations目录,并记录下你所有的关于modes.py的改动,比如0001_initial.py,

     但是这个改动还没有作用到数据库文件

    你可以手动打开这个文件,看看里面是什么

    生产环境中生成执行迁移

    python manager.py migrate

    将该改动作用到数据库文件,比如产生table之类

  • Python机房流量调度系统 环境配置

    Python机房流量调度系统 环境配置

    前面我们写了Python3 机房间流量调度系统,下面我们记录一下安装环境配置。

    升级Linux系统下的Python版本

    CentOS上安装配置Python3.7 编译安装图文教程

    安装docker

    yum install docker git screen -y
    systemctl start docker.service
    mkdir -p /data/mysqlData

    配置docker mysql

    docker run -d -p 3307:3306 -v /data/mysqlData/:/var/lib/mysql --privileged=true --name jmysql -e MYSQL_ROOT_PASSWORD='laoji.org' mysql 

    进入mysql容器,配置mysql密码

    docker exec -it jmysql /bin/bash
    mysql -uroot -p
    use mysql;
    alter user 'root'@'%' identified with mysql_native_password by 'laoji.org';
    \q
    exit 

    后面导入数据等不再详细说明。

  • Django数据库分表代码实例

    Django数据库分表代码实例

    app名称为‘core’,基本的models.py文件内容如下:

    class Province(models.Model):
        name = models.CharField(u'省份名称',max_length=32)
        code = models.IntegerField(verbose_name=u'区号', unique=True)
        
        def __unicode__(self):
            return self.name
        
        class Meta:
            verbose_name = u'省份列表'
            verbose_name_plural = u'省份列表'

    法I:

    重构 manager 中的 get_query_set() 方法。

    需要说明的是:在 django 默认情况下,会为每一个models 类添加一个名为 objects 的 Manager,这个就是 Province.objects.all() 中 objects 的由来。

    修改后的 models.py 代码如下,表结构必须一致:

    # coding:utf-8
    from django.db import models
    # Create your models here.
    class ProvinceManager(models.Manager):
        def get_queryset(self):
    #         return super(ProvinceManager, self).get_queryset().filter(id=1)
            self.model._meta.db_table = 'core_province_1' # 我的app名为core
            return super(ProvinceManager, self).get_queryset()10         11     
    class Province(models.Model):
        name = models.CharField(u'省份名称',max_length=32)
        code = models.IntegerField(verbose_name=u'区号', unique=True)
        
        objects = ProvinceManager()
        
        def __unicode__(self):
            return self.name
        
        class Meta:
            verbose_name = u'省份列表'
            verbose_name_plural = u'省份列表'

    可以多写几个 Manager 来对应不同的表,同时对应多写几个不同的 objects(可以随意起名),在调用时调用相应的 Manager。

    法II:

    在哪里调用就在哪里更改。更改处添加代码如下:

    from core.models import Province
    Province._meta.db_table = 'core_prvoince_2'
    rows = Province.objects.all() 

    总结:

    不论哪种方法,其主要还是要更改 models 的 _meta.db_table 的值

  • Python3 生成随机密码 代码实例

    Python3 生成随机密码 代码实例

    Python3 生成随机密码 代码实例

    def generate_password():
        import random
        length = 64
        seed = '1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
        print(''.join(random.choice(seed) for _ in range(length)))
    
  • ‘WSGIRequest’ object has no attribute ‘Get’解决办法

    ‘WSGIRequest’ object has no attribute ‘Get’解决办法

    出现问题

    ‘WSGIRequest’ object has no attribute ‘Get’

    解决办法

    这个原因是request只有GET和POST方法,注意都是大写,如果你也遇到这个问题,可以全局查找一下,哪里写成小写了,很简单,问题就解决了

    request.GET.get('a')
    request.POST.get('b')

  • Python3 机房间流量调度系统

    Python3 机房间流量调度系统

    场景需求

    公司有很多机房,但是由于机房见的流量价格不一致,所以如果可以的话需要尽量使用便宜的流量。以缩减流量的成本。

    解决方案

    使用2台设备作为调度中心,将所有需要调出的流量全部调到调度中心设备。然后将这些流量切成固定片数(80片)。然后通过Python脚本计算机房上联速率后决定切片去不同的机房。然后登录调度中心的交换机执行对应的traffic-policy命令。

    这里老季也是第一次使用Python,可以说是完完全全的边学python3边写项目。

    这里使用的是Django框架来写,因为简单快捷。Django适合一个人快速开发,可以在后台少些很多很多代码。

    相关文章

    实现功能

    一阶段调度( 所有机房流量均小于后台设定的95上限值)

    在流量足够的场景下,将调出的流量调度到每个机房,使得每个机房都不超过各机房的95上限。

    二阶调度(所有机房流量均大于95上限)

    在所有机房流量均超过95上限的场景下,通过后台设定的权重,优先将流量调度到权重小的机房。使其小于95阀值。

    当机房流量大于95阀值时,将超出95阀值的流量调往下一个机房。

  • Python3 如何只允许一个脚本实例运行?

    Python3 如何只允许一个脚本实例运行?

    场景需求

    Python3中如何保证同样的脚本在运行时只允许一个运行实例,不允许新建一个脚本重新运行?我们这里使用文件锁的方式,简单方便。下面给出代码实例。

    代码实例

    import sys ,os 
    def lockFile(lockfilepath):
        '''
        :param lockfilepath:文件锁,文件名
        '''
        if os.path.exists(lockfilepath):
            #文件存在,说明脚本正在执行
            logging.critical("×××××× 脚本正在执行中,退出本次调度 ××××××")
            sys.exit()
        else:
            #文件不存在,创建文件,并执行任务。
            logging.info('已开启文件锁 %s',lockfilepath)
            subprocess.getoutput('echo "" > '+lockfilepath)
            return True
    def unLockFile(lockfilepath):
        os.remove(lockfilepath)
        logging.info('已释放文件锁 %s',lockfilepath)

    调用方法

    lockFileName = '/tmp/SCHEDULINGVLAN.Lock'
    func.lockFile(lockFileName)
    #.... do something else ....
    func.unLockFile(lockFileName)
    

    这里lockfileName设定了文件存储位置。

    如果程序意外出错,执行不到程序的最下面释放文件锁的话,永远无法新起脚本进程。

    当然这里也可以使用try / catch的方式来捕捉以外错误,同时释放文件锁。

  • Python微信红包代码实例 微信红包的架构设计

    Python微信红包代码实例 微信红包的架构设计

    Python微信红包算法实例

    #!/usr/bin/env python
    # coding: utf-8
    import random
    # m : 红包个数
    # n : 红包人数
    # packet : 本次抢到的金额 , 所有金额以分为计算
    def redEnvelope(m,n):
        remain = m*100 #剩余金额
        nn = n #剩余人数
        for i in range(1,n):
            if remain == 0 :
                print('已经全部发完了')
            else :
                packet = random.randint(1,int(remain/nn*2))
                nn -= 1
                remain -= packet 
                print('第%d位成员红包的金额为%.2f元 , 余额为%.2f , 剩余%d人未领红包'%(i,packet/100,remain/100,nn))
        print('最后一个成员红包金额为%.2f元'%(remain/100))

    Python调用方法

    redEnvelope(100,4)

    运行结果

    第1位成员红包的金额为45.65元 , 余额为54.35 , 剩余3人未领红包
    第2位成员红包的金额为16.10元 , 余额为38.25 , 剩余2人未领红包
    第3位成员红包的金额为20.98元 , 余额为17.27 , 剩余1人未领红包
    最后一个成员红包金额为17.27元

    概况:2014年微信红包使用数据库硬抗整个流量,2015年使用cache抗流量。

    微信的金额什么时候算?

    答:微信金额是拆的时候实时算出来,不是预先分配的,采用的是纯内存计算,不需要预算空间存储。。
    采取实时计算金额的考虑:预算需要占存储,实时效率很高,预算才效率低。

    实时性:为什么明明抢到红包,点开后发现没有?

    答:2014年的红包一点开就知道金额,分两次操作,先抢到金额,然后再转账。
    2015年的红包的拆和抢是分离的,需要点两次,因此会出现抢到红包了,但点开后告知红包已经被领完的状况。进入到第一个页面不代表抢到,只表示当时红包还有。

    分配:红包里的金额怎么算?为什么出现各个红包金额相差很大?

    答:随机,额度在0.01和剩余平均值*2之间。
    例如:发100块钱,总共10个红包,那么平均值是10块钱一个,那么发出来的红包的额度在0.01元~20元之间波动。
    当前面3个红包总共被领了40块钱时,剩下60块钱,总共7个红包,那么这7个红包的额度在:0.01~(60/7*2)=17.14之间。
    注意:这里的算法是每被抢一个后,剩下的会再次执行上面的这样的算法(Tim老师也觉得上述算法太复杂,不知基于什么样的考虑)。 这样算下去,会超过最开始的全部金额,因此到了最后面如果不够这么算,那么会采取如下算法:保证剩余用户能拿到最低1分钱即可。 如果前面的人手气不好,那么后面的余额越多,红包额度也就越多,因此实际概率一样的。

    红包的设计

    答:微信从财付通拉取金额数据郭莱,生成个数/红包类型/金额放到redis集群里,app端将红包ID的请求放入请求队列中,如果发现超过红包的个数,直接返回。根据红包的裸祭处理成功得到令牌请求,则由财付通进行一致性调用,通过像比特币一样,两边保存交易记录,交易后交给第三方服务审计,如果交易过程中出现不一致就强制回归。

    发性处理:红包如何计算被抢完?

    答:cache会抵抗无效请求,将无效的请求过滤掉,实际进入到后台的量不大。cache记录红包个数,原子操作进行个数递减,到0表示被抢光。财付通按照20万笔每秒入账准备,但实际还不到8万每秒。

    通如何保持8w每秒的写入?

    答:多主sharding,水平扩展机器。

    据容量多少?

    答:一个红包只占一条记录,有效期只有几天,因此不需要太多空间。

    询红包分配,压力大不?

    答:抢到红包的人数和红包都在一条cache记录上,没有太大的查询压力。

    一个红包一个队列?

    答:没有队列,一个红包一条数据,数据上有一个计数器字段。

    有没有从数据上证明每个红包的概率是不是均等?

    答:不是绝对均等,就是一个简单的拍脑袋算法。

    拍脑袋算法,会不会出现两个最佳?

    答:会出现金额一样的,但是手气最佳只有一个,先抢到的那个最佳。

    每领一个红包就更新数据么?

    答:每抢到一个红包,就cas更新剩余金额和红包个数。

    红包如何入库入账?

    数据库会累加已经领取的个数与金额,插入一条领取记录。入账则是后台异步操作。

  • Python3 中如何实现冒泡排序算法?

    Python3 中如何实现冒泡排序算法?

    什么是冒泡排序算法?

    临近的两个元素进行比较,然后互换顺序,一趟走完之后最大的或者最小的元素排在第一个或者最后一个位置(最大或者最小看实际需求),给的的感觉就是一个小泡泡一直冒啊冒,所以有个好听的名字叫冒泡算法

    举个例子,有数组[10, 1, 18, 30, 23, 12, 7, 5, 18, 17],我们使用从小到大的排序方法

    第一趟,外排下标为0,对应的值为10

    内排开始

    ①下标0和下标1的值进行比较。10和1比,发现1比10小,进行互换,内排一次完成,结果是[1, 10, 18, 30, 23, 12, 7, 5, 18, 17]

    ②下标1和下标2的值进行比较。10和18比,10比18小,保持不变,结果是[1, 10, 18, 30, 23, 12, 7, 5, 18, 17]

    ③下标2和下标3的值进行比较。18和30比,18比30小,保持不变,结果是[1, 10, 18, 30, 23, 12, 7, 5, 18, 17]

    ④下标3和下标4的值进行比较。30和23比,30比23大,进行互换,结果是[1, 10, 18, 23, 30, 12, 7, 5, 18, 17]

    ……一直这样紧邻的两个数比下去,第一趟外排结束,结果是[1, 10, 18, 23, 12, 7, 5, 18, 17, 30],我们发现,我们经过了这一次排序,把最大值30送到了右侧

    第二趟,外排下标是1

    内排开始

    ①下标0和下标1的值进行比较。1和10比,1比10小,保持不变,内排一次完成,结果是[1, 10, 18, 23, 12, 7, 5, 18, 17, 30]

    ②下标1和下标2的值进行比较。10和18比,10比18小,保持不变,内排二次完成,结果是[1, 10, 18, 23, 12, 7, 5, 18, 17, 30]

    …………

    ④下标3和下标4的值进行比较。12和23比,23比12小,进行互换,内排四次完成,结果是[1, 10, 18, 12, 23, 7, 5, 18, 17, 30]

    ⑤下标4和下标5的值进行比较。23和7比较,23比7大,进行互换,内排五次完成,结果是[1, 10, 18, 12, 7, 23, 5, 18, 17, 30]

    …………经过一系列排序,结束,结果为[1, 10, 18, 12, 7, 5, 18, 17, 23, 30],这个时候我们把第二大的数据23放到正确的位置

    第三趟

    …………结果为[1, 10, 12, 7, 5, 18, 17, 18, 23, 30]

    …………

    …………

    最终结果为[1, 5, 7, 10, 12, 17, 18, 18, 23, 30]

    至此,排序完成。

    Python3 代码实例

    #!/usr/bin/python
    # -*- coding: utf-8 -*-
    #冒泡排序
     
    def bubble_sort(the_list):
        i = 0
        while i < len(the_list):
            j = 0
            while j < len(the_list)-1:
                print(the_list[j],the_list[j+1])
                if the_list[j] > the_list[j+1]:
                    the_list[j], the_list[j+1] = the_list[j+1], the_list[j]
                j = j+1
                print(the_list)
            print("======"+str(the_list))
            i = i+1
        return the_list
    if __name__ == '__main__':
        the_list = [10, 1, 18, 30, 23, 12, 7, 5, 18, 17]
        print("排序前:" + str(the_list))
        print("排序后:" + str(bubble_sort(the_list)))
    

    运行结果

    排序前:[10, 1, 18, 30, 23, 12, 7, 5, 18, 17]
    10 1
    [1, 10, 18, 30, 23, 12, 7, 5, 18, 17]
    10 18
    [1, 10, 18, 30, 23, 12, 7, 5, 18, 17]
    18 30
    [1, 10, 18, 30, 23, 12, 7, 5, 18, 17]
    30 23
    [1, 10, 18, 23, 30, 12, 7, 5, 18, 17]
    30 12
    [1, 10, 18, 23, 12, 30, 7, 5, 18, 17]
    30 7
    [1, 10, 18, 23, 12, 7, 30, 5, 18, 17]
    30 5
    [1, 10, 18, 23, 12, 7, 5, 30, 18, 17]
    30 18
    [1, 10, 18, 23, 12, 7, 5, 18, 30, 17]
    30 17
    [1, 10, 18, 23, 12, 7, 5, 18, 17, 30]
    ======[1, 10, 18, 23, 12, 7, 5, 18, 17, 30]
    1 10
    [1, 10, 18, 23, 12, 7, 5, 18, 17, 30]
    10 18
    [1, 10, 18, 23, 12, 7, 5, 18, 17, 30]
    18 23
    [1, 10, 18, 23, 12, 7, 5, 18, 17, 30]
    23 12
    [1, 10, 18, 12, 23, 7, 5, 18, 17, 30]
    23 7
    [1, 10, 18, 12, 7, 23, 5, 18, 17, 30]
    23 5
    [1, 10, 18, 12, 7, 5, 23, 18, 17, 30]
    23 18
    [1, 10, 18, 12, 7, 5, 18, 23, 17, 30]
    23 17
    [1, 10, 18, 12, 7, 5, 18, 17, 23, 30]
    23 30
    [1, 10, 18, 12, 7, 5, 18, 17, 23, 30]
    ======[1, 10, 18, 12, 7, 5, 18, 17, 23, 30]
    1 10
    [1, 10, 18, 12, 7, 5, 18, 17, 23, 30]
    10 18
    [1, 10, 18, 12, 7, 5, 18, 17, 23, 30]
    18 12
    [1, 10, 12, 18, 7, 5, 18, 17, 23, 30]
    18 7
    [1, 10, 12, 7, 18, 5, 18, 17, 23, 30]
    18 5
    [1, 10, 12, 7, 5, 18, 18, 17, 23, 30]
    18 18
    [1, 10, 12, 7, 5, 18, 18, 17, 23, 30]
    18 17
    [1, 10, 12, 7, 5, 18, 17, 18, 23, 30]
    18 23
    [1, 10, 12, 7, 5, 18, 17, 18, 23, 30]
    23 30
    [1, 10, 12, 7, 5, 18, 17, 18, 23, 30]
    ======[1, 10, 12, 7, 5, 18, 17, 18, 23, 30]
    1 10
    [1, 10, 12, 7, 5, 18, 17, 18, 23, 30]
    10 12
    [1, 10, 12, 7, 5, 18, 17, 18, 23, 30]
    12 7
    [1, 10, 7, 12, 5, 18, 17, 18, 23, 30]
    12 5
    [1, 10, 7, 5, 12, 18, 17, 18, 23, 30]
    12 18
    [1, 10, 7, 5, 12, 18, 17, 18, 23, 30]
    18 17
    [1, 10, 7, 5, 12, 17, 18, 18, 23, 30]
    18 18
    [1, 10, 7, 5, 12, 17, 18, 18, 23, 30]
    18 23
    [1, 10, 7, 5, 12, 17, 18, 18, 23, 30]
    23 30
    [1, 10, 7, 5, 12, 17, 18, 18, 23, 30]
    ======[1, 10, 7, 5, 12, 17, 18, 18, 23, 30]
    1 10
    [1, 10, 7, 5, 12, 17, 18, 18, 23, 30]
    10 7
    [1, 7, 10, 5, 12, 17, 18, 18, 23, 30]
    10 5
    [1, 7, 5, 10, 12, 17, 18, 18, 23, 30]
    10 12
    [1, 7, 5, 10, 12, 17, 18, 18, 23, 30]
    12 17
    [1, 7, 5, 10, 12, 17, 18, 18, 23, 30]
    17 18
    [1, 7, 5, 10, 12, 17, 18, 18, 23, 30]
    18 18
    [1, 7, 5, 10, 12, 17, 18, 18, 23, 30]
    18 23
    [1, 7, 5, 10, 12, 17, 18, 18, 23, 30]
    23 30
    [1, 7, 5, 10, 12, 17, 18, 18, 23, 30]
    ======[1, 7, 5, 10, 12, 17, 18, 18, 23, 30]
    1 7
    [1, 7, 5, 10, 12, 17, 18, 18, 23, 30]
    7 5
    [1, 5, 7, 10, 12, 17, 18, 18, 23, 30]
    7 10
    [1, 5, 7, 10, 12, 17, 18, 18, 23, 30]
    10 12
    [1, 5, 7, 10, 12, 17, 18, 18, 23, 30]
    12 17
    [1, 5, 7, 10, 12, 17, 18, 18, 23, 30]
    17 18
    [1, 5, 7, 10, 12, 17, 18, 18, 23, 30]
    18 18
    [1, 5, 7, 10, 12, 17, 18, 18, 23, 30]
    18 23
    [1, 5, 7, 10, 12, 17, 18, 18, 23, 30]
    23 30
    [1, 5, 7, 10, 12, 17, 18, 18, 23, 30]
    ======[1, 5, 7, 10, 12, 17, 18, 18, 23, 30]
    1 5
    [1, 5, 7, 10, 12, 17, 18, 18, 23, 30]
    5 7
    [1, 5, 7, 10, 12, 17, 18, 18, 23, 30]
    7 10
    [1, 5, 7, 10, 12, 17, 18, 18, 23, 30]
    10 12
    [1, 5, 7, 10, 12, 17, 18, 18, 23, 30]
    12 17
    [1, 5, 7, 10, 12, 17, 18, 18, 23, 30]
    17 18
    [1, 5, 7, 10, 12, 17, 18, 18, 23, 30]
    18 18
    [1, 5, 7, 10, 12, 17, 18, 18, 23, 30]
    18 23
    [1, 5, 7, 10, 12, 17, 18, 18, 23, 30]
    23 30
    [1, 5, 7, 10, 12, 17, 18, 18, 23, 30]
    ======[1, 5, 7, 10, 12, 17, 18, 18, 23, 30]
    1 5
    [1, 5, 7, 10, 12, 17, 18, 18, 23, 30]
    5 7
    [1, 5, 7, 10, 12, 17, 18, 18, 23, 30]
    7 10
    [1, 5, 7, 10, 12, 17, 18, 18, 23, 30]
    10 12
    [1, 5, 7, 10, 12, 17, 18, 18, 23, 30]
    12 17
    [1, 5, 7, 10, 12, 17, 18, 18, 23, 30]
    17 18
    [1, 5, 7, 10, 12, 17, 18, 18, 23, 30]
    18 18
    [1, 5, 7, 10, 12, 17, 18, 18, 23, 30]
    18 23
    [1, 5, 7, 10, 12, 17, 18, 18, 23, 30]
    23 30
    [1, 5, 7, 10, 12, 17, 18, 18, 23, 30]
    ======[1, 5, 7, 10, 12, 17, 18, 18, 23, 30]
    1 5
    [1, 5, 7, 10, 12, 17, 18, 18, 23, 30]
    5 7
    [1, 5, 7, 10, 12, 17, 18, 18, 23, 30]
    7 10
    [1, 5, 7, 10, 12, 17, 18, 18, 23, 30]
    10 12
    [1, 5, 7, 10, 12, 17, 18, 18, 23, 30]
    12 17
    [1, 5, 7, 10, 12, 17, 18, 18, 23, 30]
    17 18
    [1, 5, 7, 10, 12, 17, 18, 18, 23, 30]
    18 18
    [1, 5, 7, 10, 12, 17, 18, 18, 23, 30]
    18 23
    [1, 5, 7, 10, 12, 17, 18, 18, 23, 30]
    23 30
    [1, 5, 7, 10, 12, 17, 18, 18, 23, 30]
    ======[1, 5, 7, 10, 12, 17, 18, 18, 23, 30]
    1 5
    [1, 5, 7, 10, 12, 17, 18, 18, 23, 30]
    5 7
    [1, 5, 7, 10, 12, 17, 18, 18, 23, 30]
    7 10
    [1, 5, 7, 10, 12, 17, 18, 18, 23, 30]
    10 12
    [1, 5, 7, 10, 12, 17, 18, 18, 23, 30]
    12 17
    [1, 5, 7, 10, 12, 17, 18, 18, 23, 30]
    17 18
    [1, 5, 7, 10, 12, 17, 18, 18, 23, 30]
    18 18
    [1, 5, 7, 10, 12, 17, 18, 18, 23, 30]
    18 23
    [1, 5, 7, 10, 12, 17, 18, 18, 23, 30]
    23 30
    [1, 5, 7, 10, 12, 17, 18, 18, 23, 30]
    ======[1, 5, 7, 10, 12, 17, 18, 18, 23, 30]
    排序后:[1, 5, 7, 10, 12, 17, 18, 18, 23, 30]

  • 在Python3 Django框架 模板中如何使用条件判断?

    在Python3 Django框架 模板中如何使用条件判断?

    老季在本篇记录一下在Django的开发中,如何在模板中使用if判断条件。

    views.py

    # view 文件
    def func(request):
        ...
        return render(request,"index.html",{
            'current_user':"alex",
            'user_list':['alex','eric',
            'user_dict':{'k1':'v1','k2':'v2'}]
        })

    .html 模板

    # html 文件
    <html>
        ....
    <body>
        <div>{{current_user}}</div>
        <a>{{ user_list.0}}</a>
        # 条件判断
        {% if age %}
            <a> 有年龄<a>
        {% else %}
            <a> 无年龄<a>
        {% endif %}
        # 嵌套条件判断
        {% if age %}
            <a> 有年龄<a>
        {% if age > 16 %}
            <a>老男人<a>
        {% else %}
            <a>小男孩<a>
        {% else %}
            <a> 无年龄<a>
        {% endif %}
        <body>
    </html>
  • Python 登录交换机switch 巡检 拉取交换机配置信息

    Python 登录交换机switch 巡检 拉取交换机配置信息

    场景需求

    前面老季写了一个 PHP如何登录连接TELNET并执行交换机命令类 图文教程 ,最近项目中遇到了要换python3来登录交换机并拉取配置。这里我们直接贴出相关代码使用telnetlib类来登录交换机并拉取配置。

    我们在代码中可以处理交换机拉取配置时,内容过长,出现 --- More --- 需要按空格的场景。并且将所有交换机命令的返回值都进行了返回给调用方法。

    代码实例

    class TelnetClient():
        def __init__(self,):
            self.tn = telnetlib.Telnet()
            time.sleep(0.2)
        # 此函数实现telnet登录主机
        def login(self,host_ip,username,password,port=23):
            try:
                # self.tn = telnetlib.Telnet(host_ip,port=23)
                self.tn.open(host_ip,port)
            except:
                logging.critical('网络连接失败'+repr(host_ip))
                return False
            # 等待login出现后输入用户名,最多等待10秒
            self.tn.read_until(b'Username: ',timeout=1)
            self.tn.write(username.encode('ascii') + b'\n')
            self.tn.read_until(b'Password: ',timeout=1)
            self.tn.write(password.encode('ascii') + b'\n')
            # 延时两秒再收取返回结果,给服务端足够响应时间
            time.sleep(0.2)
            # 获取登录结果
            # read_very_eager()获取到的是的是上次获取之后本次获取之前的所有输出
            command_result = self.tn.read_very_eager().decode('ascii')
            if 'Login incorrect' not in command_result:
                return True
            else:
                return False
        # 此函数实现执行传过来的命令,并输出其执行结果
        def execute_some_command(self,command):
            logging.info('开始执行交换机命令:'+command)
            # 执行命令
            self.tn.write(command.encode('ascii')+b'\n')
            time.sleep(0.2)
            # 获取命令结果
            a = []
            a.append(('--- More ---').encode('ascii'))
            command_result = self.tn.read_very_eager().decode('ascii')
            while True:
                b,c,d = self.tn.expect(a,timeout=1)
                command_result += d.decode('ascii')
                if 0 == b:
                    time.sleep(0.2)
                    self.tn.write(b' \n') #不用\r\n来继续
                else:
                    break
            logging.info('命令执行结果:'+repr(command_result))
            if 'Error:' in command_result :
                logging.critical('执行结果中可能包含错误`Error:`,脚本强制退出')
                sendWxMsg('流量调度系统交换机命令执行出现错误,请及时处理!')
                sys.exit()
            return command_result
        # 退出telnet
        def logout(self):
            self.tn.write(b"exit\n")
            self.tn.close()
    

    多个交换机命令时封装调用(可自行封装)

    # 执行多条交换机命令
    def execSwitchCmd( host , username , password , commands , extra = '1' ) :
        '''
        :param host:主机地址
        :param username:用户名
        :param password:密码
        :param commands:列表命令集
        :param extra: 是否需要执行 system-view , commit 命令
        '''
        logging.info('开始执行交换机命令【'+repr(commands)+'】')
        # return True
        telnet_client = TelnetClient()
        msg = ''
        # 如果登录结果返加True,则执行命令,然后退出
        if telnet_client.login(host,username,password) :
            if extra == 1:
                msg += telnet_client.execute_some_command( 'system-view' )
            for command in commands :
                msg += telnet_client.execute_some_command( command )
            if extra == 1:            
                msg += telnet_client.execute_some_command( 'commit' )
            telnet_client.logout()    
        return msg

    调用方法

    cmd = []
    cmd.append('dis traffic-policy applied-record TO_TrafficCenter')
    res = func.execSwitchCmd(room['host'],room['username'],room['password'],cmd , '0')
    if 'xxxxx' in res :
        # 某些配置在交换机中,做什么处理
        ......

    交换机命令过多时,建议使用\r\n拼接命令并分组

    def centerSchedulingOut95( destination_id , pieces ) :
        # .....
        #.......
        cmd = []
        i = 1
        divided = 12
        tmpCmd = ''
        for policy in policys :
            from_room = getRoomById( policy['destination_id'] )
            if i % divided == 0 :
                cmd.append( tmpCmd )
                tmpCmd = ''
            else :
                tmpCmd += '\r\n' + policy['name'] + '\r\n' + 'UNDO traffic-policy TO_'+from_room['abbr']+' inbound' + '\r\n' + 'traffic-policy TO_'+to_room['abbr']+' inbound' + '\r\n'
            i += 1
            config.cursor.execute("UPDATE center_policy SET status = 2 ,destination_id = %s , update_time=%s WHERE id = %s" , [ destination_id , getNow() , policy['id'] ] )
            logging.info('|----已更改 %s 状态为:使用中,去向机房ID:%s',policy['name'] , to_room['id'])
        if tmpCmd != '' :
            cmd.append( tmpCmd )
        logging.info('|----开始登录调度中心交换机,批量执行调出POLICY命令')
        config.cursor.execute("SELECT * FROM center")
        centerObj = config.cursor.fetchone()
        if len(cmd) > 0 :
            logging.info('|----本次实际调度POLICY规则条数:%s',repr( len(policys) ) )
            execSwitchCmd( host = centerObj['host'] , username = centerObj['username'] , password = centerObj['password'] , commands = cmd )

    我们这里将命令拼接成 \r\n的格式拼接,每12个命令一组,传入到交换机里执行。

  • Python3 半自动使用 ChromeDriver 采集豆瓣图片 并提交到 Chevereto 图床

    Python3 半自动使用 ChromeDriver 采集豆瓣图片 并提交到 Chevereto 图床

    前面我们写了Python 爬虫 抓取豆瓣小组图片 通过api提交入库到 Chevereto 图床,但是现在有些群组需要登录才行,所以我们这里做了一个半自动脚本并使用chromedriver自动登录豆瓣并提交图片到 Chevereto 图床。

    注:老季是Python新手,且本脚本大部分内容来自网络。

    chormedriver下载地址

    http://npm.taobao.org/mirrors/chromedriver/

    Python代码实例

    #!/usr/bin/python
    # -*- coding: UTF-8 -*-
    # 作者:老季
    # 网址:https://www.laoji.org
    #导入所需的库
    import logging
    import random
    import time
    import urllib.request
    import requests , json
    from selenium import webdriver
    # 实例化driver
    # option= webdriver.ChromeOptions()
    # driver = webdriver.Chrome(chrome_options=option)
    driver = webdriver.Chrome('D:\\Downloads\\chromedriver.exe') # chromedirver所在路径
    # 登陆
    driver.get('https://accounts.douban.com/passport/login')
    driver.find_element_by_class_name('account-tab-account').click()  # 模拟点击
    time.sleep(2)
    driver.find_element_by_id('username').send_keys('豆瓣用户名')  # 输入用户名
    driver.find_element_by_id('password').send_keys('豆瓣密码')  # 输入密码
    driver.find_element_by_css_selector("[class='btn btn-account btn-active']").click()  # 模拟点击
    time.sleep(5)
    '''
    TODO:验证码
    '''
    # 获取cookie
    session = requests.Session()
    cookies = driver.get_cookies()
    for cookie in cookies:
        session.cookies.set(cookie['name'], cookie['value'])
    # print(cookies)
    time.sleep(3)
    logging.FileHandler(filename='Selenium_img_douban.log', encoding='utf-8')
    logging.basicConfig(level=logging.INFO,
                        format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',
                        datefmt='%Y-%m-%d %A %H:%M:%S',
                        # filename='F:\\豆瓣下载\\Selenium_img_douban.log', # 日志保存路径
                        filemode='w')
    # 模拟浏览器提交图片
    def submit_img(url):
        submit_url = 'http://tutie.org/api/1/upload/?key='+urllib.parse.quote_plus('f14fe8e8b11c08902a489706d7d99941')+'&source='+urllib.parse.quote_plus(url)
    #    print(submit_url)
        req = urllib.request.Request(submit_url)
        try:
            res = urllib.request.urlopen(req)
            data = json.loads(res.read().decode())
            return str(data['status_code'])        
        except urllib.error.HTTPError as e:
            print(e.read())      
    
    def get_headers():
        '''
        随机获取一个headers
        '''
        user_agents = ['Mozilla/5.0 (Windows NT 6.1; rv:2.0.1) Gecko/20100101 Firefox/4.0.1',
                       'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-us) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50',
                       'Opera/9.80 (Windows NT 6.1; U; en) Presto/2.8.131 Version/11.11']
        headers = {'User-Agent': random.choice(user_agents)}
        return headers
    
    def get(url,group_url, start_page, end_page, params=None):
        '''
        向一个url发送get请求,返回response对象
        :param url: 网页链接
        :param params: URL参数字典
        :return: 发送请求后获取的response对象
        '''
        # 等待一个随机的时间,防止被封IP,这里随机等待0~6秒,亲测可有效地避免触发豆瓣的反爬虫机制
        time.sleep(6 * random.random())
        resp = session.get(url, params=params, headers=get_headers())
        print(resp)
        logging.info(resp)
        if resp:
            logging.info(
                '[get] url = {0}, status_code = {1}'.format(url, resp.status_code))
            resp.encoding = 'utf-8'
            # 这里很重要,每次发送请求后,都更新session的cookie,防止cookie过期
            if resp.cookies.get_dict():
                session.cookies.update(resp.cookies)
                logging.info('[get] updated cookies, new cookies = {0}'.format(
                    resp.cookies.get_dict()))
        else:
            logging.info('[get] url = {0}, response is None'.format(url))
        logging.info('[info] 寻找小组列表地址...')
        logging.info('[get] 已进入小组首页')
        while start_page <= end_page:
            driver.get(group_url + str((start_page - 1) * 25)) # 晒晒你最性感的照片小组
            logging.info('已进入第' + str(start_page) + '页')
            print('已进入第' + str(start_page) + '页')
            # 每一页讨论链接列表
            links = driver.find_elements_by_xpath(r"//tbody/tr/td[@class='title']/a")
            topic_links = {}
            for link in links:
                topic_link = link.get_attribute('href')
                title_name = link.get_attribute('title')
                # 获取的图片以小组话题名称命名
                img_name = title_name.replace('?', '?').replace('\\', '').replace('/', '').replace('"', '').replace(':','').replace('*','').replace('<', '').replace('>', '').replace('|', '').replace('\n', '')
                topic_links[topic_link] = img_name
                topic_num = 0
            for topic_link, img_name in topic_links.items():
                logging.info('进入第' + str(start_page) + '页,第' + str(topic_num + 1) + '话题。')
                topic_num += 1
                driver.get(topic_link)
                # 判断该话题下有无图片
                img_links = driver.find_elements_by_class_name('image-wrapper')
                if len(img_links) > 0:
                    i = 0
                    for img_link in img_links:
                        img_name = topic_links[topic_link] + '_' + str(i)
                        img_src = img_link.find_element_by_xpath('./img').get_attribute('src')
                        print('[get] 话题:' + img_name + ', 图片链接:' + img_src)
                        img = img_src.replace('.webp','.jpg')
                        print('提交图片链接:'+img)
                        submit_img( img )
                        # download_img = urllib.request.urlretrieve(img_src, 'F:\\豆瓣下载\\%s.jpg' % img_name)
                        # time.sleep(3 * random.random())
                        i += 1
                else:
                    print('该标题下无图片')
                img_links2 = driver.find_elements_by_css_selector("[class='topic-figure cc']")
                time.sleep(3 * random.random())
            start_page += 1
            time.sleep(3 * random.random())
        time.sleep(5)
        driver.quit()
    
    if __name__ == '__main__':
        home_url = 'https://www.douban.com/'
        group_url = 'https://www.douban.com/group/481977/discussion?start='
        get(home_url , group_url, 0, 10000)
    
WeChat
↑