关于做面食

2016年9月28日 没有评论

和面粉打交道十几年了吧,也做了快20年的饭,想起以前五岁的时候,妈妈在地里干活,我和我姐做的炒南瓜丝,当时火候没控制好,炒糊了,其实也不是火候的问题吧,那时候吃不起油,不放油干炒确实容易糊。七八岁的时候,暑假会回老家,家里种的还有小麦,收割的时候会有零散的麦穗落在地里面,我妈便让我和我姐提着篮子去捡,捡一个下午确实能捡一篮子,也走了很久很久的路,最后得到几毛钱的奖励,可以买几根辣条或冰袋。再然后就是炒面了,当时也没有方便面可吃,就把面粉放锅里小火炒熟,不放任何东西包括油和盐,炒熟后可以放很长时间,饿了就用开水冲,放点白砂糖,特别香,估计现在难以下咽吧。说到糖,想起馒头的一种吃法,馒头除了可以夹方便面调料外还可以夹白砂糖,夹白砂糖口感确实好。上了初中,方便面就吃得起了,有一天我同桌发明了一种特殊的吃法,让我馋了好久,他用方便面蘸酱包吃,感觉还是蛮有味道的,而且还可以把粉包省出来以后夹馒头吃。有点扯远了,说说本文的正事吧,关于做面食。

做面食无外乎五种吃法,煮、蒸、烤、煎、炸,我不太喜欢把面食做的太油腻,前三种做的多,第一种做的比较出神入化,开个面馆绰绰有余。

煮。要使用煮这种做法,那面粉要做成什么呢?首先想到的是面片、宽面条、细面条、烩面、水疙瘩、小疙瘩以及由面条演化出来的捞面条、炸酱面等等,这些面食的口感大不相同,形状也肯定不一样,影响面食口感的因素主要是温度、醒面、揉面、面的形状、面的水分、面的盐分。面可以加盐也可以不加,在冬天基本可以不用加,加了面的柔性就没了而且不容易做好,因为温度低,面上筋也比较慢,如果急着吃可以把面盆放在温水锅上面,但是口感不好说了。盐这东西,我发现对于面食来说可有可无,面食的口感最关键的因素是揉面、醒面和水分。醒面有两种方法,第一种用湿布盖在面团的上面,湿布只能湿不能带过多的水,另一种就是拿个碗扣住,防止面里面的水分流失,第一种适合做水疙瘩,第二种应用就比较广泛了。醒一会要揉一次,揉要有力气,软绵绵的捏几下那可不行。揉了接着醒,醒一会接着揉,看你的时间和耐心了。不管什么面,揉的越多越好吃。水分,好多人都掌握不了,可以这样搞,把面粉放在盆里面,水龙头流下来水滴,拿筷子不停的搅拌,成絮状即可。

手烫伤 待续

 

 

 

 

分类: 随笔 标签:

研三了

2016年8月31日 没有评论

进入研三每天像打了鸡血一样,忙不完的事。每个月都要外出上万公里,不是在写代码、写文档就是在路上,感觉一件件事压在心头,让我每天都需要计划一周后的事。八月初去了趟南昌,将近40℃的天气,找老道、老王喝二锅头,睡了一天一夜才醒。第二天回北京,感觉整个人都不行了。八月底去了趟徐州,去的前一天喝酒喝到三点半,睡了五个小时就起来了。去徐州那晚上也是疯狂喝到两点,五点多起床。感觉就要猝死了,只要有睡觉的机会就想睡觉。和兄弟在一起的时间总是太短暂,总是不想就拿睡觉去浪费了,当喝多了,想说啥说啥,感谢这些朋友,感谢这些酒友。

该写论文了,花了一周,累死累活写了三万字,勉强交了初稿,然后就要准备笔试、面试,还有公司的事、项目的事、远程办公的事,期间又约了几个天使投资,被洗脑了一番,生意的事真是看的不太懂。如果一个期间只有一个目标,一个压力就好了,当你想着校招、论文、工作,还有北京、合肥两地的距离时,你总要盘算着怎样弄好些。每个人总要处理各种压力,权衡时间的分配与管理,当承受该承受的,做该做的,而不是马马虎虎,总有很好的机会给你。

