Nginx 用 deny 禁止某些IP访问

在nginx配置conf(一般在 /etc/nginx 目录 )中加入

include /etc/nginx/blackips.conf;

新建 blackips.conf

#屏蔽单个IP的命令是
deny 192.168.1.1
#封整个段即从123.0.0.1到123.255.255.254的命令
deny 123.0.0.0/8
#封IP段即从123.45.0.1到123.45.255.254的命令
deny 124.45.0.0/16
#封IP段即从123.45.6.1到123.45.6.254的命令是
deny 123.45.6.0/24


也就是说,如果最后的斜杠后的数值:
8:匹配后三位最大值的
16:匹配后两位最大值的
24:匹配后一位最大值的

用 nginx -t 命令检查配置是否成功

[root@xxx ~]# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

最后 nginx -s reload 重启nginx 让配置生效

Laravel将采集WBE页面Table转换为CSV文件保存

一,准备环境 simple_html_dom

composer 找了很多源都没找到,我采用的是自己下载。

下载地址:https://sourceforge.net/projects/simplehtmldom/

解压后的文件

将 simple_html_dom.php 上传到 根目录/app/LIb/

并修改 composer.json 找到 autoload 引入类库

    "autoload": {
        "psr-4": {
            "App\\": "app/"
        },
        "classmap": [
            "database/seeds",
            "database/factories",
            "app/Lib/simple_html_dom.php"  //增加
        ]
    },

准备工作完成。

二,使用

//$content 为 包含 table 的页面源码   
 private function get_table($content ){
		//echo "Start table2csv".PHP_EOL;

		$html = new simple_html_dom();
		@$html->load($content);
		$re = [];
		$csv = "";
		
		$fp = fopen ( '示例.csv' , 'w' );

		foreach($html->find('tr') as $element)
		{
			$th = array();
			foreach( $element->find('th') as $row)  
			{
				$th [] = $row->plaintext;
			}
			if(!empty($th)){
				$re[] = $th;
				fputcsv ( $fp , $th );
			}
			$td = array();
			foreach( $element->find('td') as $row)  
			{
				$td [] = $row->plaintext;
			}
			
			if(!empty($td)){
				$re[] = $td;
				fputcsv ( $fp , $td);

			}
		}
		fclose( $fp );
		return $re;
		//echo "end table2csv".PHP_EOL;
    }

保存文件效果

某校考研录取成绩

Laravel Admin ModelTree 展示问题的解决方案

ModelTree 树形目录配置

问题描述

在grid 中引入ModelTree改造过的selectOptions()时,会出现 无法识别的bug。

勉强可以使用,但是展示效果非常差,占据页面很大宽度。

展示问题1
展示问题2

解决方案

实际上 ModelClass::selectOptions(); 返回结果就是一个Array,循环replace 了  即可。

$option_arr = ModelClass::selectOptions();
		
foreach($option_arr as $key=>$value){
		
    $option_arr[$key] =  str_replace(" ", ".",$value); //替换掉  
}

$grid->column('pid', __('分类'))->editable('select',$option_arr)->sortable();
修改完的页面。

基本上完美解决了展示问题。

Laravel Admin 树形目录管理

laravel  5.8.38    laravel admin  1.7.16  本文创建于 2020.8.17

完成后长这样

1.创建数据库

CREATE TABLE `art_paper` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(45) DEFAULT NULL,
  `fid` int(11) DEFAULT NULL,
  `index` int(11) DEFAULT NULL,
  `paperid` int(11) DEFAULT NULL,
  `creattime` datetime DEFAULT NULL,
  `state` int(11) DEFAULT '1',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=70 DEFAULT CHARSET=utf8;

2.生成model

php artisan code:models –table=art_paper

3.修改Models文件

namespace App\Models;

use Carbon\Carbon;
use Encore\Admin\Traits\ModelTree;  //add
use Illuminate\Database\Eloquent\Model;

