2019年8月

首先我们说下为什么要获取小程序的formId,如果我们想要给用户发通知(小程序消息)那么该用户必须在7天之内提交过表单,也就是我们必须有7天之内的一个formId。
那么怎么获取formId呢。也很简单,提交表单的时候加上report-submit="{{true}}",也就是:
<form bindsubmit="formSubmit" report-submit="{{true}}">。按钮的类型为form-type="submit"
表单的提交建议还是使用这种,因为这样可以积累一个formId。小编之前为了方便直接写了个请求函数,那样获取不到formId。在取值formId的时候也很简单,只需要在formSubmit这个函数里面,获取就可以
let formId = e.detail.formId
但是在模拟器里面你会发现,你获取到的是the formId is a mock one.是不是很好奇呢。其实在模拟器是获取不到formId,只有真机才可以。

Discuz这个论坛程序是使用php进行开发的,所以迁移也很简单,首先把源码下载下来,然后放在迁移之后的服务器上即可,如果数据库地址,用户名,密码都没有发生改变的话,那就完事了,完成迁移了。是不是很简单呢,但是往往没那么简单,一般迁移数据库经常会改变账号密码,或者是地址,所以需要配置数据库的。网站系统需要修改的位置有主要有两处Discuz和UC-center

  • 路径:/config/config_global.php 这里路径是从网站的根目录里面开始算起的,打开 config_global.php修改里面的账号密码以及服务器地址即可。
  • 路径:/uc_server/data/config.inc.php,打开 config.inc.php 文件修改,修改里面的账号密码以及服务器地址即可。
  • 路径:/config/config_ucenter.php,打开 config_ucenter.php ,修改里面的账号密码以及服务器地址即可。

都是修改

['dbhost'] = '数据库地址';
['dbuser'] = '数据库用户名';
['dbpw'] = '数据库密码';
['dbname'] = '数据库名称';

到这里整个论坛都恢复正常访问了。

微信小程序在用户发布内容的时候往往需要检查发布内容是否违规,是否有敏感词汇,或者图片等有木有问题等等吧。检查这些内容当然可以使用手工进行检测,人工进行审核,但是那样是不是就太麻烦了。所以微信官方也给我们提供了免费的查询接口,记住是免费的。不过目前只能是微信才能使用。下面小编使用python封装的两个方法。

msg_sec_check文本内容检查

import requests
from flask import json, jsonify

def msg_sec_check(content=None, access_token=None):
    '''文字内容检查'''
    if content == None:
        return True
    url = 'https://api.weixin.qq.com/wxa/msg_sec_check?access_token=%s' % access_token
    req = {
        'content': content
    }
    req = json.dumps(req, ensure_ascii=False).encode('utf-8')
    rs = requests.post(url, data=req)
    if json.loads(rs.content).get("errcode")!=0:
        return False
    return True

参数说明:

  • content:要检测的内容
  • access_token:access_token

msg_sec_check图片检测

import requests
from flask import json, jsonify

def msg_sec_check(media=None, access_token=None):
    '''图片检查'''
    if content == None:
        return True
    url = 'POST https://api.weixin.qq.com/wxa/img_sec_check?access_token=%s' % access_token
    req = {
        'media': media
    }
    req = json.dumps(req, ensure_ascii=False).encode('utf-8')
    rs = requests.post(url, data=req)
    if json.loads(rs.content).get("errcode")!=0:
        return False
    return True

参数说明:

  • media:要检测的图片,格式支持PNG、JPEG、JPG、GIF,图片尺寸不超过 750px x 1334px
  • access_token:access_token