分类: 随笔 标签:

谈谈抓取与反抓取

2016年8月24日 没有评论

抓取是采集竞品或其它源网站数据,反抓取就是防止别人的抓取行为。目前来说,没有一家公司在反抓取方面做的比较好。举个例子,搜狗运维部门用机器学习搞反抓取策略,在业界也挺得意的,被我花了一周攻克,只用了四十个IP,一天请求上百万,两个多月了,照样好好的用着。

业界反抓取无非以下几种策略:

  1. 按照请求频率封禁IP(现在只有比较low的公司会用这种,这种方法的负面伤害更大)
  2. 按照 IP和请求头部(agent 等信息)封禁
  3. 通过执行Javascript程序注入动态cookie
  4. 通过机器学习策略分析用户行为
  5. 探测到用户有抓取行为,丢一些假数据给用户,比如某地图商

主流是第三种和第四种,第三种的门槛主要是是需要渲染JS才能得到正确的cookie,而普通抓取程序不具备这个功能,并且渲染JS速度太慢,在大规模抓取中不适用。但是第三种我有一套解决方案,是cookie分发机制,出于一些考虑,这套技术不做分享。(在搜狗公共号抓取中,使用cookie分发机制,四十IP可以做到10个/s 请求速度而不遭遇封禁)

第四种那就要好好伪装自己的请求了,比如请求的refer、user-agent、请求的文件类型等,需要自己去做随机请求,难度不大。

抓取解析,那就太简单了,分析DOM结构、使用正则等等,看你具体使用场景吧。

 

分类: WEB开发 标签:

谈谈股票交易

2016年8月22日 没有评论

去年七月中旬入市,一年了,见过无数次千股跌停和千股涨停,操作过的股票也上百只,最多持仓十万人民币,也算是半个老鸟了,随便聊聊。

炒股最重要的是学会控制仓位吧,涨的时候不要急着满仓,跌的时候不要慌着抄底,也不要盲目割肉,年初那熔断,割的我肉疼,亏了三十个点跑了。

其次,要相信技术相信判断,控制贪婪和恐惧吧。我碰见很多次涨停,却从未在涨停价出手过,一般跌下来技术指标破位才知道卖,理想总是很丰满。急跌的时候又控制不住恐惧,跌停板割肉收盘飘红也是我干过的事,急跌的时候,大家都在跌,何必恐惧,跌下来的早晚会涨回来。

我比较喜欢看的是30分钟和15分钟分时线,一般卖点会从这两种线判断。买点更喜欢看一个股的趋势,在一个下跌趋势的股中接飞刀确实不太理智。

炒股讲价值投资确实扯蛋,在这种投机氛围浓重的市场,价值投资可能只是买了茅台之类的股票碰巧赚了钱的人的装逼专用吧。在A股,做长线肯定是极少有回报的,做波段才是利润的来源。对于大多数人来说,能赚到钱不在于你选了多牛逼的股,而在于你找准了买入点,在合适的位置卖掉罢了。买入要三思,卖出只要有利润永远是对的。

不讲价值投资也至少讲下基本面,一个差的基本面,带来的不确定更多,靠差业绩的股票赚钱无异于去赌,风险很大。有时候一个股票一天涨一个点,涨个三四天跌一个点,很多人就会忍受不了,他们更多的是期望涨停、大涨,然而买到这种股票的机会太少,更多的是手握那些不停在区间震荡的股票。看好就拿着,总有一天会轮到手上的股票去涨,不看好就不要买。

如果玩短线,不要选弱势股,也不要自以为挖掘出什么消息了可以提前布局,你知道消息,别人比你知道消息,也有几十万人知道消息,不要自以为聪明,套的大多是自以为是的人。我比较喜欢玩短线,一般持股三天到四天,超过四天那就是我套牢了。套牢盘不要轻易去碰,研究下散户多少,套牢盘的消化需要一些时候。

买之前最好研究下概念,看下财报,看下股东情况,不要觉得会涨就买,当理性战胜感性,当克服自己的恐惧与贪念,总有一天会获得持续稳定的收益。

分类: 随笔 标签:

一年祭

2016年8月21日 没有评论

