前言

好烦啊,一直搞不定
下面只是记录我踩过的一些坑,大家不要看了

背景

默认的video标签会有下载按钮,而且不能倍速播放,于是使用了video.js
为防止下载video禁止掉了右键菜单
目前存在的问题

  • 打开调试或者查看原网页可以直接看到视频链接
  • 手机端会之间显示浏览器的播放界面,都有直接下载的按钮

途径

坑1 修改referrer

想通过referrer判断是否是播放还是直接下载(先假设下载都是空referrer)
video.js不能直接控制http请求,不能控制referrer
控制全局referrer可以在head中加下面这句

1
<meta name="referrer" content="always/never/origin/default">

应该是下载空referrer这个假设本来就有问题,这条路堵死了

坑2 blob

blob用于处理二进制文件,youtube和bilibili都是用的blob,看起来很promising
但是我不会用啊。。。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<video id="id" width="320" height="240"  type='video/mp4' controls  > </video>

window.onload = function() {
var xhr = new XMLHttpRequest();
xhr.open('GET', 'mov_bbb.mp4', true);
xhr.responseType = 'blob'; //important
xhr.onload = function(e) {
if (this.status == 200) {
console.log("loaded");
var blob = this.response;
var video = document.getElementById('id');
video.oncanplaythrough = function() {
console.log("Can play through video without stopping");
URL.revokeObjectURL(this.src);
};
video.src = URL.createObjectURL(blob);
video.load();
}
};
xhr.send();
}

可以工作,但需要先把视频加载一遍才能看,意思是这个页面加载时间要以分钟来记了。。。
而且还有跨域的问题

坑3 阿里云的flash

这个坑还没踩进去,但是还是不想用flash,都2018年了啊

后面的坑

  • 不行就用ua,把手机端的禁掉,然后pc端由他们下去吧
  • 然后再看看这个链接里的方法,说不定能用呢😢
  • 近期不搞了,先专心写毕业论文吧

0. 关于火车,关于回家

这篇是在火车上写的,回家坐火车会有种奇妙的感觉,大概一学期也就这么一次,你不会为挥霍时间而慌张,反而是时间越快越高兴,大概是家的魔力吧。

所以这篇思路可能会有点跳,想到哪写到哪吧。

1. 关于博客,关于js

之前我一直不愿意用hexo写博客,几个原因,

  1. 这种静态的博客,一点逼格也没有,连个留言都要第三方插件解决
  2. 没有博客对编辑界面,只能在某个特定对电脑上写,然后再推上去
  3. 我不会node

然而最终还是意外地向hexo妥协了,还是那么几个原因,

  1. 好像我的博客不会有人注册或留言的,静态也够用
  2. 我已经人机合一了。。。
  3. 我对python的热爱被flask终结掉了,我想换个语言了
  4. 想通了一个道理,不拥抱js/css,网站一定会很丑。。。

所以还是要感谢FJ,在我下定好决心学node又不知道做什么的时候,FJ说要有小程序,于是就有了小程序于是我就像突然看到了灯塔一样,也突然有了动力。

其实也是挺奇怪的事,我也早早想到过小程序,但是呢,所有自己想到的项目,都会在心里自动贴一个标签,练手。然后练手两个字,就完全限制了这个项目的意义,练到手熟之后呢,大概就不了了之了。FJ的作用,大概只是说了句小程序,然后提了一堆我看来奇奇怪怪的需求。但也是因此,这个本来应该是练手的项目,它的意义就足以支撑我认真做下去了。

所以啊,我还是一个靠意义活着的生物,不管真假。

2. 关于圣经旧约

我是这学期开始看圣经的,当然正如你们所见的,我是个温和的共产主义者。看圣经完全是出于好奇心,主要是《西部世界》带起来的。

故事性不强而且很散,为了怕我看了就忘了,先把看了的部分记下来。