class ArtPaper extends Model
{
	use ModelTree;  //add
	protected $table = 'art_paper';
	public $timestamps = false;

/**  add  **/
	public function __construct(array $attributes = [])
    {
        parent::__construct($attributes);

        $this->setParentColumn('fid');
        $this->setOrderColumn('index');
        $this->setTitleColumn('name');
    }
/**  add end **/

4.创建管理页面

php artisan admin:make ArtpaperController --model App\\Models\\ArtPaper

按提示加好路由
Add the following route to app/Admin/routes.php:
$router->resource('art-papers', ArtpaperController::class);

5.修改 Controller 文件

增加
use Encore\Admin\Tree;
use Encore\Admin\Layout\{Column, Row, Content};
use Encore\Admin\Widgets\Box;

//注意这里要新建index方法,在 grid 里写会报错    
 public function index(Content $content){
     	

        return $content
            ->header('逻辑800题目录')
            ->row(function (Row $row){
            	$row->column(6, $this->treeView()->render());
            	$row->column(6, function (Column $column){
                    $form = new \Encore\Admin\Widgets\Form();
                    $form->action(admin_url('logic-papers'));
                    $form->select('fid', __('父目录'))->options(LogicPaper::selectOptions());
                    $form->text('name', __('名称'))->required();
                    $form->number('index', __('排序'))->default(99)->help('越小越靠前');
                    $form->hidden('_token')->default(csrf_token());
                    $column->append((new Box(__('新建'), $form))->style('success'));
                });
            });
            //->body($tree);

    
    } 
    protected function treeView()
    {
    	 $tree = new Tree(new LogicPaper);
    	 return $tree;
        // return  CategoriesModel::tree(function (Tree $tree){
//             $tree->disableCreate(); // 关闭新增按钮
//             $tree->branch(function ($branch) {
//                 return "<strong>{$branch['cate_name']}</strong>"; // 标题添加strong标签
//             });
//         });
    }

laravel-admin 笔记

自动创建数据库

php artisan make:model User -crm
同时创建

修改  ./database/migrations/  下数据文件

