Giter Site home page Giter Site logo

jamch01.github.io's People

Contributors

gitbook-bot avatar jamch01 avatar

Stargazers

 avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

jamch01.github.io's Issues

签到打卡性质的文章

最近再修之前项目的bug,工作比较繁重……昨天没有签到,但是真的是写了一天代码。

好了既然开坑了,就得说说。

昨天见到了三年多没见的老李同志,激动的忘了偷拍留念。

坐在一起时候不自然的想起来很早的故事,可能七年前到现在。幸好,我们没有七年之痒的遭遇。但七年之间我们见面真是不多。甚至都不如我在这些年中那些泛泛之交见得多,很奇怪有些人见面多了就会觉得烦,有些人很久不见也不会冷淡。

这厮可能是为数不多的万年不见还和昨天见过一样的人之一。

就像昨天一样,我捧着电话和她聊天,因为长途电话得给我妈偷偷交话费;每天上学时候都很迫切的去学校传达处老大爷那里看看有没有我的信,然后上课时候偷偷拆开瞄几眼。

过几天见~

Python中 y != x - (x - y) 什么条件下成立

定睛一看这道题,mdzz这完全不成立啊,可是仔细想想就会得到意外的收获

成立答案一

当x,y为float时候

因为float的精度不足以支持

在某种程度上,判断float时候不应该使用==来判断是否相等,应该判断两者的差值。

成立答案二

当x,y为集合

像这样,x-y是图中纯绿色部分,y-(x-y)其实为x集合与y集合的交集,明显与y不相等。

x = set([1,2,3,4,5,6,7,8,9,0])
y = set([1,2,3,4,5,6,7,8,9,11,111])
y != x-(x-y)
# True

当然没有交集也成立

x = set([1,2,3])
y = set([4,5,6])
y != x-(x-y)
# True

N-Gram食用记录

N-Gram?

可以理解为N元模型,基于一定数量的语料信息,可以使用N-Gram评估一个句子是否合理,推测下一字符是什么。

假设一个句子S可以表示位一个由字或词组成序列W1,W2,W3,W4,……,Wn。则可以得到如下的结论:

P(S) = P(W1,W2,W3,W4,……,Wn) 

       = P(W1)P(W2|W1)P(W3|W1,W2)……P(Wn|W1,W2,...,Wn-1)

1+1>2

当样本信息的文字足够杂乱(极限情况为一篇文章没有重复出现相同的文字组合)时,此时的样本信息已经无法使用。

对此,可以引入马尔科夫假设解决问题。即:下一个词(字)的出现仅依赖于它前面的一个或几个词(字)。

与此同时N-Gram也有了不同的变化:

  • 假设下一个词的出现依赖它前面的一个词,则有:

    P(S)=P(W1)P(W2|W1)P(W3|W1,W2)...P(Wn|W1,W2,...,Wn-1)

    ​ =P(W1)P(W2|W1)P(W3|W2)...P(Wn|Wn-1)

    此时称为big-Gram

  • 假设下一个词的出现依赖它前面的两个词,则有:

    P(S)=P(W1)P(W2|W1)P(W3|W1,W2)...P(Wn|W1,W2,...,Wn-1)

    ​ =P(W1)P(W2|W1)P(W3|W1,W2)...P(Wn|Wn-1,Wn-2)

    此时称为tri-Gram

当然,可以选择向前取N个词(字)以获得更加精确的效果,但也会对你维护高阶马尔科夫假设带来了困难。

测试

N-Gram可能使用一个或多个N阶矩阵来表示相关的概率(次数)。矩阵的个数与马尔科夫假设的阶数相关(即向前关注多少个字)。

我使用了有向有权图来代替矩阵。但同样的是,在高阶马尔科夫假设时,仍然需要使用多张有向有权图来实现(或不同的属性名称)。

但为了方便测试达到效果,我采用了一阶马尔科夫假设(即当前字只与之前一个字有关)。样本文集使用了我国《宪法》。语句采用了《宪法》中的最后一句(中华人民共和国首都是北京及其反义句)。

代码见这里

效果分析

在有权有向图中,并没有对样本的计算样本的频率,而是使用样本的频数,得到的结果会很大。计算结果为:11005274908800

而在非法输入时,会得到样本文集中不存在”不是“(样本集中不存在)这层关系,但会根据已有的数据频数进行推测是不是要找"不得"。

初步达到了目标。

猜想

在以上我使用了N-Gram实现了输入纠错。在敏感词识别的时候,很大一部分有混淆的成分(如共*党)。也同时可以使用N-Gram进行语句的混淆检测,甚至还原(相较使用香农熵有很大的优势)。

MySQL中的“Too many connections”的原因。

😄

问题分析