如有错误或冒犯,烦请指正。

  • 上帝创世,嗯。
  • 然后就是伊甸园里,撒旦化身成蛇,引诱夏娃亚当吃了禁果,然后他们知羞耻。上帝惩罚蛇用肚子走路,女人见蛇就踩,蛇见女人就咬脚后跟,男人需要劳作才能收获果实,然后把亚当夏娃逐出伊甸园。
  • 亚当夏娃大儿子该隐种地,二儿子亚伯放牧。该隐献给上帝谷物,亚伯献给上帝羊羔,上帝喜欢亚伯的礼物,该隐妒嫉,遂杀弟。
  • 后来世风日下,god has seen too much evil,上帝后悔造了人,于是计划大洪水大清洗一下。
  • 让诺亚造船,然后每个动物带一对。水落之后,诺亚放出鸽子,鸽子衔橄榄枝返回,诺亚于是知道水完全退了。上帝以彩虹立誓,不在用洪水灭世。
  • 上帝让诺亚的长孙亚伯拉罕带着族人去往应许之地迦南。但亚伯拉罕的侄子罗德,执意去往索多玛。索多玛后被周围国家所灭,罗德通遭罪,亚伯拉罕于是去解救。
  • 亚伯拉罕妻子不会生孩子,两个人急了,于是找婢女夏甲生了孩子,取名实马里。后上帝赐子亚伯拉罕,并取名为以撒。
  • 上帝说索多玛恶贯满盈,要毁灭索多玛。亚伯拉罕恳求,上帝答应只要索多玛能有十个好人,就放过这里。前来考察的两个天使遇上罗德,罗德招待他们,但索多玛的全城老幼却要求罗德交出客人。天使让罗德一家逃难,然后毁灭了索多玛。罗德妻子在逃跑时,回头看,变成盐柱。
  • 上帝考验亚伯拉罕,亚拿儿子献祭,上帝及时制止,并送了只羊羔。
  • 以撒母亲帮儿子从她的族人中,选取了妻子利百加。
  • 利百加也不能生,于是上帝让她怀上了双胞胎,分别是以扫和雅各。雅各骗取了哥哥以扫的长子权,骗取了父亲本应该给以扫的祝福。以扫恨之入骨,雅各逃往舅舅拉班家。
  • 拉班有两个女儿,小女儿好看。雅各给舅舅放羊,舅答应七年之后把好看的小女儿嫁给雅各。七年之后,过完新婚之夜,雅各发现嫁给她的时大女儿。因为按照当地习俗,妹妹不能比姐姐先嫁。于是雅各又答应给拉班放七年羊,然后和妹妹结婚。
  • 婚后雅各只喜欢妹妹,冷落姐姐,于是上帝让姐姐怀孕。反正后来姐妹互相争宠,给雅各生了一堆孩子。雅各放羊放着放着就变得很富有,拉班及其子妒嫉,于是上帝让雅各回到故乡。
  • 好长好啰嗦,后面慢慢更。

1. 基本定义

特征值分解
$$ A = \boldsymbol{V}diag(\lambda)\boldsymbol{V}^{-1} $$
奇异值分解类似,但不要求A是方阵
$$ A = \boldsymbol{UDV}^T$$
假设$A$是(m,n),那么$\boldsymbol{U}$是(m,m),$\boldsymbol{D}$是(m,n),$\boldsymbol{V}$是(n,n)。$\boldsymbol{U}$、$\boldsymbol{V}$均为对称矩阵,分别称为左奇异向量,右奇异向量,$D$是对角矩阵,其对角元素称为奇异值。
两者关系
$A$的左奇异向量,是$AA^T$的特征向量,$A$的右奇异向量,是$A^TA$的特征向量。$A$的非零奇异值,是$AA^T$和$A^TA$的特征值的平方根。

2. 待续吧

等我知道了SVD怎么算之后再写。

1
2
<div id="wrap{{ subject.id }}" class="wrap">{{ subject.about_subject | safe }}</div>
<div id="read-more{{ subject.id }}" class="read-more"></div>
1
2
3
4
5
<style>
.wrap{position: relative;overflow: hidden;}
.read-more a{padding-right: 22px;background: url() no-repeat 100% 50%;font-weight: bold;text-decoration: none;}
.read-more a:hover{color: #000;}
</style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<script type="text/javascript">
{% for subject in subjects %}
$(function(){
var slideHeight = 300; // px
var defHeight = $('#wrap{{ subject.id }}').height();
if(defHeight >= slideHeight){
$('#wrap{{ subject.id }}').css('height' , slideHeight + 'px');
$('#read-more{{ subject.id }}').append('<a href="#">查看更多</a>');
$('#read-more{{ subject.id }} a').click(function(){
var curHeight = $('#wrap{{ subject.id }}').height();
if(curHeight == slideHeight){
$('#wrap{{ subject.id }}').animate({
height: defHeight
}, "normal");
$('#read-more{{ subject.id }} a').html('隐藏');
}else{
$('#wrap{{ subject.id }}').animate({
height: slideHeight
}, "normal");
$('#read-more{{ subject.id }} a').html('查看更多');
}
return false;
});
}
});
{% endfor %}
</script>

来自这里
css 子元素设置为float之后,脱离文件流,导致父元素撑不起来,解决办法

  1. 父元素也设置为float(不推荐,会影响父元素后面都元素)
  2. 父元素添加 overflow:hidden(诡异的css)
  3. 建立一个空的子div <div style="clear: both"></div>
  4. 通过伪类:after清除浮动,具体如下
    1
    2
    3
    <div class="father">
    <div class="son">子元素</div>
    </div>
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    .son {
    float: left;
    }
    .father:after {
    content: "";
    height: 0;
    width: 0;
    visibility: hidden;
    clear: both;
    display: block;
    }

抄自这里

form的enctype属性为编码方式,常用有两种:application/x-www-form-urlencodedmultipart/form-data

默认为application/x-www-form-urlencoded。 当action为get时候,浏览器用x-www-form-urlencoded的编码方式把form数据转换成一个字串(name1=value1&name2=value2…),然后把这个字串append到url后面,用?分割,加载这个新的url。 当action为post时候,浏览器把form数据封装到http body中,然后发送到server。

如果没有type=file的控件,用默认的application/x-www-form-urlencoded就可以了。 但是如果有type=file的话,就要用到multipart/form-data了。浏览器会把整个表单以控件为单位分割,并为每个部分加上Content-Disposition(form-data或者file),Content-Type(默认为text/plain),name(控件name)等信息,并加上分割符(boundary)。

更详细的

dump database

1
2
3
4
sqlite3 <database_file>
.output <dump_text_file>
.dump
.exit

dump table

1
2
3
.output <dump_text_file>
.dump <table_name>
.exit

dump table structure

1
2
3
.output <dump_text_file>
.schema
.exit

dump data of a table into a text

1
2
3
4
.mode insert
.output <dump_text_file>
.dump <table_name>
.exit
1
.read <dump_text_file>

0. 前言

作业在这里
原仓库被coursera要求删掉了,多亏我及时folk/斜眼笑

视频可以直接在网易上看

1. 神经网络前馈和后馈



如果没有激活函数的话,多层的神经网络仍然是个线性的模型。

2. 超参数、正则化、优化算法等

L2正则化相当于是w权重减小, weight decay

后面等这些是用在mini-batch中的,当训练数据量太大,需要对训练数据分割为mini-batch。但这样会造成收敛方向波动,为了减小这种波动,引入Adam优化算法。




batch norm

3. CNN

待续

感觉这篇已经总结得很好了

1. gunicorn

python用的是anaconda 2.7,首先安装虚拟环境
好像是anaconda下用virtualenv会有点问题
gunicorn的w表示开启进程数
PS: nohup的详细解释

1
2
3
4
5
conda create -n newenv python=2.7 
source activate newenv //启用python 虚拟环境
pip install gunicorn //安装gunicorn
nohup gunicorn -w 4 --access-logfile access.log --error-logfile error.log -b 127.0.0.1:8080 manage:app&
app_file_name:app_name &

gunicorn更改log的输出,详细说明

1
2
--access-logfile FILE
--error-logfile FILE, --log-file FILE

2. nginx

1
yum install nginx

然后修改nginx配置,转发至localhost的端口

1
2
3
4
5
6
7
8
9
10
server {
listen 80 default_server;
server_name _;

location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}

检查nginx config,重启nginx

1
2
nginx -t
service naginx restart

3.nginx反向代理和防盗链

为了防止静态资源被其他站点请求,改为return 403
但这样一来,本站请求的静态资源在经过static后,不再做转发,所以又把转发重复了一遍。
不知道有没有更优雅的写法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
server {
listen 80 default_server;
server_name _;

location /static/ {
valid_referers 47.95.193.53;
if ($invalid_referer) {
return 403;
}
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}

反爬虫

1
2
3
4
5
6
7
location / {
if ($http_user_agent ~* "python|curl|java|wget|httpclient|okhttp") {
return 503; #service unavaiable
}
# 正常处理
...
}

4.坑比阿里云的smtp端口

阿里云默默地把smtp的25端口禁掉了,要使用ssl的465端口
使用flask-mail需要在config.py 中配置

1
2
3
MAIL_SERVER = 'smtp.163.com'
MAIL_PORT = 465
MAIL_USE_SSL = True

https原理

比较严肃,看这里

下面的部分比较好懂,其实是抄的这里

引言:从传纸条的困境说起

想象一下,你和班上的心仪对象相距甚远,只能依赖中间的同学帮忙传递纸条来交流。一开始一切甜蜜,但很快就出现了两个致命的问题:一是有人偷看纸条,把你们的秘密作为茶余饭后的谈资;二是有人篡改内容,导致你们之间产生误会。

为了解决这个问题,你必须在所有信息交互都必须通过中间人传递的前提下,找到一种安全通讯的方法。这套“顶级的阳谋”就是今天网络安全传输的基石——HTTPS协议。


第一步:保护内容——对称加密

最初的想法很简单:把要传递的消息放到一个带锁的盒子里。发送方使用一把钥匙上锁,接收方再用同一把钥匙解锁。这把钥匙就是“密钥”,这种加密和解密都使用相同密钥的方式,被称为对称加密

对称加密虽然保护了信息本身的安全,但在现实场景中存在一个根本性缺陷。由于所有信息必须通过中间人传递,这把用来加密的密钥也必须通过中间人来传递。一旦中间人知道了密钥的信息,你们的通信就不再安全了。

问题核心: 如何在不安全的通道中安全地传输密钥?简单地用多层对称加密套娃是行不通的,因为最外层的密钥始终存在泄露的风险。


第二步:保护密钥——非对称加密

为了解决密钥传输问题,聪明的人们发明了一种神奇的锁,它拥有两把钥匙:A和B。

这种锁的神奇之处在于:如果用A钥匙加锁,必须用B钥匙解锁;反之,如果用B钥匙加锁,则必须用A钥匙解锁。这种加密和解密使用不同密钥的方式,被称为非对称加密

在这种机制下,我们定义两种密钥:

  1. 私钥 (Private Key A): 只有你自己知道,没有告诉任何人。
  2. 公钥 (Public Key B): 对所有人公开。

通过非对称加密,我们得出一个关键结论:公钥加密,私钥解密,可以实现消息的保密传输

利用非对称加密传输对称密钥(M)

现在,我们可以利用非对称加密的特性,安全地传输用来进行日常通信的对称密钥(M)。

这个过程分为三步,目的是让你的对象把密钥M安全传输到你手中:

  1. 公开公钥: 你将你的公钥 B 传给你的对象(相当于对外公开了,中间人可以保留一份,无所谓)。
  2. 加密密钥: 你的对象用收到的 公钥 B 加密他们手中的对称密钥 M
  3. 安全接收: 你的对象把加密后的消息传给你。只有你手里的 私钥 A 才能解密拿到对称密钥 M

此时,双方手中掌握了同一个对称密钥 M,就可以安全通信了。由于中间人没有你的私钥 A,他们无法解密。


第三步:防止篡改——中间人攻击与数字签名

虽然非对称加密保护了对称密钥 M 的传输安全,但新的问题随之出现:公钥 B 的传输仍然是明文的。尽管你不怕中间人看到公钥,但你必须警惕他们篡改公钥。

中间人攻击 (MITM)

中间人攻击的过程是绝妙且危险的:

  1. 在你将公钥 B 传给你的对象时,中间人将其拦截并替换成自己伪造的伪造公钥发送给你的对象。
  2. 你的对象用中间人伪造的公钥加密 M。此时,中间人可以轻易解密拿到 M
  3. 随后,中间人再用真正的公钥 B 加密 M,发送给你。
  4. 你用自己的私钥 A 解密,成功拿到 M,并未发现任何问题。
  5. 你的对象也未发现问题。

最终,中间人神不知鬼不觉地知道了你们的通信内容 M。

解决方法:签名与验证

为了防止信息被篡改或伪造,我们引入了另一个非对称加密的应用:私钥加密,公钥解密

  • 私钥加密:通常叫做签名
  • 公钥解密:则是验证签名的过程,叫做验签

通过这种方式,我们可以在传输公钥 B 时,再套一层非对称加密,用一个私钥 C 加密,让对方用对应的公钥 D 来解密。如果中间人想要篡改里面的信息,他们就需要用私钥 C 重新加密,而私钥 C 是中间人不知道的,因此无法篡改。

新的挑战: 然而,公钥 D 此时又变成了明文传输,仍然可能被中间人篡改。如果不断套用非对称加密来保护上一层的公钥,问题永远无法根治。


第四步:信任体系——引入 CA 机构

光凭通信双方自身,无法解决公钥被篡改的根本问题,必须引入一个可信的第三方来帮忙。

现在的核心问题是:如何防止中间人在公钥 B 传输过程中篡改它?

  1. 委托第三方签名: 你将公钥 B 交给一个可信的第三方(CA机构)。这个第三方机构也拥有一套公私钥。
  2. 生成数字签名: 第三方用自己的私钥对公钥 B 进行加密,形成一个数字签名
  3. 传输与验证: 你将这个数字签名和你的公钥 B 一起发给你的对象。
  4. 信任验证: 你的对象使用第三方的公钥解密。一方面可以拿到你的公钥 B,另一方面也可以进行比对,确认它是否被篡改。

有人可能会问:中间人是否可以伪造一个第三方的公钥,像刚刚那样进行中间人攻击呢?

答案是:可以,但中间人胡乱生成的公钥不具备可信度。只要接收方增加一步验证环节——如果这个公钥不属于大家公认可信的第三方,就拒绝后续的通信过程

我们将这个公认可信的第三方权威机构叫做 CA(Certificate Authority),即证书颁发机构


总结:HTTPS 的诞生

将你和你的对象换成计算机,将中间传递纸条的同学换成网络环境,那么这一整套用于网络安全传输的协议就叫做 HTTPS

现在我们访问网站,地址基本都是以 https:// 开头的。例如,在 Chrome 浏览器中打开百度,你可以看到 CA 机构的名称、网站的公钥以及数字签名等信息。

HTTPS 的目标:帮助通信双方协商出一个用于对称加密的密钥 M。而中间人的目标是想方设法神不知鬼不觉地知道这个 M 是什么。

为了实现这一目标,HTTPS 建立了一个层层保护的机制:

  1. 内容保护: 使用 M 进行对称加密。
  2. 密钥 M 保护: 套上一层非对称加密来传输 M。
  3. 公钥保护: 再通过 CA 机构做签名,防止非对称加密中使用的公钥被篡改。

当你毫不在乎地在浏览器里输入地址时,请记住这个毫不起眼的 HTTPS,它是人类的智慧结晶。这是深处完全不可信的网络环境中的一套顶级阳谋,让你可以在全世界的眼皮子底下安心对话


小结:HTTPS就像一个高度复杂的邮寄系统。我们最终目的是用一把简单的锁(对称加密 M)来传输信件。但为了安全地把这把锁的钥匙 M 送到对方手上,我们先把它放进一个只有你才能打开的保险箱里(非对称加密)。为了确保这个保险箱的接收地址(公钥)没有被邮递员(中间人)偷偷换掉,我们请来一个公证处(CA)盖章认证。只有公证处认证过的地址,这个保险箱才会被信任和接收。

使用流程

  1. 阿里云或七牛云的免费ssl服务,阿里云不用填什么资料直接就审核了,七牛云好像麻烦一点。
  2. 配置DNS
  3. 审核通过之后,下载证书文件,将证书文件放在Nginx安装目录cert中,一般为/etc/nginx
  4. 配置nginx,主要是将http重定向到https上
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    server {
    listen 80;
    server_name _;

    location / {
    rewrite ^/(.*)$ https://yongxinxue.xin/$1 permanent;
    }
    }

    server {
    listen 443;
    server_name _;
    ssl on;
    ssl_certificate cert/214462643660969.pem;
    ssl_certificate_key cert/214462643660969.key;
    ssl_session_timeout 5m;
    ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_prefer_server_ciphers on;
    location / {
    if ( $host != 'yongxinxue.xin' ){
    rewrite ^/(.*)$ https://yongxinxue.xin/$1 permanent;
    }
    proxy_pass http://127.0.0.1:8080;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
    }
0%