   public function up()
    {
        Schema::create('columns', function(Blueprint $table)
        {
            $table->increments('id');
            $table->string('name')->nullable();
            $table->string('url')->nullable();
            $table->text('intr');
            $table->string('otherauthor');
            $table->integer('copyinfo');
            $table->timestamps();
        });
    }

执行  php artisan migrate

自动生成Admin管理页面

php artisan admin:make UserController –model App\\Models\\User

根据已存在的表创建model

php artisan code:models –table=test

创建指定链接的某个表

php artisan code:models –connection=mysql001 –table=test

【论文查重】pycorrector 搭建错别字识别

先更新 wheel ,否则会报下面这个错

error: can’t copy ‘pycorrector/data/kenlm’: doesn’t exist or not a regular file

pip install –upgrade wheel
pip install –upgrade setuptools

pip install pypinyin
pip install kenlm
pip install numpy
pip install jieba
pip install pycorrector

kenlm  在centos下安装可能会出现找不到 Python.h 的错误

解决办法    yum install python36u-devel

python 文件内容

#coding=utf-8
import pycorrector
corrected_sent,detail=pycorrector.correct(‘少先队员因该为老人让坐’)
print(corrected_sent, detail)

执行结果

2019-03-08 10:10:32,814 – /usr/local/lib/python3.5/dist-packages/pycorrector/corrector.py – DEBUG – Loaded same pinyin file: /usr/local/lib/python3.5/dist-packages/pycorrector/data/same_pinyin.txt, same stroke file: /usr/local/lib/python3.5/dist-packages/pycorrector/data/same_stroke.txt, spend: 0.047 s.
2019-03-08 10:10:32,816 – /usr/local/lib/python3.5/dist-packages/pycorrector/detector.py – DEBUG – Loaded language model: /usr/local/lib/python3.5/dist-packages/pycorrector/data/kenlm/people_chars_lm.klm, spend: 0.0011556148529052734 s
2019-03-08 10:10:34,098 – /usr/local/lib/python3.5/dist-packages/pycorrector/detector.py – DEBUG – Loaded word freq file: /usr/local/lib/python3.5/dist-packages/pycorrector/data/word_dict.txt, spend: 1.2822625637054443 s
2019-03-08 10:10:34,099 – /usr/local/lib/python3.5/dist-packages/pycorrector/detector.py – DEBUG – Loaded confusion file: /usr/local/lib/python3.5/dist-packages/pycorrector/data/custom_confusion.txt, spend: 1.2832543849945068 s
少先队员应该为老人让座 [[‘因该’, ‘应该’, 4, 6], [‘坐’, ‘座’, 10, 11]]

微信小程序之快速创建朋友圈分享海报

音频教程见《免费导航》

// pages/share/pic/sharepic.js
var app = getApp();
Page({

  /**
   * 页面的初始数据
   */
  data: {
    jdConfig: {
      width: 750,
      height: 1334,
      backgroundColor: '#fff',
      debug: false,
      blocks: [
        {
          width: 690,
          height: 808,
          x: 30,
          y: 183,
          borderWidth: 2,
          borderColor: '#f0c2a0',
          borderRadius: 20,
        },
        {
          width: 634,
          height: 74,
          x: 59,
          y: 770,
          backgroundColor: '#fff',
          opacity: 0.5,
          zIndex: 100,
        },
      ],
      texts: [
        {
          x: 113,
          y: 61,
          baseLine: 'middle',
          text: '蟠桃',
          fontSize: 32,
          color: '#8d8d8d',
        },
        {
          x: 30,
          y: 113,
          baseLine: 'top',
          text: '发现一个好物,推荐给你呀',
          fontSize: 38,
          color: '#080808',
        },
        {
          x: 92,
          y: 810,
          fontSize: 38,
          baseLine: 'middle',
          text: '标题标题标题标题标题标题标题标题标题',
          width: 570,
          lineNum: 1,
          color: '#8d8d8d',
          zIndex: 200,
        },
        {
          x: 59,
          y: 895,
          baseLine: 'middle',
          text: [
            {
              text: '2人拼',
              fontSize: 28,
              color: '#ec1731',
            },
            {
              text: '¥99',
              fontSize: 36,
              color: '#ec1731',
              marginLeft: 30,
            }
          ]
        },
        {
          x: 522,
          y: 895,
          baseLine: 'middle',
          text: '已拼2件',
          fontSize: 28,
          color: '#929292',
        },
        {
          x: 59,
          y: 945,
          baseLine: 'middle',
          text: [
            {
              text: '商家发货&售后',
              fontSize: 28,
              color: '#929292',
            },
            {
              text: '七天退货',
              fontSize: 28,
              color: '#929292',
              marginLeft: 50,
            },
            {
              text: '运费险',
              fontSize: 28,
              color: '#929292',
              marginLeft: 50,
            },
          ]
        },
        {
          x: 360,
          y: 1065,
          baseLine: 'top',
          text: '长按识别小程序码',
          fontSize: 38,
          color: '#080808',
        },
        {
          x: 360,
          y: 1123,
          baseLine: 'top',
          text: '超值好货一起拼',
          fontSize: 28,
          color: '#929292',
        },
      ],
      images: [
        {
          width: 62,
          height: 62,
          x: 30,
          y: 30,
          borderRadius: 62,
          url: 'https://www.yibaifen.com/images/02bb99132352b5b5dcea.jpg',
        },
        {
          width: 634,
          height: 634,
          x: 59,
          y: 210,
          url: 'https://www.yibaifen.com/images/193256f45999757701f2.jpeg',
        },
        {
          width: 220,
          height: 220,
          x: 92,
          y: 1020,
          url: 'https://www.yibaifen.com/images/d719fdb289c955627735.jpg',
        },
        {
          width: 750,
          height: 90,
          x: 0,
          y: 1244,
          url: 'https://www.yibaifen.com/images/67b0a8ad316b44841c69.png',
        }
      ]

    },
    demoConfig: {
      width: 750,
      height: 1000,
      backgroundColor: '#fff',
      debug: false,
      blocks: [
        {
          x: 0,
          y: 10,
          width: 750, // 如果内部有文字,由文字宽度和内边距决定
          height: 120,
          paddingLeft: 0,
          paddingRight: 0,
          borderWidth: 10,
          borderColor: 'red',
          backgroundColor: 'blue',
          borderRadius: 40,
          text: {
            text: [
              {
                text: '金额¥ 1.00',
                fontSize: 80,
                color: 'yellow',
                opacity: 1,
                marginLeft: 50,
                marginRight: 10,
              },
              {
                text: '金额¥ 1.00',
                fontSize: 20,
                color: 'yellow',
                opacity: 1,
                marginLeft: 10,
                textDecoration: 'line-through',
              },
            ],
            baseLine: 'middle',
          },
        }
      ],
      texts: [
        {
          x: 0,
          y: 180,
          text: [
            {
              text: '长标题长标题长标题长标题长标题长标题长标题长标题长标题',
              fontSize: 40,
              color: 'red',
              opacity: 1,
              marginLeft: 0,
              marginRight: 10,
              width: 200,
              lineHeight: 40,
              lineNum: 2,
            },
            {
              text: '原价¥ 1.00',
              fontSize: 40,
              color: 'blue',
              opacity: 1,
              marginLeft: 10,
              textDecoration: 'line-through',
            },
          ],
          baseLine: 'middle',
        },
        {
          x: 10,
          y: 330,
          text: '金额¥ 1.00',
          fontSize: 80,
          color: 'blue',
          opacity: 1,
          baseLine: 'middle',
          textDecoration: 'line-through',
        },
      ],
      images: [
        {
          url: 'https://www.yibaifen.com/images/02bb99132352b5b5dcea.jpg',
          width: 300,
          height: 300,
          y: 450,
          x: 0,
          // borderRadius: 150,
          // borderWidth: 10,
          // borderColor: 'red',
        },
        {
          url: 'https://www.yibaifen.com/images/02bb99132352b5b5dcea.jpg',
          width: 100,
          height: 100,
          y: 450,
          x: 400,
          borderRadius: 100,
          borderWidth: 10,
        },
      ],
      lines: [
        {
          startY: 800,
          startX: 10,
          endX: 300,
          endY: 800,
          width: 5,
          color: 'red',
        }
      ]

    }
  },
  onPosterSuccess(e) {
    const { detail } = e;
    wx.previewImage({
      current: detail,
      urls: [detail]
    })
  },
  onPosterFail(err) {
    console.error(err);
  },
  /**
   * 生命周期函数--监听页面加载
   */
  onLoad: function (options) {
   
  },

  /**
   * 生命周期函数--监听页面初次渲染完成
   */
  onReady: function () {

  },

  /**
   * 生命周期函数--监听页面显示
   */
  onShow: function () {

  },

  /**
   * 生命周期函数--监听页面隐藏
   */
  onHide: function () {

  },

  /**
   * 生命周期函数--监听页面卸载
   */
  onUnload: function () {

  },

  /**
   * 页面相关事件处理函数--监听用户下拉动作
   */
  onPullDownRefresh: function () {

  },

  /**
   * 页面上拉触底事件的处理函数
   */
  onReachBottom: function () {

  },

  /**
   * 用户点击右上角分享
   */
  onShareAppMessage: function () {

  }
})

Python 可视化实战(一)

课程请移步

小程序 《免费导航》

课程要点

  • matplotlib
  • numpy
  • moviepy
import matplotlib
matplotlib.use('TkAgg')
import matplotlib.pyplot as plt
import numpy as np
from moviepy.video.io.bindings import mplfig_to_npimage
import moviepy.editor as mpy

#绘图
duration = 2

fig_mpl, ax = plt.subplots(1,facecolor='white')
xx = np.linspace(-2,2,200) # the x vector
zz = lambda d: np.sinc(xx**2)+np.sin(xx+d) # the (changing) z vector
ax.set_title("Example in y=0")
ax.set_ylim(-1.5,2.5)
line, = ax.plot(xx, zz(0), lw=3)

#生成动画并保存成gif

def make_frame_mpl(t):
    line.set_ydata( zz(2*np.pi*t/duration))  # <= Update the curve
    return mplfig_to_npimage(fig_mpl) # RGB image of the figure

animation =mpy.VideoClip(make_frame_mpl, duration=duration)
animation.write_gif("1.gif", fps=20)