首先,我认为存在即为合理。这种提示并非说是MySQL的问题,而是我们程序的问题。
我举一个简单的例子,在github_relationship中,我曾尝试使用PyMySQL来创建MySQL连接来进行相关的数据库操作。
这样看着似乎没有什么问题,但当使用多线程以后,会发现原本创建的连接无法使用。这是因为:在PEP249中,相关线程安全的描述如下:

threadsafety Meaning
0 Threads may not share the module.
1 Threads may share the module, but not connections.
2 Threads may share the module and connections.
3 Threads may share the module, connections and cursors.

我们可以得知,在标志为1时,线程之间可以共享模块,但无法共享连接。也就意味着我们的每一个线程连接数据库时,都需要创建相应的连接。

但这样就结束了么?

import pymysql.cursors

config = {
    'host': '127.0.0.1',
    'port': 3306,
    'user': 'root',
    'password': 'root',
    'db': 'test',
    'charset': 'utf8',
}

while True:
    connection = pymysql.connect(**config)
    # do something
    connection.close()

貌似这么写是结束了,但是不久就会出现我们题目中所提到的问题->Too many connections.

这是为什么?

对,我也有怀疑,为什么我分明关闭了连接(connection.close()),为什么还会出现这种错误?这个问题的答案就是,程序关闭了连接,而服务端并没有关闭。
怎么证明?

# 使用root登陆MySQL
show global variables like 'wait_timeout';

# 得到如下的信息
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| wait_timeout  | 28800 |
+---------------+-------+
1 row in set (0.00 sec)

这便就是MySQL的默认的超时时间,即8个小时(单位是秒)。在查询结束后,将连接置于sleep状态,即使不存在网络等其他因素的问题,也不能允许客户端长久的建立连接,即超过8小时候,MySQL服务端主动关闭连接。
官方描述:

wait_timeout:The number of seconds the server waits for activity on a noninteractive connection before closing it. On thread startup, the session wait_timeout value is initialized from the global wait_timeout value or from the global interactive_timeoutvalue, depending on the type of client (as defined by the CLIENT_INTERACTIVE connect option to mysql_real_connect()).

科学合理的解决

我想,这就是使用ORM的原因了。

由一道数学题引发的思考

这道题是这样的,一条绳子随机剪两刀,裁出的三部分能够拼接成三角形的概率是多少。
当然,来源图片是最好的

我的解法

当我第一眼看到这道题时,有一种惯性思维是把它当作了一道传统的古典概型题目。但仔细分析以后发现这是一个几何概型。

蛤?

这时,可以把问题转换为算面积的简单问题。
假设绳长L,三部分分别为x,y,z:
解法1
因为x,y,z分别是L的一部分,所以有
x + y + z = L
x > 0
y > 0
z > 0
同时,由x,y,z组成的图形为三角形,所以有
x + y > z
y + z > x
x + z > y
这是一个三元一次不等式组,在空间直角坐标系中可以画出其图像。
此处应该有个图。

解法2
类似于解法1,但引入了降维的**,将三维的事物转换为二维的事物。
因为x + y + z = L,所以有
z = L - x - y
x > 0
y > 0
L - x -y >0 y < x - L
而由三角形中,任意两边之和大于第三边,将z代入,
x + y > L/2
y < L/2
x < L/2
这是一个二元一次不等式组,在平面直角坐标系中可以画出其图像。
此处也应该有个图。

如果这时,我们假设所需要的解可以不是十分精确,或较为精确时,可以引入蒙特卡罗模拟进行问题的转换。这又将问题近似的转换为古典概型(单位事件有限,且等可能)。

import random

a = 0
for i in range(100000):
    L = random.randint(3, 100000 + 1)
    x = random.randrange(0, L)
    y = random.randrange(0, L - x)
    z = L - x - y
    if x + y > z and x + z > y and z + y > x:
        a += 1
print a

Flask中的异步

前提介绍

昨天碰到一个很可爱的人……:
我:我不会Django,我会Flask。
他:好啊,那咱们来谈谈Django吧。
我:……
他:如果请求无法即使完成,那么需要异步,怎么做?
我:tornado?

使用Flask实现的异步

我们清楚,在请求时,不可能立即获得结果,比如去请求某个爬虫接口(像企查查)来获得最新数据时,程序会阻塞在相应的函数中。在Flask中,我们举个简单的例子:

from flask import Flask
import time
app = Flask(__name__)


@app.route('/', methods=['GET'])
def hello_world():
    return 'Hello World'


@app.route('/async', methods=['GET'])
def async():
    time.sleep(10)
    return 'async'

if __name__ == '__main__':
    app.run(debug=True)

这是一个简单的Flask项目。在/中,直接返回Hello World,而在/async中,等待10秒后,返回async。我们都知道,在Flask中,如果使用默认的app.run()的方式启动,是很不科学的。因为这样会导致并发十分低下,而且没有异步处理。
进行如下的测试:

  1. 打开http://127.0.0.1/async,在地址栏输入完成,敲下回车后,立马进行2
  2. 打开http://127.0.0.1,观察结果