转眼间,一年过去了,过去一年干了啥呢,好像也没干啥,无非学了一些乱七八糟的技术,做了一堆乱七八糟的东西罢了。

基本算是脱离技术一年多了吧,在此期间也没看过算法,也没看过数据结构,也很少去看新技术、新知识,一年了,啥都忘了,也不知道自己是不是做技术出身的了。

跑过很多地方、整天很忙,做过一个又一个系统,也不知道自己在干啥,没有投资、没有资本,或许现在被别人嘲笑吧,一年了,自己又得到了什么呢。

把希望寄托在别人身上说明自己太弱,很多事都是靠自己争取的,为什么要在别人身上浪费生命呢,一年了或许该想通了。钱这东西在急缺的时候真是好,但可以买走一个人的梦想吗。

 

分类: 随笔 标签:

机器学习中概率论知识小结

2016年7月10日 没有评论

一、引言

 

这里只对本人觉得经常用到的概率论知识点做一次小结,主要是基本概念,因为机器学习中涉及概率论的地方,往往知道基本概念就不难理解,后面会不定期更新。

二、古典概率论中的几个重要的公式

 

  • P(A¯)=1P(A)P(A¯)=1−P(A)
  • P(AB)=P(A)P(AB)P(A−B)=P(A)−P(AB)
  • P(A+B)=P(A)+P(B)P(AB)P(A+B)=P(A)+P(B)−P(AB)
  • P(A+B+C)=P(A)+P(B)+P(C)P(AB)P(AC)P(BC)+P(ABC)P(A+B+C)=P(A)+P(B)+P(C)−P(AB)−P(AC)−P(BC)+P(ABC)
  • 对于 nn 个事件 A1,A2,A3,,AnA1,A2,A3,…,An,两两互斥,则 P(ni=1Ai)=ni=1P(Ai)P(∪i=1nAi)=∑i=1nP(Ai)

二、贝叶斯(Bayes)公式

 

通常把事件 A 的概率 P(A)叫做实验前的假设概率,即先验概率(prior probability),如果有另一个事件 B 与事件 A 有某种关系,即事件 A 和 B 不是互相独立的,那么当事件 B 确实发生之后,则应当重新估计事件 A 的概率,即 P(A | B), 这叫做条件概率或者试验后的假设概率,即后验概率(posterior probability).

公式一:

再引入全概率公式:设事件A当前仅当互不相容的事件(即任意两个事件不可能同时发生的)(i = 1, 2 , … n) 中的任意一个事件发生时才可能发生,已知事件  的概率  及事件 A 在  已发生的条件下的条件概率,则事件 A 发生的概率为:

这就是全概率公式.

根据概率乘法定理:

我们可以得到:

于是:

再根据上面介绍的全概率公式,则可得到传说中的贝叶斯公式:

这些公式定理几乎贯穿整个机器学习,很基本,也很重要!

三、常用的离散随见变量分布

  1. “0-1”分布”: 设随机变量 X 只能取得两个数值:0与1,而概率函数是: 通常把这种分布叫做“0-1”分布或者两点分布,是分布参数.
  2. 二项分布(binomial distribution): 设随机变量 X 可能的的值是0, 1, 2, …, n, 而概率函数是:

其中,这种分布叫做二项分布,含有两个参数  和 ,通常把这种分布记作,如果随见变量 X 服从二项分布,记作

3.  泊松(Possion)分布: 设随机变量 X 的可能值是一切非负整数,而概率函数是:

其中λ > 0 为常数,这种分布叫做泊松分布。泊松分布就含有一个参数λ ,记作P(λ), 如果随机变量 X 服从泊松分布,则记作X~P(λ)

四、随机变量的分布函数

 

x 是任何实数,考虑随机变量 X 取得的值不大于  x 的概率,即事件 X ≤   x  的概率,记作 F(x) = P(X ≤ x), 这个函数叫做随机变量 X 的概率分布函数或者分布函数,注意区别于上面讲到的概率函数.

如果已知随机变量 X 的分布函数 F(X), 则随见变量 X 落在半开区间 (x1, x2] 内的概率:P(x1 < X ≤ x2) = F(x2) –F(x1)