74444007_p0-1140x600.jpg
在开发一个项目的时候,一般不可能一直在写自己当前的任务,往往是当前任务写的正火热的时候,又来了新的紧急性任务,或者出现了bug需要处理,那出现这种情况的时候怎么弄呢,当前的任务还没做完,还不能发布,这时候我们总不能把刚写的代码删除了吧。哈哈!!!不用,我们只需要执行一个git stash的命令就可以把当前修改的内容保存起来,不再影响开发其他的功能。当我们开发完其他功能的时候,在切换会主线任务时,只需要执行下git stash pop就可以了。
git stash的存储结构时栈的结构,我们可以一直stash,出来的时候也是一样,一直pop就可以,每次pop就会出来一个stash。但是小编不建议大家放多个stash,因为时间久了你就分不清楚了,而且一般情况下,老的stash就没有意义了。
下面咱再说集个关于stash常用的方法吧。

  • git stash:保存当前工作进度,会把暂存区和工作区的改动stash(保存)起来。执行完这个命令后,在运行git status命令,就会发现当前是一个干净的工作区,没有任何改动。使用git stash save '注释'可以添加一些注释。
  • git stash list显示保存进度的列表,也就是你所有的stash。
  • git stash pop [–index] [stash_id]: git默认会把工作区和暂存区的改动都恢复到工作区,通过git stash pop命令恢复进度后,会删除当前进度。

    • git stash pop 把最近一次的stash恢复最新的进度到工作区。
    • git stash pop --index 恢复最新的进度到工作区和暂存区,尝试将原来暂存区的改动还恢复到暂存区。
    • git stash pop [stash_id] 恢复指定的进度到工作区。stash_id是通过git stash list命令得到的。例如:stash@{1}
  • git stash apply [–index] [stash_id]` 除了不删除恢复的进度之外,其余和git stash pop 命令一样。
  • git stash drop [stash_id]删除一个存储的进度。如果不指定stash_id,则默认删除最新的存储进度。
  • git stash clear 删除所有存储的进度,如果你忘记了存储进度上午内容,建议直接clear,但是一定要慎重。

小程序实现转发分享的方式主要有两种:

  • 点击有上角的三个点实现转发
    这个比较简单,直接在onShareAppMessage里面写转发内容就行,因为点击之后会自动执行。

    onShareAppMessage: function(res) {
      return {
        title: '小宁博客',
        path: '/pages/index/index',
        imageUrl: 'https://www.sunxiaoning.com/usr/uploads/2019/03/3616970405.jpeg'
      }
    }

    参数说明:

    title 转发标题 ,默认是当前小程序名称
    path 转发路径 默认是当前页面 path ,必须是以 / 开头的完整路径
    imageUrl 自定义图片路径,可以是本地文件路径、代码包文件路径或者网络图片路径。支持PNG及JPG。显示图片长宽比是 5:4。
  • 通过点击按钮进行转发

<button open-type="share">分享</button>
sunset-1140x600.jpg

首先需要导入re模块import re

re库中常用方法

  • re.search(pattern, string, flags=0)遍历整个字符串并返回第一个成功的匹配。
  • re.match(pattern, string, flags=0)尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match()就返回none。

    pattern :匹配的正则表达式
    string :要匹配的字符串。
    flags :标志位,用于控制正则表达式的匹配方式
  • re.sub(pattern, repl, string, count=0)用于替换字符串中的匹配项,repl : 替换的字符串,也可为一个函数。

    pattern : 正则中的模式字符串。
    repl : 替换的字符串,也可为一个函数。
    string : 要被查找替换的原始字符串。
    count : 模式匹配后替换的最大次数,默认 0 表示替换所有的匹配。
  • re.compile(pattern[, flags])用于编译正则表达式,生成一个正则表达式( Pattern )对象,供 match() 和 search() 这两个函数使用。

    pattern : 一个字符串形式的正则表达式
    flags : 标志位,用于控制正则表达式的匹配方式
  • findall(string[, pos[, endpos]])在字符串中找到正则表达式所匹配的所有子串,并返回一个列表,如果没有找到匹配的,则返回空列表。

    string : 待匹配的字符串。
    pos : 可选参数,指定字符串的起始位置,默认为 0。
    endpos : 可选参数,指定字符串的结束位置,默认为字符串的长度。
  • re.split(pattern, string[, maxsplit=0, flags=0])能够匹配的子串将字符串分割后返回列表。

    pattern: 匹配的正则表达式
    string: 要匹配的字符串。
    maxsplit: 分隔次数,maxsplit=1 分隔一次,默认为 0,不限制次数。
    flags: 标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。

常用的匹配规则总结表

  • \w匹配字母数字及下划线
  • \W匹配非字母数字及下划线
  • \s匹配任意空白字符,等价于 [\t\n\r\f].
  • \S匹配任意非空字符
  • \d匹配十进制数字,等价于 [0-9]
  • \D匹配任意非数字
  • \A匹配字符串开始
  • \Z匹配字符串结束,如果是存在换行,只匹配到换行前的结束字符串
  • \z匹配字符串结束
  • \G匹配最后匹配完成的位置
  • \n匹配一个换行符
  • \t匹配一个制表符
  • .除换行外任意一个字符
  • ^匹配字符串的开头
  • $匹配字符串的末尾
  • .匹配任意字符,除了换行符
  • [...]用来表示一组字符,单独列出:[amk] 匹配 'a','m' 或 'k'
  • [^...]不在 [] 中的字符:[^abc]匹配除了 a,b,c 之外的字符。
  • *匹配 0 个或多个的表达式。
  • +匹配 1 个或多个的表达式。
  • ?匹配 0 个或 1 个由前面的正则表达式定义的片段,非贪婪方式
  • {n}精确匹配 n 个前面表达式。
  • {n,} 至少n次
  • {n, m}匹配 n 到 m 次由前面的正则表达式定义的片段,贪婪方式
  • a | b匹配 a 或 b
  • ( )匹配括号内的表达式,也表示一个组

修饰符总结

  • re.I使匹配对大小写不敏感
  • re.L做本地化识别(locale-aware)匹配
  • re.M多行匹配,影响 ^$
  • re.S使 . 匹配包括换行在内的所有字符
  • re.U根据Unicode字符集解析字符。这个标志影响 \w, \W, \b, \B
  • re.X该标志通过给予你更灵活的格式以便你将正则表达式写得更易于理解。
"p.*y"#贪婪模式
"p.*?y"#懒惰模式,精准

D1r.jpg

python中常见的文件的操作,对于文件的操作常用的就是读取以及写入了,在这里小编介绍几种常用的操作方法。

Python字符串可以是二进制数据,而不是仅仅是文字。

open 函数

open()函数的作用是打开一个文件,并且创建一个file对象。
语法file object = open(file_name [, access_mode][, buffering])
参数

  • file_name:file_name指的是你要操作的文件的路径以及文件名。
  • access_mode:access_mode指的是打开文件的模式:只读,写入,追加等模式。
  • buffering:buffering指的是寄存的大小,如果buffering等于0,就不会有寄存。如果buffering等于1,访问文件时会寄存行。如果将buffering大于1的整数,表明了这就是的寄存区的缓冲大小。如果buffering小于0,寄存区的缓冲大小则为系统默认。

access_mode的取值:

  • r以只读方式打开文件。文件的指针将会放在文件的开头。这是默认模式。
  • rb以二进制格式打开一个文件用于只读。文件指针将会放在文件的开头。这是默认模式。
  • r+打开一个文件用于读写。文件指针将会放在文件的开头。
  • rb+以二进制格式打开一个文件用于读写。文件指针将会放在文件的开头。
  • w打开一个文件只用于写入。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。
  • wb以二进制格式打开一个文件只用于写入。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。
  • w+打开一个文件用于读写。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。
  • wb+以二进制格式打开一个文件用于读写。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。
  • a打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。
  • ab以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。
  • a+打开一个文件用于读写。如果该文件已存在,文件指针将会放在文件的结尾。文件打开时会是追加模式。如果该文件不存在,创建新文件用于读写。
  • ab+以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。如果该文件不存在,创建新文件用于读写。

file对象的属性

  • file.name返回文件的名称。
  • file.mode返回被打开文件的访问模式。
  • file.closed文件已被关闭则返回true,否则返回false。
  • file.softspace末尾是否强制加空格。

close()函数

file对象的 close()方法刷新缓冲区里任何还没写入的信息,并关闭该文件,这之后便不能再进行写入。当一个文件对象的引用被重新指定给另一个文件时,Python 会关闭之前的文件。
语法:语法:fileObject.close();

write()函数

write()方法可将任何字符串写入一个已经打开的文件。并且write()方法不会在字符串的结尾添加换行符('\n')。并且write()之后一定要close().
语法fileObject.write(String);
参数:String是要写入到已打开文件的内容。

read()函数

read()方法从一个打开的文件中读取一个字符串。
语法fileObject.read([count]);
参数:count参数是要从已打开文件中读取的字节的个数。该方法从文件的开头开始读入,如果没有传入count,它会尝试尽可能多地读取内容,很可能是直到文件的末尾。

readline()函数

fileObject.readline() 会从文件中读取单独的一行。换行符为 '\n'。当读取到最后一行时,则返回一个空字符串。
语法fileObject.readline()

readlines()函数

fileObject.readlines()将以列表的形式返回该文件中包含的所有行,列表中的一项表示文件的一行
语法fileObject.readlines([sizehint])
参数:sizehint, 则读取指定长度的字节, 并且将这些字节按行分割。

rename()函数

rename()对文件重命名。
语法fileObject.rename(current_file_name, new_file_name)

remove()函数

删除文件。
语法fileObject.remove(file_name)

mkdir()函数

mkdir()方法在当前目录下创建新的目录们。
语法fileObject.mkdir(new_dir)

chdir()函数

可以用chdir()方法来改变当前的目录。
语法fileObject.chdir(new_dir)
参数:newdir是你想设成当前目录的目录名称。

getcwd()函数

getcwd()方法显示当前的工作目录。
语法fileObject.getcwd()

rmdir()函数

rmdir()方法删除目录,目录名称以参数传递。在删除这个目录之前,它的所有内容应该先被清除。
语法fileObject.rmdir(dir_name)
pink_eyes-shirt-1140x600.jpg

欧几里得距离算法是经过人们一致评价的物品为坐标轴,然后将参与评价的人绘制到图上,并考察他们彼此之间距离的远近,如图:
ojld.png

注:图片来源于《集体智慧编程》

上图是在二维空间中6位用户对Snakes 和 Dupree 这两Item评价的直观体现
就其意义而言,欧几里得距离越小,两个用户相似度就越大,欧氏距离越大,两个用户相似度就越小。
在日常使用中,一般习惯于将相似度与1类比,相似度在数值上反映为0<=Similarity(X,y)<=1,越接近1,相似度越高;等于1时则表示两人具有一样的偏好。那么我们在使用欧几里得距离时,可以通过 1/(1+Distance(X,Y))来贯彻上一理念,加一是为了避免遇到被零整除的情况。

欧几里德距离是指多维空间两点间的距离,这是一种用直尺测量出来的距离。如果将两个点分别标记为$(p_1,p_2,p_3....p_n)$和$(q_1,q_2,q_3.....q_n)$,则欧几里德距离的计算公式为:

$$\sqrt{(p_1-q_1)^2+(p_2-q_2)^2...+(p_n-q_n)^2} = \sqrt{\sum_{i=1}^{n}(p_i-q_i)^2}$$

oujilide.jpeg

计算图

python代码的实现

#返回一个有关person1与person2的基于距离的相似度评价
def sim_distance(prefs,person1,persion2):
    #得到shared_items的列表
    si = {}
    for item in prefs[person1]:
        if item in prefs[persion2]:
            si[item] = 1

    #如果两者没有共同之处,则返回0
    if len(si) == 0: return 0
    #计算所有差值的平方和
    sum_of_squares = sum([pow(prefs[person1][item]-prefs[persion2][item],2) for item in prefs[person1] if item in prefs[persion2]])
    #返回(距离+1)的倒数
    return 1/(1+sqrt(sum_of_squares))

启动 Redis

redis-server

查看 redis 是否启动(链接redis):

redis-cli

出现下面内容:
redis 127.0.0.1:6379>
127.0.0.1 是本机 IP ,6379 是 redis 服务端口。现在我们输入 ping 命令。
也就是:

redis 127.0.0.1:6379> ping
PONG

这就说明我们安装成功了。

操作远程redis: redis-cli -h host -p port -a password

redis支持5中数据类型

string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合)。