结果发现,即使在/中的数据是直接返回,但我们仍然等了很久,查看日志:

 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
 * Restarting with stat
 * Debugger is active!
 * Debugger pin code: 206-424-668
127.0.0.1 - - [15/Feb/2017 12:23:05] "GET /async HTTP/1.1" 200 -
127.0.0.1 - - [15/Feb/2017 12:23:15] "GET /async HTTP/1.1" 200 -
127.0.0.1 - - [15/Feb/2017 12:23:15] "GET / HTTP/1.1" 200 -

发现,访问/并没有立即执行,而是等待了10秒后执行。

那科学合理的方法是:

使用gevent

将代码稍作调整,

from flask import Flask
from gevent import monkey
monkey.patch_all()
from gevent.pywsgi import WSGIServer
import time


app = Flask(__name__)

@app.route('/', methods=['GET'])
def hello_world():
    return 'Hello World'

@app.route('/async', methods=['GET'])
def async():
    time.sleep(10)
    return 'async'

if __name__ == '__main__':
    http_server = WSGIServer(('127.0.0.1', 5000), app)
    http_server.serve_forever()

这时,我们进行相同的操作,观察到这回在输入/后,会立即返回数据。查看日志如下:

127.0.0.1 - - [2017-02-15 12:25:43] "GET / HTTP/1.1" 200 127 0.001000
127.0.0.1 - - [2017-02-15 12:25:49] "GET /async HTTP/1.1" 200 120 10.001000

即,使用gevent解决Flask异步(非阻塞)

当然用tornado才是王道

DVWA日常食用记录

DVWA

DVWA是一个PHP/MySQL的一个Web应用,其主要目的为了学习Web渗透相关知识的一个靶场环境。对于安全学习是一个很好的实例。

因为进入了一家安全公司,需要补充自身知识,于是开了这个坑。

因为恐惧,所以我想当个Hacker。

香农熵|信息熵食用记录

Shannon, Claude Elwood. "A mathematical theory of communication." ACM SIGMOBILE Mobile Computing and Communications Review 5.1 (2001): 3-55.

C. E. Shannon 在1948年的论文(这里)中提到了“任何信息都存在冗余,冗余大小与信息中每个符号(数字、字母或单词)的出现概率或者说不确定性有关。”。进而提出了“信息熵”的概念。

其公式表达如图:

H(x)表示为信息熵

n为符号系统中符号种类的数量,比如换做英语将会有26(大写)+26(小写)+1(空格)=53,但我们此时没有考虑标点符号

xi表示第i个字符

b为对数的底数一般取2为底,单位为比特。当然换成其他数字也是可以的,需要保证单位

p为概率

做个假设

采用独唱者文章《那个皮肤很黑的女孩》中的描述:

那个皮肤很黑的女孩,叫霞,其实霞除了长得黑以外,相貌并不比其他的女孩差。她坐在靠教室最里面的一行,好象永远不说话一样,老师提问她,她站得笔直,就是一声不吭。有时候我甚至不知道班里还有这样一个女生。后来我才知道,原来霞跟我居然是一个村的,学校前面有一条马路,她们家在马路的那边,我们家在马路的这边。

在汉语中,大概有3500个常用汉字(见这里),其中包括常用字2500个和次常用字1000个。但人们在日常学习生活中对文字的使用并不符合古典概型,即虽然单位事件是有限的,但每个单位事件的发生概率不同。

在假设中,我们的符号系统为语句中出现的文字信息。

又到了激动人心的show me the code的阶段了

    from math import log2
    import collections
    
    str = '那个皮肤很黑的女孩,叫霞,其实霞除了长得黑以外,相貌并不比其他的女孩差。她坐在靠教室最里面的一行,好象永远不说话一样,老师提问她,她站得笔直,就是一声不吭。有时候我甚至不知道班里还有这样一个女生。后来我才知道,原来霞跟我居然是一个村的,学校前面有一条马路,她们家在马路的那边,我们家在马路的这边。'
    m = collections.Counter(str)
    # m表示字符串统计结果
    # len(res)表示符号系统中种类数量
    res = set()
    for i in str:
        res.add(i)
    print('Shannon:{}'.format(-sum([c / float(len(res))
                                * log2(c / float(len(res))) for c in m.values()])))

得到结果:

Shannon:9.124763643803512

得到的结果表明,在这段话,使用符号系统可以使用9.1248bit表示。

使用Python如何获得一协议报文的信息

问题转换

我们无法或者很难用程序实现一个报文,于是有了Socket。所以,可以将这个问题转换为如何在Socket中如何查看某协议的报文信息。

构建服务端

我选用了HTTP协议,因为……不用构建客户端……
Ruslan的文章---Let’s Build A Web Server.中,很明确的告诉了我们应当如何构建一个简单的Web服务器。由于他使用的Python2,我修改了部分代码,可以在Python3上运行。

import socket
HOST, PORT = '', 8888
# 创建socket,默认参数family=AF_INET, type=SOCK_STREAM, AF_INET(IPV4协议的套接字)
# SOCK_STREAM是一种面向连接的socket(TCP)UDP是SOCK_DGRAM
listen_socket = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM)
listen_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
listen_socket.bind((HOST, PORT))
# 制定连接数,排队机制
listen_socket.listen(1)
print('Serving HTTP on port %s ...' % PORT)
while True:
    # 使用accept()方法等待连接
    client_connection, client_address = listen_socket.accept()
    # 接受最大的数据量
    request = client_connection.recv(1024)
    try:
        print(request.decode('utf8'))
    except UnicodeDecodeError:
        print('request is none')
    http_response = b"""
HTTP/1.1 200 OK

Hello, World!
"""
    # 使用send方法返回信息
    client_connection.sendall(http_response)
    client_connection.close()

客户端请求

使用HTTP的目的就是避免建立一个客户端……,那打开浏览器,输入http://127.0.0.1:8888/

信息

在客户端请求完成以后,并且受到了服务端的返回(就是在浏览器看到了Hello World)时,我们查看服务端程序的输出信息:

GET / HTTP/1.1
Host: 127.0.0.1:8888
Connection: keep-alive
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
DNT: 1
Accept-Encoding: gzip, deflate, sdch, br
Accept-Language: zh-CN,zh;q=0.8
Cookie: _ga=GA1.1.517976666.1487123574

GET /favicon.ico HTTP/1.1
Host: 127.0.0.1:8888
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36
Accept: image/webp,image/*,*/*;q=0.8
DNT: 1
Referer: http://127.0.0.1:8888/
Accept-Encoding: gzip, deflate, sdch, br
Accept-Language: zh-CN,zh;q=0.8
Cookie: _ga=GA1.1.517976666.1487123574

总共有两条,其中第一条是请求网站,第二条为请求favicon.ico。
这些已经足够了,拿出我们的HTTP请求报文格式来进行对比。

请求行部分:
由请求方法,URL和HTTP协议版本组成

请求头部分:
由key-value的格式组成
包括但不限于以下:
User-Agent:请求的浏览器标识
Accept:客户端可识别的响应内容类型
Accept-Language:客户端可接受的语言
Accept-Encoding:客户端可接受的压缩格式
Host:请求的主机名
Connection:连接方式
Cookie:Cookie

请求包体部分:
GET中没有诶,在POST等操作中有,即key-value的格式组成的请求参数

两种重复文章识别算法——TF-IDF算法和余弦相似性

简介

在爬虫爬取某些网站的文章时,经常会遇到恶意批量刷文章的行为。这些文章的url不尽相同,无法使用url进行过滤。这就导致了抓取了大量的,重复数据。但数学告诉我们,这事儿简单。

当然,不仅仅可以去除重复的文章。反过来讲,也可以归类近似的文章。

TF-IDF

TF-IDF实现原理

在介绍之前,是否还有其他方式实现这种过滤重复的方法?

有,统计文章的词频(TF)。按照常理我们认为,某个词重复的次数在文章中占比很大,我们就有理由相信这个词是文章的关键词(Key Word)。

对,这是一个很好的方法,我是用jieba分词,将简介中的那段话进行分词,我们一起看看结果。

import jieba
article = '''在爬虫爬取某些网站的文章时,
经常会遇到恶意批量刷文章的行为。
这些文章的url不尽相同,无法使用url进行过滤。
这就导致了抓取了大量的,重复数据。但数学告诉我们,这事儿简单。
'''
res = jieba.lcut_for_search(article)
print(Counter(res))

# Counter({',': 4, '。': 4, '的': 4, '文章': 3, '这': 2, 'url': 2, '了': 2, '不尽': 1, '爬虫': 1, '不尽相同': 1, '进行': 1, '爬取': 1, '经常': 1, '过滤': 1, '这些': 1, '会': 1, '数据': 1, '无法': 1, '我们': 1, '相同': 1, '时': 1, '简单': 1, '重复': 1, '抓取': 1, '批量': 1, '行为': 1, '网站': 1, '遇到': 1, '刷': 1, '恶意': 1, '某些': 1, '在': 1, '大量': 1, '事儿': 1, '导致': 1, '数学': 1, '使用': 1, '告诉': 1, '就': 1, '但': 1})

好吧,先忽略标点符号。那最多出现的就是这个字。类如这种词,在句中并无具体意义,我们将这种词称为停止词

在统计词频时,我们需要略过这种无意义的停止词。

假设文章爬虫重复这几个词的词频相同。根据一般认知,文章这个词的出现频率要比其他两个要高(在其他正常的文章中)。这就使我们无法确认文章是否是这篇文章的关键词。

这里,我们知道了TF是什么意思,接下来是IDF。