五、连续随机变量的概率密度

连续随机变量的概率密度就是分布函数的导函数

六、随机变量的数学期望

 

如果随机变量 X 只能取得有限个值:

而取得有限个值得概率分别是:

 

则数学期望:

 

 

如果连续随机变量 X 的概率密度为,则连续随机变量的数学期望:

一个常数的的数学期望等于这个常数本身。

定理:两个独立随机变量的乘积的数学期望等于它们数学期望的乘积。证明如下:

对于离散随机变量 X 与 Y 独立:

对于连续随机变量 X 与 Y 独立:

七、方差与标准差

 

随机变量 X 的方差记作 D(X),定义为:

下面证明一个很有用的公式(会用到性质:一个常数的的数学期望等于这个常数本身):

简而言之:随机变量的方差等于变量平方的期望减去期望的平方.

标准差就是方差的算术平方根。

常数的方差为0.

 

八、协方差与相关系数

 

随机变量 X 与 随机变量 Y 的协方差记作:

进一步推导可得:

因为两个独立随机变量乘积的期望等于两个随机变量各自期望的乘积,于是当两个随机变量独立使,很容易得到它们的协方差为0.

两个随机变量 X 与 Y 的 相关系数为:

两个随机变量的相关系数的绝对值不大于1.

当且仅当随机变量 Y 与 X 之间存在线性关系:

时,相关系数的绝对值等于1,并且

九、正态分布

 

正态分布又叫高斯分布,设连续随机变量 X 的概率密度

其中 μ 及 σ>0 都是常数,这种分布就是正态分布.

正态分布含有两个参数 μ 及 σ>0,其中μ等于正态分布的数学期望,而 σ 等于正态分布的标准差,通常把这种分布记作,随机变量 X 服从正态分布,则记为:

定理 设随机变量 X 服从正态分布,则 X 的线性函数 Y= a + bX(b≠0)也服从正态分布,且有

分类: 机器学习 标签:

IOS 设备抓包

2016年7月1日 没有评论

因为要抓IOS 4G流量包,故记录下过程。

IOS 设备USB 连接Mac
打开xcode windows->devices 查看 设备号

然后输入命令

 

就出现虚拟的网桥rvi0 ,可以用wireshark 监听、

 

分类: 零碎 标签:

awk使用

2016年6月21日 没有评论

awk 处理数据挺方便的,整理下使用方法。

先看下最简单的用法

下面是数据,文件名pic.csv

10371029    130657404  33250828600
10375462   0  32754488348
10401830   130670653  33301943326
10490532   130818323  33390650001,33390638503
10492736   130808000  33392915994,33392923278,33392951671,33392965894
10501933   130847315  33426734671,33426784141,33426741368
10520323   130871605  33474622551
10561441   130900744  33569740772
10563686   130931058  33572560455,33572597666,33572625609
10594334   130933942  33595945445,33595930712
10609164   130968431  33625612546
10623734   130960850  33655945376
10625513   130985226  33659411835,33659434639
10662700   131036062  33748007817
10688362   131050019  33802663455
10744503   131143877  33909572401,33909557630
10749313   131138769  33912184752
10777611   131181015  33975768553
10790647   131192937  34013919173,34013904105,34013909379
10790833   131198786  34014605153,34014654005,34014895558,34014920756
10799709   131213531  34039005481
10805941   131221289  34048620033,34048637653
10806145   131228025  34049593438,34049617769,34049618566,34049596717
10837378   131259345  34138112374,34138156606
10847268   131293940  34163393641,34163387864

只看前两列

awk '{print $1,$2}' pic.csv

数据过滤,只看第一列数字为10847268

awk ' $1==10847268' pic.csv

内建变量
说到了内建变量,我们可以来看看awk的一些内建变量:

$0 当前记录(这个变量中存放着整个行的内容)
$1~$n 当前记录的第n个字段,字段间由FS分隔
FS 输入字段分隔符 默认是空格或Tab
NF 当前记录中的字段个数,就是有多少列
NR 已经读出的记录数,就是行号,从1开始,如果有多个文件话,这个值也是不断累加中。
FNR 当前记录数,与NR不同的是,这个值会是各个文件自己的行号
RS 输入的记录分隔符, 默认为换行符
OFS 输出字段分隔符, 默认也是空格
ORS 输出的记录分隔符,默认为换行符
FILENAME 当前输入文件的名字