如果某个词十分少见,但在某篇文章中多次出现,那么这个词在很大程度上反映了这篇文章的主题。

在统计学中,我们对每个词语分配一个权重。如果这个词十分常见,那么这个权重值就会低;反之,则高。

这个权重值,就被成为逆文档频率(Inverse Document Frequency)

TF-IDF算法,即就是TF与IDF的乘积,它的值与某词语对于文章的重要性成正比。

计算方法

  1. 词频(TF)
    词频,顾名思义就是某个词语在文章中出现的次数。但为了避免文章长短的差异导致的差距,使用某个词出现的次数占总词数的百分比,来进行一个标准化。

  2. 逆文档率(IDF)
    使用逆文档率时,必须要有一个语料库。计算方法:

  3. 计算
    TF-IDF = TF*IDF

余弦相似性

余弦相似性(通过计算两个向量的夹角余弦值来评估他们的相似度。)

根据向量坐标,绘制在空间中,求得夹角的Cos值。Cos值越接近1,则说明夹角越小,即两向量相似。
更多

DEMO

  1. 给定两个句子
    A: 我喜欢足球,也喜欢篮球。
    B: 我喜欢足球,不喜欢篮球。

  2. 对句子进行分词,并统计词频

分词
A:我/ 喜欢/ 足球/ ,/ 也/ 喜欢/ 篮球 /。
B:我/ 喜欢/ 足球/ ,/ 不/ 喜欢/ 篮球/ 。

出现的所有的词语:
我/ 喜欢/ 足球 / 篮球/ 也/ 不

词频
A:我:1,喜欢:2,足球:1,篮球:1,也:1,不:0
B:我:1,喜欢:2,足球:1,篮球:1,也:1,不:1

词频向量
A:[1, 2, 1, 1, 0]
B:[1, 2, 1, 1, 1]

好了,这里我们就可以开始计算相似性了。
计算公式如下:

将上面的数据带入,得0.9354(保留四位小数)θ约为21.4300°(保留四位小数)。
那么,我们可以说A句和B句十分的相似。

Python

# -*- coding: utf8 -*-
import math
import jieba.analyse
article_a = '我喜欢**,也喜欢美国。'
article_b = '我喜欢足球,不喜欢篮球。'


def cut_word(article):
    # 这里使用了TF-IDF算法,所以分词结果会有些不同->https://github.com/fxsjy/jieba#3-关键词提取
    res = jieba.analyse.extract_tags(
        sentence=article, topK=20, withWeight=True)
    return res


def tf_idf(res1=None, res2=None):
    # 向量,可以使用list表示
    vector_1 = []
    vector_2 = []
    # 词频,可以使用dict表示
    tf_1 = {i[0]: i[1] for i in res1}
    tf_2 = {i[0]: i[1] for i in res2}
    res = set(list(tf_1.keys()) + list(tf_2.keys()))

    # 填充词频向量
    for word in res:
        if word in tf_1:
            vector_1.append(tf_1[word])
        else:
            vector_1.append(0)
            if word in tf_2:
                vector_2.append(tf_2[word])
            else:
                vector_2.append(0)

    return vector_1, vector_2


def numerator(vector1, vector2):
    #分子
    return sum(a * b for a, b in zip(vector1, vector2))


def denominator(vector):
    #分母
    return math.sqrt(sum(a * b for a,b in zip(vector, vector)))


def run(vector1, vector2):
    return numerator(vector1,vector2) / (denominator(vector1) * denominator(vector2))


vectors =  tf_idf(res1=cut_word(article=article_a), res2=cut_word(article=article_b))
# 相似度
similarity = run(vector1=vectors[0], vector2=vectors[1])
# 使用arccos计算弧度
rad = math.acos(similarity)
print(similarity, rad)

# 0.2157074518785444 1.353380046633586

A Simple Player for luoo.net

介绍

这个是很久之前就写过的程序,最近拉出来完善了一下。下载落网期刊部分所有的歌曲和图片

一些开发时候遇到的问题

最主要的就是播放音乐了,选择了好多最后使用了pyglet,可能这个库比较陌生,很简单的一个例子就是->PyMinecraft

在pyglet中播放音乐,需要依赖AVbin,开发者这么描述:

AVbin is a C library that provides a thin, cross-platform wrapper around Libav’s video- and audio-decoding functionality, providing long-term binary compatibility for applications and languages that need it. See also: Pyglet, a python media framework that makes extensive use of AVbin.

总结一下就是一个用C语言开发的库,提供Libav的视频和音频解码功能。

之后,在使用的过程中仍然有一个疑问,就是使用pyglet播放音乐时,只能播放第一首歌,无法列表播放。在翻阅schedule_once的源码以后得到了解决方法:

def exiter(dt):
	pyglet.app.exit()

for music in music_list:
    try:
        # 加载音乐
        player = pyglet.media.load(music)
    except Exception as e:
        logging.error(msg='需要使用AVbin支持播放,下载地址->http://avbin.github.io/AVbin/Download.html')
        return
    play_time = player.duration
    print('''正在播放‘{}’,总时长:{}s'''.format(music, str(play_time)))
    # 播放音乐
    player.play()
    # 设置延时任务,时间为正在播放的音乐时长,任务为退出pyglet(__exiter)
    pyglet.clock.schedule_once(self.exiter, play_time)
    # 启动pyglet
    pyglet.app.run()

项目地址

luowang

来谈谈Python中or与and

Python中空字符串为假,非空字符串为真。非零的数为真。

and

and是Python中的一个逻辑表达式,进行布尔运算但是返回的结果并不是一个布尔值

当所有值为真时,返回and后的值;当存在假值时,返回第一个假值

>>> 1 and 2
2
>>> 1 and 0
0

or

or也同and相同,但不同之处是返回第一个真值

>>> 0 or 1
1
>>> '' or 1
1
>>> '' or 0
# 这就尴尬了,没有一个真值这怎么玩
# 会默认返回最后一个值
0

记录一件在上海遇到的事儿

其实对于我来说,最喜欢的城市莫过于西安了。去过的城市也挺多了,也喜欢一些其他的城市,比如北京。但是要来上海出差,却让我觉得十分不开心诶。

不是我对这个城市有什么成见,而是我觉得不能与这个城市融为一体。我是个慢性格,又有一些懒散,但这里的快节奏生活却是让我很难适应。加之出差的日子也可以偶尔偷懒,这就让我和这个城市里的其他人看起来更加有区别了。

但我有时候也在这里思念北方的日子,可能是喜好的原因,我喜欢听北京话。在北京时候我甚至搬了一个小板凳在胡同里听着那些老头老太太在侃大山,然后我也加入了~

在这里我确实没法这样,语言不通,哪怕他们说的很慢我也很难听懂吴侬软语。而且这里的人们似乎对外来人有着天生的不友好。是啊我也不喜欢你诶

但是下午经历了将近三个小时的地铁以后,从张江到呼兰路,再到七宝。长时间在地铁里面总让人觉得不是十分舒服。出了地铁,今天的上海的狂风让人清醒了不少。在七宝办完事儿之后,因为觉得张江的饭菜实在难吃就去了之前在七宝十分喜欢的面馆。

还是那家店,和那个亲切的老板,可是他漂亮女儿不在诶~,难怪今天周四,应该在上课。

还是点了葱油面,加着喜欢的浇头,吃着十分舒服。在结账时候老板问我:“小伙子,最近去哪里啦?”

“嗯,公司搬到了张江,我今天回来办点事儿。”,我回答道,“您还记的我?”。

“是啊,一个人一顿饭吃了一份葱油面,又吃了一份抄手很少见啊。”

“哈哈哈,以后我常来。”

本来我并不喜欢这个城市,我觉得这里没有人情味,没有历史的浓重的感觉。但这个时候我发现我错了。

最后,我相信老板您肯定看不到这篇文章,但我仍然祝您生意兴隆,财源广进。

TextRank和PageRank初探

算法简介

Google的经典算法--PageRank点击了解更多关于PageRank

PageRank的核心目标在于计算网页的重要性,从而提供一个自上向下的排名。而TextRank主要为文章中的单元的重要性(或关键词)。

计算方法

我们煮一个简单的栗子。(如果你想看的更多请移步至PageRank算法简介及Map-Reduce实现,本例为其例子的简化版)

首先模拟一个PageRank的场景,如图(在本例中,假设互联网中只存在4个页面ABCD。且满足:1. 图是强连通的,即从任意网页可以到达其他任意网页;2.禁止出现网页不存在指向其他网页的链接,但存在指向自己的链接。):

当某位用户在访问A页面时,他有1/3的概率去访问BCD页面中一(在AB之间的直线A→B表示A可以访问B,BA中的B→A表示B可以访问A。相对于A来说,前者为出链,后者为入链)。

同理,在D页面时,有1/2的概率访问BC,依次类推可以画出一个表格:

---- A B C D
A 0 1/2 1 0
B 1/3 0 0 1/2
C 1/3 0 0 1/2
D 1/3 1/2 0 0

使用矩阵表示为:

在第一次访问时,由于现在的模型符合古典概型,即访问的页面是等可能的,即访问每个页面的可能性都为1/4,Vn表示第n次访问的概率

在未来的多次访问中,我们用相同的方法计算,直到矩阵收敛(Vn=MV(n-1)):

即此时的矩阵为页面的PageRank。

DEMO

todo

More

我们可以有PageRank算法推演出TextRank算法。这个算法是由Rada Mihalcea and Paul Tarau 提出,论文在这里。将文章分割成若干单元(可能是句,也可能是词)后,简历图模型。利用投票机制使得文本中的单元可以进行重要性排序。这种模型相对于HMM来说不需要更多的训练;对于以前提到的两种重复文章识别算法——TF-IDF算法和余弦相似性来说,有好的机制。

Linux说:“我不知道你为什么写我”。

如何查看某一进程真实内存使用?

top

这个问题不自觉地想到了使用top命令,

在途中比较接近表格的数据中,各个表头分别代表:

PID:进程的ID
USER:进程所有者
PR:进程的优先级别,越小越优先被执行
NInice:值
VIRT:进程占用的虚拟内存
RES:进程占用的物理内存
SHR:进程使用的共享内存
S:进程的状态。S表示休眠,R表示正在运行,Z表示僵死状态,N表示该进程优先值为负数
%CPU:进程占用CPU的使用率
%MEM:进程使用的物理内存和总内存的百分比
TIME+:该进程启动后占用的总的CPU时间,即占用CPU使用时间的累加值。
COMMAND:进程启动命令名称

当查看具体某一进程时,可以使用管道过滤,比如->top |grep 'python3'

使用参数 -u [username] 查看某一用户所占用的内存,比如->top -u root

当然,今天情人节,你能看得懂所有进程名,并且知道他们是做什么的,不用考虑,你一定是单身。

如何查看Linux负载?

开机时间(运行时间)

[root@Ubuntu ~]# w
 10:37:03 up 16 days, 14:58,  1 user,  load average: 0.16, 0.14, 0.14
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
root     pts/1    255.255.255.255  10:26    7.00s  0.01s  0.00s w

进程相关

还是top中的图片,我们现在关心一下前五行。

Tasks: 124 total,   2 running, 120 sleeping,   2 stopped,   0 zombie
# Tasks表达了目前系统中的总进程数及状态,需要注意zombie
top - 10:40:41 up 16 days, 15:01,  1 user,  load average: 0.03, 0.10, 0.13
Tasks: 124 total,   2 running, 120 sleeping,   2 stopped,   0 zombie
%Cpu(s):  4.7 us,  1.7 sy,  0.0 ni, 93.0 id,  0.7 wa,  0.0 hi,  0.0 si,  0.0 st
# Cpu(s)表示CPU目前运行的状态,us表示用户使用,sy表示内核使用,id表示空闲,wa表示IO等待使用
KiB Mem :  1016796 total,    72832 free,   712588 used,   231376 buff/cache
# Mem行展示了当前内存的状态,total总的内存,userd是已使用,free是剩余,buff/cache是目录缓存。
KiB Swap:        0 total,        0 free,        0 used.   137848 avail Mem
# 大部分同上,

走进迷信——A君B站二三事

这是一道计算机网络这门课特别爱考的题目,但是我相信,即使是计算机老司机也不一定能够说清楚在一台PC上访问某一页面时候到底经历了什么。

做出如下约定

假如网络遵循如下拓扑,这是一般家庭很常见的拓扑结构。
日后再补……
为了避免名字上的冲突,称A君和B站。

前提

一个安静的晚上,A君回到家中,吃过晚饭,又到了打开某些网站的时候了。这是一个普通的人——A君每天都要做的事情。此时他觉得自己真的十分放松。

又是熟悉的浏览器,又是熟悉的B站,和熟悉的操作。

在一番翻云覆雨过后,A君不禁产生了疑问,我这么做又有什么意义?不过,和往常不同的是,A君这回对自己访问B站时,究竟是怎样的过程产生了疑问。那就让我们带着问题,走入今天的《走进迷信——A君B站二三事》。

走进迷信

互联网中,我们都知道是使用IP作为标记的,但是复杂的IP地址恐怕很少有人能够记的住,于是就有了域名,举个例子也就是我们的B站。

在一番探索过后,A君发现,第一步竟然是打(输)开(入)浏(B站)览(域)器(名)!!!

按照常理来说会通过DNS来查询B站的域名对应的哪台主机IP,然后再去访问。但事实时这样的么?

A君产生了疑问,是啊,这样操作没有问题。但是我每次都要进行同样的查询么?

不,当然不是。

A君又一次经过查询得知,浏览器大多都会缓存DNS,比如自己使用的Chrome,会在[这里](chrome //net-internals/#dns)进行缓存。于是A君清除了浏览器的DNS缓存。又一次打开了B站。

此时A君通过DNS缓存知道了B站对应的IP(1.1.1.1),这时,他想起了多年前番羽墙去国外的网站看小电影的经历。于是在想当没有DNS时候,是否可以通过修改hosts文件达到相同的效果。

于是便打开了自己的hosts文件,进行了如下的编辑

b.com 1.1.1.1

保存后,取消了DNS服务,同时清除了DNS缓存,发现B站仍然可以打开。这时候A君嘴角挂上了**的微笑。又不禁翻云覆雨来奖励自己一番。

快乐的时光总是那么短暂,A君突然看到了自己桌上摆的路由器,突然想到,成功?我才刚刚上路啊!

看着路由器,他浑身颤抖了,是啊,还是没有解决如何访问啊!

他又穿戴整齐,坐在椅子上,打开了自己的网络配置,突然一个叫做默认网关的选项引起了他的注意。他发现这个与自己的路由器管理界面的地址竟然一模一样!

这时,他想到自己的网卡有地址(MAC地址),自己的PC也有地址(IP地址),自己也有网关的(IP地址),唯独缺一个网关的MAC地址就可以搞事情了哇。

嗯,ARP。

此时,他不禁想起来了上学时老师讲的ARP协议,于是打开了终端输入

arp -a

他惶恐了,这……就获得了ARP表(IP-MAC对应)此时大功告成!

但是又细细想来,又输入了

arp -d

便删除了ARP的缓存表,他想一探究竟!

结果仍然可以获得,这是因为PC在本地没有ARP信息时,会像路由器请求,当请求的IP和自身IP在同一网段时,就用自身的接口相连。否则就用网关的接口。

至此,我们整理一下手中的信息。

如果DNS缓存,hosts文件均不存在B站时候,PC会向设置的DNS服务器发送请求,查询B站对应的IP,并根据此IP去访问。

在查询DNS的过程中,PC会先查询自己的DNS设置,根据DNS分部的不同分为外部DNS和本地DNS。

本地DNS,系统会使用ARP查询到DNS服务器的MAC后进行查询。
外部DNS,系统会使用ARP查询默认网关后在进行DNS查询。

当DNS缓存,hosts文件存在B站时,PC会优先使用DNS缓存和hosts文件中的记录。

这时,A君的兴致盎然,他想第三次奖励自己的时候,发现已经很累了。但是对于未知世界的探索,还是让他继续的努力下去。

至于B站服务端如何A君觉得自己管不了,总之是返回一个HTML。那就有的搞了。

HTML中包括了HTML,CSS,JS等数据。浏览器会首先解析这一部分数据。而后构建DOM树,渲染资源,布局,最后展示。

尊重版权

在午休时间开始写这篇文章。

昨天向jetbrains申请了student license,但是因为学校并不提供edu邮箱(其实学校的官网也不是.edu)。跟jetbrains比较详细的描述了我的情况以后,jetbrains竟然通过了我的申请。

很意外很惊喜。

申请的主要原因是lanyus分享出来的key失效了,而且我也觉得使用他人的key是一件很猥琐的事情。虽然我很少使用pro版本,community已经足够我使用。但是jetbrains其他的IDE或者工具仍然是十分优秀的。

所以我想到了洗白。

为什么编程语言开源免费,而IDE却收费,或者我应该不应该去交IDE的钱?我想这是很多人的疑问。既然使用了服务我想去交钱也是应该的。很滑稽的事情是百度的搜索框中输入PyCharm以后,通过NGram算法不全的大多是激活码,破解版。难为百度了。

我相信大多数语言不需要IDE,使用notepad足够编写,但却仍然有很多人去选择IDE的原因是写着舒服啊,有代码提示啊等等原因。这是IDE的dev提供的便捷的服务,但同时使用的时候请尊重他们的劳动。

很简单,因为我们还没有制造出来某些值得让别人去山寨的东西,所以我们的版权意识并没有那么严苛。比如Office365一天一块钱而已,当然不想付可以选择免费的libre office。

这也可能是早期的“拿来主义”的影响,而采用了真正的拿来。

很滑稽的一件事是SSR的作者breakwa11之前违背开源协议不开源SSR,但因为是一姑娘竟然有很多人为她洗地。

Forking and merging, that's how open source works.

最后再附上clowwindy的

最适合这个民族的其实是一群小白围着大大转,大大通过小白的夸奖获得自我满足,然后小白的吃喝拉撒都包给大大解决的模式。通过这个项目我感觉我已经彻底认识到这个民族的前面为什么会有一堵墙了。没有墙哪来的大大。所以到处都是什么附件回帖可见,等级多少用户组可见,一个论坛一个大大供小白跪舔,不需要政府造墙,网民也会自发造墙。这尼玛连做个翻墙软件都要造墙,真是令人叹为观止。这是一个造了几千年墙的保守的农耕民族,缺乏对别人的基本尊重,不愿意分享,喜欢遮遮掩掩,喜欢小圈子抱团,大概这些传统是改不掉了吧。
现在维护这些项目已经越来越让我感到无趣。我还是努力工作,好好养家,早日肉翻吧。

我为什么不用issues写博客,真的是太蠢了

以前纠结于wordpress,typecho,hexo,ghost和不拉不拉,直到刚刚才想到issues也是一个很好的写博客的平台。

嗯,就是太懒了,这里有我最基础的要求->支持Markdown,以及支持评论(虽然多说也是可以的,但是我还是喜欢这里)。

那以后就使用issues了~

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.