awk  -F: '{print $1,$3,$6}' OFS="\t" /etc/passwd
root    0       /root
bin     1       /bin
daemon  2       /sbin
adm     3       /var/adm
lp      4       /var/spool/lpd
sync    5       /sbin

如果把文件第一列用逗号分隔,可以用

awk 'ORS="," {print $1}' pic.csv
分类: UNIX 标签:

密码保护:翻墙说明

2016年5月9日 要查看留言请输入您的密码。

这是一篇受密码保护的文章,您需要提供访问密码:

分类: 零碎 标签:

HTTP 协议中的 Transfer-Encoding

2016年4月12日 没有评论

Transfer-Encoding,是一个 HTTP 头部字段,字面意思是「传输编码」。实际上,HTTP 协议中还有另外一个头部与编码有关:Content-Encoding(内容编码)。Content-Encoding 通常用于对实体内容进行压缩编码,目的是优化传输,例如用 gzip 压缩文本文件,能大幅减小体积。内容编码通常是选择性的,例如 jpg / png 这类文件一般不开启,因为图片格式已经是高度压缩过的,再压一遍没什么效果不说还浪费 CPU。

而 Transfer-Encoding 则是用来改变报文格式,它不但不会减少实体内容传输大小,甚至还会使传输变大,那它的作用是什么呢?本文接下来主要就是讲这个。我们先记住一点,Content-Encoding 和 Transfer-Encoding 二者是相辅相成的,对于一个 HTTP 报文,很可能同时进行了内容编码和传输编码。

Persistent Connection

暂时把 Transfer-Encoding 放一边,我们来看 HTTP 协议中另外一个重要概念:Persistent Connection(持久连接,通俗说法长连接)。我们知道 HTTP 运行在 TCP 连接之上,自然也有着跟 TCP 一样的三次握手、慢启动等特性,为了尽可能的提高 HTTP 性能,使用持久连接就显得尤为重要了。为此,HTTP 协议引入了相应的机制。

HTTP/1.0 的持久连接机制是后来才引入的,通过 Connection: keep-alive 这个头部来实现,服务端和客户端都可以使用它告诉对方在发送完数据之后不需要断开 TCP 连接,以备后用。HTTP/1.1 则规定所有连接都必须是持久的,除非显式地在头部加上 Connection: close。所以实际上,HTTP/1.1 中 Connection 这个头部字段已经没有 keep-alive 这个取值了,但由于历史原因,很多 Web Server 和浏览器,还是保留着给 HTTP/1.1 长连接发送 Connection: keep-alive 的习惯。

浏览器重用已经打开的空闲持久连接,可以避开缓慢的三次握手,还可以避免遇上 TCP 慢启动的拥塞适应阶段,听起来十分美妙。为了深入研究持久连接的特性,我决定用 Node 写一个最简单的 Web Server 用于测试,Node 提供了http 模块用于快速创建 HTTP Web Server,但我需要更多的控制,所以用 net 模块创建了一个 TCP Server:


require('net').createServer(function(sock) {
    sock.on('data', function(data) {
        sock.write('HTTP/1.1 200 OK\r\n');
        sock.write('\r\n');
        sock.write('hello world!');
        sock.destroy();
    });
}).listen(9090, '127.0.0.1');

启动服务后,在浏览器里访问 127.0.0.1:9090,正确输出了指定内容,一切正常。去掉 sock.destroy() 这一行,让它变成持久连接,重启服务后再访问一下。这次的结果就有点奇怪了:迟迟看不到输出,通过 Network 查看请求状态,一直是 pending。

这是因为,对于非持久连接,浏览器可以通过连接是否关闭来界定请求或响应实体的边界;而对于持久连接,这种方法显然不奏效。上例中,尽管我已经发送完所有数据,但浏览器并不知道这一点,它无法得知这个打开的连接上是否还会有新数据进来,只能傻傻地等了。

Content-Length

要解决上面这个问题,最容易想到的办法就是计算实体长度,并通过头部告诉对方。这就要用到 Content-Length 了,改造一下上面的例子:


require('net').createServer(function(sock) {
    sock.on('data', function(data) {
        sock.write('HTTP/1.1 200 OK\r\n');
        sock.write('Content-Length: 12\r\n');
        sock.write('\r\n');
        sock.write('hello world!');
    });
}).listen(9090, '127.0.0.1');

可以看到,这次发送完数据并没有关闭 TCP 连接,但浏览器能正常输出内容并结束请求,因为浏览器可以通过Content-Length 的长度信息,判断出响应实体已结束。那如果 Content-Length 和实体实际长度不一致会怎样?有兴趣的同学可以自己试试,通常如果 Content-Length 比实际长度短,会造成内容被截断;如果比实体内容长,会造成 pending。

由于 Content-Length 字段必须真实反映实体长度,但实际应用中,有些时候实体长度并没那么好获得,例如实体来自于网络文件,或者由动态语言生成。这时候要想准确获取长度,只能开一个足够大的 buffer,等内容全部生成好再计算。但这样做一方面需要更大的内存开销,另一方面也会让客户端等更久。

我们在做 WEB 性能优化时,有一个重要的指标叫 TTFB(Time To First Byte),它代表的是从客户端发出请求到收到响应的第一个字节所花费的时间。大部分浏览器自带的 Network 面板都可以看到这个指标,越短的 TTFB 意味着用户可以越早看到页面内容,体验越好。可想而知,服务端为了计算响应实体长度而缓存所有内容,跟更短的 TTFB 理念背道而驰。但在 HTTP 报文中,实体一定要在头部之后,顺序不能颠倒,为此我们需要一个新的机制:不依赖头部的长度信息,也能知道实体的边界。

Transfer-Encoding: chunked

本文主角终于再次出现了,Transfer-Encoding 正是用来解决上面这个问题的。历史上 Transfer-Encoding 可以有多种取值,为此还引入了一个名为 TE 的头部用来协商采用何种传输编码。但是最新的 HTTP 规范里,只定义了一种传输编码:分块编码(chunked)。

分块编码相当简单,在头部加入 Transfer-Encoding: chunked 之后,就代表这个报文采用了分块编码。这时,报文中的实体需要改为用一系列分块来传输。每个分块包含十六进制的长度值和数据,长度值独占一行,长度不包括它结尾的 CRLF(\r\n),也不包括分块数据结尾的 CRLF。最后一个分块长度值必须为 0,对应的分块数据没有内容,表示实体结束。按照这个格式改造下之前的代码:


require('net').createServer(function(sock) {
    sock.on('data', function(data) {
        sock.write('HTTP/1.1 200 OK\r\n');
        sock.write('Transfer-Encoding: chunked\r\n');
        sock.write('\r\n');

        sock.write('b\r\n');
        sock.write('01234567890\r\n');

        sock.write('5\r\n');
        sock.write('12345\r\n');

        sock.write('0\r\n');
        sock.write('\r\n');
    });
}).listen(9090, '127.0.0.1');

上面这个例子中,我在响应头中表明接下来的实体会采用分块编码,然后输出了 11 字节的分块,接着又输出了 5 字节的分块,最后用一个 0 长度的分块表明数据已经传完了。用浏览器访问这个服务,可以得到正确结果。可以看到,通过这种简单的分块策略,很好的解决了前面提出的问题。

前面说过 Content-Encoding 和 Transfer-Encoding 二者经常会结合来用,其实就是针对 Transfer-Encoding 的分块再进行 Content-Encoding。下面是我用 telnet 请求测试页面得到的响应,就对分块内容进行了 gzip 编码:

telnet www.lvxinwei.com 80

GET /index.php HTTP/1.1
Host: www.lvxinwei.com
Accept-Encoding: gzip

HTTP/1.1 200 OK
Server: nginx
Date: Sun, 03 May 2015 17:25:23 GMT
Content-Type: text/html
Transfer-Encoding: chunked
Connection: keep-alive
Content-Encoding: gzip

用 HTTP 抓包神器 Fiddler 也可以看到类似结果,有兴趣的同学可以自己试一下。

分类: WEB开发 标签: