<?xml version="1.0" encoding="UTF-8"?> <rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" ><channel><title>isnowfy</title> <atom:link href="http://www.isnowfy.com/feed/" rel="self" type="application/rss+xml" /><link>http://www.isnowfy.com</link> <description>isnowfy的随心记</description> <lastBuildDate>Mon, 30 Apr 2012 08:23:25 +0000</lastBuildDate> <language>en</language> <sy:updatePeriod>hourly</sy:updatePeriod> <sy:updateFrequency>1</sy:updateFrequency> <generator>http://wordpress.org/?v=3.3.2</generator> <xhtml:meta xmlns:xhtml="http://www.w3.org/1999/xhtml" name="robots" content="noindex" /> <item><title>数论的应用-RSA公钥算法</title><link>http://www.isnowfy.com/application-tonumber-theory-and-introduction-to-rsa/</link> <comments>http://www.isnowfy.com/application-tonumber-theory-and-introduction-to-rsa/#comments</comments> <pubDate>Sun, 15 Apr 2012 15:20:45 +0000</pubDate> <dc:creator>isnowfy</dc:creator> <category><![CDATA[数学]]></category> <category><![CDATA[math]]></category> <category><![CDATA[密码学]]></category> <category><![CDATA[数论]]></category><guid isPermaLink="false">http://www.isnowfy.com/?p=439</guid> <description><![CDATA[要说起RSA算法的话就不得不提欧拉这个伟大的数学家，他在数学的很多方面都有很多研究，而RSA也正是基于他在数论上的欧拉公式才建立起来的。欧拉公式稍后再说，先简单说一下公钥密钥的非对称算法的概念，平常我们用的加密算法往往都是对称的，也就是说加密密钥和解密密钥是一样的，比如凯撒密码，你把每个字母后移3位，a变成d，b变成e，这里3就是加密密钥，然后解密的时候前移3位，这时候3就是解密密钥，非对称加密顾名思义就是加密密钥和解密密钥是不同的，恩，数学就是能干很多神奇的事情啊。 数论在很长的一段时间里被认为是没用的，纯数学的，优美的理论，一直到1976年。当时在美国斯坦福大学的迪菲（Diffie）和赫尔曼(Hellman)两人提出了公开密钥密码的新思想（论文"New Direction in Cryptography"），再后来，1977年由罗纳德·李维斯特（Ron Rivest）、阿迪·萨莫尔（Adi Shamir）和伦纳德·阿德曼（Leonard Adleman）一起提出了RSA。当时他们三人都在麻省理工学院工作。RSA就是他们三人姓氏开头字母拼在一起组成的。 首先介绍欧拉函数，表示是小于或等于n的正整数中与n互质的数的数目，比如，小于6和6互质的只有1和5。并且如果n的分解式为那么，然后有欧拉定理如果n，m是整数且gcd(n,m)=1，那么： 话说费马小定理就是欧拉定理的特殊性形式，下面开始说明RSA的主要步骤。 首先选出两个素数p，q，令n=p*q 再选出e，满足gcd(e,(p-1)*(q-1))=1 计算出d，满足d*e=1 (mod (p-1)*(q-1)) 丢弃p,q(不要让其他人知道)公布n,e保留d，到这一步就是d作为密钥，e作为公钥 发送密文时,令 发送密文时,令 让我们具体一点，比如A要给B传送数据M=52，B选出p=17,q=11则n=187,选出e=7,算出d=23，A通过查询知n=187,e=7,计算得出C=35发给B，B通过计算得出M=52 好了我们来简单说明一下RSA的正确性吧，因为选取的p和q是素数，所以，因为d*e=1 (mod (p-1)*(q-1))，设，则 那么这种非对称加密算法解决了什么问题呢，首先他解决了密钥在非安全信道传播的问题，简单说你和别人想要加密传输资料，但是加密需要把密钥告诉对方才可以，这时候就可以直接把公钥发给对方，即使公钥被其他人截获，也无法通过公钥推算出密钥，换言之，除了拥有密钥的你之外，别人是不能解密内容的。另外公钥密钥还有一个用途就是数字签名了，一份东西你用私钥加密，别人都可以用公钥解密，因为别人没有私钥，所以加密的只可能是你，这样就是可以防止抵赖等，而且公钥密钥还有一系列很有意思的用途这里就不展开说了。数论，密码学神马的还是很有趣的啊。我猜您可能还会喜欢: None Found]]></description> <content:encoded><![CDATA[<p><a href="http://www.isnowfy.com/wp-content/uploads/2012/04/Euler.jpg"><img src="http://www.isnowfy.com/wp-content/uploads/2012/04/Euler-240x300.jpg" alt="" title="Euler" width="240" height="300" class="alignnone size-medium wp-image-440" /></a><br /> 要说起RSA算法的话就不得不提<a href="http://zh.wikipedia.org/wiki/%E8%90%8A%E6%98%82%E5%93%88%E5%BE%B7%C2%B7%E6%AD%90%E6%8B%89">欧拉</a>这个伟大的数学家，他在数学的很多方面都有很多研究，而RSA也正是基于他在数论上的欧拉公式才建立起来的。欧拉公式稍后再说，先简单说一下公钥密钥的非对称算法的概念，平常我们用的加密算法往往都是对称的，也就是说加密密钥和解密密钥是一样的，比如凯撒密码，你把每个字母后移3位，a变成d，b变成e，这里3就是加密密钥，然后解密的时候前移3位，这时候3就是解密密钥，非对称加密顾名思义就是加密密钥和解密密钥是不同的，恩，数学就是能干很多神奇的事情啊。<br /> <span id="more-439"></span></p><p>数论在很长的一段时间里被认为是没用的，纯数学的，优美的理论，一直到1976年。当时在美国斯坦福大学的迪菲（Diffie）和赫尔曼(Hellman)两人提出了公开密钥密码的新思想（论文"New Direction in Cryptography"），再后来，1977年由罗纳德·李维斯特（Ron Rivest）、阿迪·萨莫尔（Adi Shamir）和伦纳德·阿德曼（Leonard Adleman）一起提出了RSA。当时他们三人都在麻省理工学院工作。RSA就是他们三人姓氏开头字母拼在一起组成的。</p><p>首先介绍欧拉函数，<span class='MathJax_Preview'><img src='http://www.isnowfy.com/wp-content/plugins/latex/cache/tex_a0020daa3fec60004254eda5aa74adff.gif' style='vertical-align: middle; border: none; ' class='tex' alt="\phi(n)" /></span><script type='math/tex'>\phi(n)</script>表示是小于或等于n的正整数中与n互质的数的数目，比如<span class='MathJax_Preview'><img src='http://www.isnowfy.com/wp-content/plugins/latex/cache/tex_7de55b0ebaa495dac2c5f9bfba5c79b4.gif' style='vertical-align: middle; border: none; ' class='tex' alt="\phi(6)=2" /></span><script type='math/tex'>\phi(6)=2</script>，小于6和6互质的只有1和5。并且如果n的分解式为<span class='MathJax_Preview'><img src='http://www.isnowfy.com/wp-content/plugins/latex/cache/tex_f9be52ee075d5692175266adaaeaee7b.gif' style='vertical-align: middle; border: none; ' class='tex' alt="n=p_1^{m_1}*p_2^{m_2}...*p_s^{m_s}" /></span><script type='math/tex'>n=p_1^{m_1}*p_2^{m_2}...*p_s^{m_s}</script>那么<span class='MathJax_Preview'><img src='http://www.isnowfy.com/wp-content/plugins/latex/cache/tex_cac28cd82870e814f6f79f8aa455f3ea.gif' style='vertical-align: middle; border: none; ' class='tex' alt="\phi(n)=p_1^{m_1-1}*(p_1-1)*p_2^{m_2-1}*(p_2-1)...*p_s^{m_s-1}*(p_s-1)" /></span><script type='math/tex'>\phi(n)=p_1^{m_1-1}*(p_1-1)*p_2^{m_2-1}*(p_2-1)...*p_s^{m_s-1}*(p_s-1)</script>，然后有欧拉定理如果n，m是整数且gcd(n,m)=1，那么：</p><blockquote><p> <span class='MathJax_Preview'><img src='http://www.isnowfy.com/wp-content/plugins/latex/cache/tex_39910e89656607d8eac2901a8319a4fb.gif' style='vertical-align: middle; border: none; ' class='tex' alt="m^{\phi(n)}=1\quad (mod\quad n)" /></span><script type='math/tex'>m^{\phi(n)}=1\quad(mod\quad n)</script></p></blockquote><p>话说费马小定理就是欧拉定理的特殊性形式，下面开始说明RSA的主要步骤。</p><ul><li>首先选出两个素数p，q，令n=p*q</li><li>再选出e，满足gcd(e,(p-1)*(q-1))=1</li><li>计算出d，满足d*e=1 (mod (p-1)*(q-1))</li><li>丢弃p,q(不要让其他人知道)公布n,e保留d，到这一步就是d作为密钥，e作为公钥</li><li>发送密文时,令<span class='MathJax_Preview'><img src='http://www.isnowfy.com/wp-content/plugins/latex/cache/tex_0075275955c198716477df834a0958ce.gif' style='vertical-align: middle; border: none; ' class='tex' alt="C=M^e\quad (mod \quad n)" /></span><script type='math/tex'>C=M^e\quad(mod \quad n)</script></li><li>发送密文时,令<span class='MathJax_Preview'><img src='http://www.isnowfy.com/wp-content/plugins/latex/cache/tex_116538462cca79cef2910f33d47980ff.gif' style='vertical-align: middle; border: none; ' class='tex' alt="M=C^d\quad (mod \quad n)" /></span><script type='math/tex'>M=C^d\quad(mod \quad n)</script></li></ul><p>让我们具体一点，比如A要给B传送数据M=52，B选出p=17,q=11则n=187,选出e=7,算出d=23，A通过查询知n=187,e=7,计算<span class='MathJax_Preview'><img src='http://www.isnowfy.com/wp-content/plugins/latex/cache/tex_0075275955c198716477df834a0958ce.gif' style='vertical-align: middle; border: none; ' class='tex' alt="C=M^e\quad (mod \quad n)" /></span><script type='math/tex'>C=M^e\quad(mod \quad n)</script>得出C=35发给B，B通过计算<span class='MathJax_Preview'><img src='http://www.isnowfy.com/wp-content/plugins/latex/cache/tex_116538462cca79cef2910f33d47980ff.gif' style='vertical-align: middle; border: none; ' class='tex' alt="M=C^d\quad (mod \quad n)" /></span><script type='math/tex'>M=C^d\quad(mod \quad n)</script>得出M=52</p><p>好了我们来简单说明一下RSA的正确性吧，因为选取的p和q是素数，所以<span class='MathJax_Preview'><img src='http://www.isnowfy.com/wp-content/plugins/latex/cache/tex_d987143e34e820f4f5b8a5cac2a779a7.gif' style='vertical-align: middle; border: none; ' class='tex' alt="\phi(n)=(p-1)*(q-1)" /></span><script type='math/tex'>\phi(n)=(p-1)*(q-1)</script>，因为d*e=1 (mod (p-1)*(q-1))，设<span class='MathJax_Preview'><img src='http://www.isnowfy.com/wp-content/plugins/latex/cache/tex_c21ce5e470a06a7c123674448ff3ae01.gif' style='vertical-align: middle; border: none; ' class='tex' alt="d*e=k*\phi(n)+1" /></span><script type='math/tex'>d*e=k*\phi(n)+1</script>，则<span class='MathJax_Preview'><img src='http://www.isnowfy.com/wp-content/plugins/latex/cache/tex_928f105b8894b1b030d92a6feaa39b6e.gif' style='vertical-align: middle; border: none; ' class='tex' alt="C^d=(M^e)^d=M^{e*d}=M*(M^{\phi(n)})^k=M\quad (mod \quad n)" /></span><script type='math/tex'>C^d=(M^e)^d=M^{e*d}=M*(M^{\phi(n)})^k=M\quad(mod \quad n)</script></p><p>那么这种非对称加密算法解决了什么问题呢，首先他解决了密钥在非安全信道传播的问题，简单说你和别人想要加密传输资料，但是加密需要把密钥告诉对方才可以，这时候就可以直接把公钥发给对方，即使公钥被其他人截获，也无法通过公钥推算出密钥，换言之，除了拥有密钥的你之外，别人是不能解密内容的。另外公钥密钥还有一个用途就是数字签名了，一份东西你用私钥加密，别人都可以用公钥解密，因为别人没有私钥，所以加密的只可能是你，这样就是可以防止抵赖等，而且公钥密钥还有一系列很有意思的用途这里就不展开说了。数论，密码学神马的还是很有趣的啊。<br /><strong>我猜您可能还会喜欢:</strong><ul class="similar-posts">None Found</ul><p></p> ]]></content:encoded> <wfw:commentRss>http://www.isnowfy.com/application-tonumber-theory-and-introduction-to-rsa/feed/</wfw:commentRss> <slash:comments>1</slash:comments> </item> <item><title>python中文分词</title><link>http://www.isnowfy.com/python-chinese-segmentation/</link> <comments>http://www.isnowfy.com/python-chinese-segmentation/#comments</comments> <pubDate>Sat, 17 Mar 2012 14:15:56 +0000</pubDate> <dc:creator>isnowfy</dc:creator> <category><![CDATA[algorithm]]></category> <category><![CDATA[program]]></category> <category><![CDATA[math]]></category> <category><![CDATA[probability]]></category> <category><![CDATA[python]]></category><guid isPermaLink="false">http://www.isnowfy.com/?p=431</guid> <description><![CDATA[相对于英文而言，中文在计算机处理方面有个必须要面对的问题就是中文分词，英文的单词都是空格间隔的，而中文的词语则不同，所以用程序解决中文分词，在很多自然语言处理方面都是首要进行的步骤。 其中最简单的就是最大匹配的中文分词了，比如“今天天气不错”可以分词为“今天/天气/不错”，但是面对一些有歧义的句子时却显得捉襟见肘，于是“南京市长江大桥”就会被分成“南京市长/江/大桥”而不是“南京市/长江/大桥”，于是更好的是基于统计学原理的分词，也就是说看哪种出现的频率更高。 对于一个中文字符串“a1a2a3...an”如何正确的用词语c1,c2..cm表示就是中文分词的任务，也就是说我们要去找寻P(c1c2..cm)最大的分词，按照马尔科夫链的想法就是说我们就是求P(c1)*P(c1&#124;c2)*P(c1c2&#124;c3)*...P(c1c2...cm-1&#124;cm)最大。按照阿卡姆剃刀的想法我们可以假设一个最可能的实现，于是google黑板报的假设就是每个词只跟前面的词有关，于是变为求P(c1)*P(c1&#124;c2)*P(c2&#124;c3)*...P(cm-1&#124;cm)最大。进一步的其实我们可以假设每个词都是相对独立的，也就是求P(c1)*P(c2)*...P(cm)最大，那么这个怎么求呢，就是用dp的方法。ok，上代码。 # -*- coding: UTF-8 -*- &#160; import collections d=collections.defaultdict&#40;lambda:1&#41; &#160; def init&#40;filename=&#39;SogouLabDic.dic&#39;&#41;: &#160; &#160; f=open&#40;filename,&#39;r&#39;&#41; &#160; &#160; total=0 &#160; &#160; while True: &#160; &#160; &#160; &#160; line=f.readline&#40;&#41; &#160; &#160; &#160; &#160; if not line: break &#160; &#160; &#8230; <a href="http://www.isnowfy.com/python-chinese-segmentation/">继续阅读 <span class="meta-nav">&#8594;</span></a>]]></description> <content:encoded><![CDATA[<p><a href="http://www.isnowfy.com/wp-content/uploads/2012/03/aokamu.jpg"><img src="http://www.isnowfy.com/wp-content/uploads/2012/03/aokamu-300x289.jpg" alt="" title="aokamu" width="300" height="289" class="alignnone size-medium wp-image-432" /></a><br /> 相对于英文而言，中文在计算机处理方面有个必须要面对的问题就是中文分词，英文的单词都是空格间隔的，而中文的词语则不同，所以用程序解决中文分词，在很多自然语言处理方面都是首要进行的步骤。<br /> <span id="more-431"></span></p><p>其中最简单的就是最大匹配的中文分词了，比如“今天天气不错”可以分词为“今天/天气/不错”，但是面对一些有歧义的句子时却显得捉襟见肘，于是“南京市长江大桥”就会被分成“南京市长/江/大桥”而不是“南京市/长江/大桥”，于是更好的是基于统计学原理的分词，也就是说看哪种出现的频率更高。</p><p>对于一个中文字符串“a1a2a3...an”如何正确的用词语c1,c2..cm表示就是中文分词的任务，也就是说我们要去找寻P(c1c2..cm)最大的分词，按照马尔科夫链的想法就是说我们就是求P(c1)*P(c1|c2)*P(c1c2|c3)*...P(c1c2...cm-1|cm)最大。按照阿卡姆剃刀的想法我们可以假设一个最可能的实现，于是<a href="http://www.google.com.hk/ggblog/googlechinablog/2006/04/blog-post_7327.html">google黑板报</a>的假设就是每个词只跟前面的词有关，于是变为求P(c1)*P(c1|c2)*P(c2|c3)*...P(cm-1|cm)最大。进一步的其实我们可以假设每个词都是相对独立的，也就是求P(c1)*P(c2)*...P(cm)最大，那么这个怎么求呢，就是用dp的方法。ok，上代码。</p><div class="geshi no python"><ol><li class="li1"><div class="de1"><span class="co1"># -*- coding: UTF-8 -*-</span></div></li><li class="li1"><div class="de1">&nbsp;</div></li><li class="li1"><div class="de1"><span class="kw1">import</span> <span class="kw3">collections</span></div></li><li class="li1"><div class="de1">d=<span class="kw3">collections</span>.<span class="me1">defaultdict</span><span class="br0">&#40;</span><span class="kw1">lambda</span>:<span class="nu0">1</span><span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">&nbsp;</div></li><li class="li1"><div class="de1"><span class="kw1">def</span> init<span class="br0">&#40;</span>filename=<span class="st0">&#39;SogouLabDic.dic&#39;</span><span class="br0">&#41;</span>:</div></li><li class="li1"><div class="de1">&nbsp; &nbsp; f=<span class="kw2">open</span><span class="br0">&#40;</span>filename,<span class="st0">&#39;r&#39;</span><span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; total=<span class="nu0">0</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; <span class="kw1">while</span> <span class="kw2">True</span>:</div></li><li class="li1"><div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; line=f.<span class="kw3">readline</span><span class="br0">&#40;</span><span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="kw1">not</span> line: <span class="kw1">break</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; word, freq = line.<span class="me1">split</span><span class="br0">&#40;</span><span class="st0">&#39;<span class="es0">\t</span>&#39;</span><span class="br0">&#41;</span><span class="br0">&#91;</span><span class="nu0">0</span>:<span class="nu0">2</span><span class="br0">&#93;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; total+=<span class="kw2">int</span><span class="br0">&#40;</span>freq<span class="br0">&#41;</span><span class="nu0">+1</span><span class="co1">#smooth</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">try</span>:</div></li><li class="li1"><div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; d<span class="br0">&#91;</span>word.<span class="me1">decode</span><span class="br0">&#40;</span><span class="st0">&#39;gbk&#39;</span><span class="br0">&#41;</span><span class="br0">&#93;</span>=<span class="kw2">int</span><span class="br0">&#40;</span>freq<span class="br0">&#41;</span><span class="nu0">+1</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">except</span>:</div></li><li class="li1"><div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; d<span class="br0">&#91;</span>word<span class="br0">&#93;</span>=<span class="kw2">int</span><span class="br0">&#40;</span>freq<span class="br0">&#41;</span><span class="nu0">+1</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; f.<span class="me1">close</span><span class="br0">&#40;</span><span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; d<span class="br0">&#91;</span><span class="st0">&#39;_t_&#39;</span><span class="br0">&#93;</span>=total</div></li><li class="li1"><div class="de1">&nbsp;</div></li><li class="li1"><div class="de1"><span class="kw1">def</span> solve<span class="br0">&#40;</span>s<span class="br0">&#41;</span>:</div></li><li class="li1"><div class="de1">&nbsp; &nbsp; l=<span class="kw2">len</span><span class="br0">&#40;</span>s<span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; p=<span class="br0">&#91;</span><span class="nu0">0</span> <span class="kw1">for</span> i <span class="kw1">in</span> <span class="kw2">range</span><span class="br0">&#40;</span>l<span class="nu0">+1</span><span class="br0">&#41;</span><span class="br0">&#93;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; p<span class="br0">&#91;</span>l<span class="br0">&#93;</span>=<span class="nu0">1</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; div=<span class="br0">&#91;</span><span class="nu0">1</span> <span class="kw1">for</span> i <span class="kw1">in</span> <span class="kw2">range</span><span class="br0">&#40;</span>l<span class="nu0">+1</span><span class="br0">&#41;</span><span class="br0">&#93;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; t=<span class="br0">&#91;</span><span class="nu0">1</span> <span class="kw1">for</span> i <span class="kw1">in</span> <span class="kw2">range</span><span class="br0">&#40;</span>l<span class="br0">&#41;</span><span class="br0">&#93;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; <span class="kw1">for</span> i <span class="kw1">in</span> <span class="kw2">range</span><span class="br0">&#40;</span>l<span class="nu0">-1</span>,<span class="nu0">-1</span>,<span class="nu0">-1</span><span class="br0">&#41;</span>:</div></li><li class="li1"><div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">for</span> k <span class="kw1">in</span> <span class="kw2">range</span><span class="br0">&#40;</span><span class="nu0">1</span>,l-i<span class="nu0">+1</span><span class="br0">&#41;</span>:</div></li><li class="li1"><div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; tmp=d<span class="br0">&#91;</span>s<span class="br0">&#91;</span>i:i+k<span class="br0">&#93;</span><span class="br0">&#93;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> k<span class="sy0">&gt;</span><span class="nu0">1</span> <span class="kw1">and</span> tmp==<span class="nu0">1</span>:</div></li><li class="li1"><div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">continue</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>d<span class="br0">&#91;</span>s<span class="br0">&#91;</span>i:i+k<span class="br0">&#93;</span><span class="br0">&#93;</span><span class="sy0">*</span>p<span class="br0">&#91;</span>i+k<span class="br0">&#93;</span><span class="sy0">*</span>div<span class="br0">&#91;</span>i<span class="br0">&#93;</span> <span class="sy0">&gt;</span> p<span class="br0">&#91;</span>i<span class="br0">&#93;</span><span class="sy0">*</span>d<span class="br0">&#91;</span><span class="st0">&#39;_t_&#39;</span><span class="br0">&#93;</span><span class="sy0">*</span>div<span class="br0">&#91;</span>i+k<span class="br0">&#93;</span><span class="br0">&#41;</span>:</div></li><li class="li1"><div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; p<span class="br0">&#91;</span>i<span class="br0">&#93;</span>=d<span class="br0">&#91;</span>s<span class="br0">&#91;</span>i:i+k<span class="br0">&#93;</span><span class="br0">&#93;</span><span class="sy0">*</span>p<span class="br0">&#91;</span>i+k<span class="br0">&#93;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; div<span class="br0">&#91;</span>i<span class="br0">&#93;</span>=d<span class="br0">&#91;</span><span class="st0">&#39;_t_&#39;</span><span class="br0">&#93;</span><span class="sy0">*</span>div<span class="br0">&#91;</span>i+k<span class="br0">&#93;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; t<span class="br0">&#91;</span>i<span class="br0">&#93;</span>=k</div></li><li class="li1"><div class="de1">&nbsp; &nbsp; i=<span class="nu0">0</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; <span class="kw1">while</span> i<span class="sy0">&lt;</span>l:</div></li><li class="li1"><div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">print</span> s<span class="br0">&#91;</span>i:i+t<span class="br0">&#91;</span>i<span class="br0">&#93;</span><span class="br0">&#93;</span>,</div></li><li class="li1"><div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; i=i+t<span class="br0">&#91;</span>i<span class="br0">&#93;</span></div></li><li class="li1"><div class="de1">&nbsp;</div></li><li class="li1"><div class="de1">&nbsp;</div></li><li class="li1"><div class="de1"><span class="kw1">if</span> __name__ == <span class="st0">&#39;__main__&#39;</span>:</div></li><li class="li1"><div class="de1">&nbsp; &nbsp; init<span class="br0">&#40;</span><span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; s=<span class="st0">&quot;其中最简单的就是最大匹配的中文分词&quot;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; s=s.<span class="me1">decode</span><span class="br0">&#40;</span><span class="st0">&#39;utf8&#39;</span><span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; solve<span class="br0">&#40;</span>s<span class="br0">&#41;</span></div></li></ol></div><p>词库用到了<a href="http://www.sogou.com/labs/dl/w.html">搜狗实验室</a>提供的不错的词库，程序还是很清晰的，值得注意的就是乘法不要直接去乘因为频率都是小于1的，乘的太多可能就会变为0就要影响整个算法了，所以我是分子分母分开存放的，话说直接用了python的原生大整数，连gcd都懒得写了啊。。。</p><p>ps:注意到如果词在字典里没有出现会导致概率乘积是0的情况，所以需要进行smooth</p><p>参考资料：<br /> <a href="http://scturtle.is-programmer.com/posts/26648.html">http://scturtle.is-programmer.com/posts/26648.html</a><br /> <a href="http://www.matrix67.com/blog/archives/4212">http://www.matrix67.com/blog/archives/4212</a><br /> <a href="http://www.google.com.hk/ggblog/googlechinablog/2006/04/blog-post_7327.html">http://www.google.com.hk/ggblog/googlechinablog/2006/04/blog-post_7327.html</a><br /> <a href="http://mindhacks.cn/2008/09/21/the-magical-bayesian-method/">http://mindhacks.cn/2008/09/21/the-magical-bayesian-method/</a><br /><strong>我猜您可能还会喜欢:</strong><ul class="similar-posts"><li><a href="http://www.isnowfy.com/similar-image-search/" rel="bookmark" title="2011 年 09 月 04 日">关于相似图片搜索</a></li><li><a href="http://www.isnowfy.com/machine-learning-subtitle-script/" rel="bookmark" title="2011 年 10 月 11 日">machine learning公开课的字幕获取脚本</a></li><li><a href="http://www.isnowfy.com/download-doubanfm-songs/" rel="bookmark" title="2011 年 11 月 13 日">自动下载豆瓣FM的加心歌曲</a></li><li><a href="http://www.isnowfy.com/introduction-to-gevent/" rel="bookmark" title="2011 年 12 月 21 日">gevent初步</a></li><li><a href="http://www.isnowfy.com/libcurl-fetch-webpage/" rel="bookmark" title="2011 年 08 月 27 日">c中使用libcurl抓取网页</a></li><li><a href="http://www.isnowfy.com/wordpress-optimization/" rel="bookmark" title="2011 年 08 月 16 日">又折腾了一把wordpress</a></li><li><a href="http://www.isnowfy.com/lucene-build-search/" rel="bookmark" title="2011 年 07 月 10 日">lucene3.2 简单的建立索引和查询</a></li></ul><p></p> ]]></content:encoded> <wfw:commentRss>http://www.isnowfy.com/python-chinese-segmentation/feed/</wfw:commentRss> <slash:comments>2</slash:comments> </item> <item><title>P和NP那些事</title><link>http://www.isnowfy.com/introduction-to-p-and-np/</link> <comments>http://www.isnowfy.com/introduction-to-p-and-np/#comments</comments> <pubDate>Tue, 21 Feb 2012 16:54:02 +0000</pubDate> <dc:creator>isnowfy</dc:creator> <category><![CDATA[algorithm]]></category> <category><![CDATA[math]]></category> <category><![CDATA[数学]]></category><guid isPermaLink="false">http://www.isnowfy.com/?p=421</guid> <description><![CDATA[在计算机科学里，有时间复杂度的概念，然后就有P,NP,NPC,NP-hard的概念，平常大家说的这个题是np的，只能搜了，其实是理解错了np的概念，首先要明确np并不是“不是p”的意思，p大家都清楚是指有多项式时间的算法，而np看全称是“nondeterministic polynomial time”，是说非确定多项式时间，进一步说，正如图片上说的p是属于np的，所有p问题都是np问题。 ok，下面仔细说一下，按照官方的解释呢 p是指在多项式时间能由确定型图灵机解决的问题 np是指在多项式时间能由非确定型图灵机解决的问题 确定型图灵机可以理解为就是按照某种固定的算法，一步步求出解的程序，而非确定型图灵机其实是概念上的，他的理论价值更大一些，他是指某个程序rp非常好，能猜出答案。怎么叫猜出答案呢，举个例子比如说哈密顿问题（是说经过图上的所有点一次且仅一次的路径），程序猜出了个路径ACDEFB啥的，然后程序要自己看看这个路径是不是哈密顿路，验证了一下，我勒个去，还真是，于是答案就出现了。所以这里的猜是指给出一个正确的答案，就是不仅猜出了个答案，还要自己验证一下是不是正确的，所以在有些地方解释np就是说能在多项式时间验证的问题就是np的，也不能说不对吧。 我们看到p是属于np的，那么是不是有是np但不是p的问题呢，也就是p是否等于np呢，这是个亘古难题，但是大家普遍倾向于不等于。 这里有点跳跃啊，我们先要介绍一个规约的概念，规约就是说一个问题A可以在多项式时间转化为问题B，然后问题A有解当前仅当转化后的问题B有解，也就是说只要解决了B那么就可以解决A，注意这个转化是单向的，比如你可以用解二次方程的方法解一次方程，但是反过来却不行。 然后有个叫Cook的人发现所有的np问题都可以规约到一种叫做SAT的问题，也就是说只要SAT能有效的解决，所有问题都能利这种方法经过相应转化而有效解决，后来人们发现所有的问题能规约到的问题不止一种，而是一大类，有很多个，这类问题就被称作NP-complete问题，俗称np完全问题，就是说这类问题是np里最难的，所有的np问题都可以规约到他们。到这里我们注意到npc问题是有两个条件的： （1）他是np问题 （2）所有的np问题都可以规约到他。 如果只满足条件（2）那么被称作NP-hard，俗称np难问题，也就是说NP-hard和np问题的交集就是npc，那么以后要证明某个问题是npc问题只要先证明他是np问题，再证明某个npc问题可以规约到他（注意这个顺序是某npc规约到你要求的问题，很多人都犯顺序的错误）就可以了，如果你证明了某个问题是npc的，那么你就不用费劲心思的去想优雅的多项式算法了。 好了，让我们看看传奇的第一个npc问题SAT到底是什么，SAT全称是satisfiability，他是问对于一个合取范式，是否有一种输入使得他的输出是1，具体点就是类似这样的布尔表达式（x1 or x2 or x3）and(x3 or x4)and(x1 or x5)对于所有的x是否有一种01取值，使得最后的结果是1，据说证明这个是npc非常复杂，大体思想就是说给定输入的图灵机操作都可以表示成这种形式的布尔表达式。而对于acmer比较熟悉的2-SAT问题就是SAT的特例，并且他是有多项式算法的，就是2-SAT是p的，而3-SAT就是npc问题了。 npc问题有很多的，比较有名的有团问题，顶点覆盖集问题，支配集问题，独立集问题，哈密顿路问题，旅行商问题等，同样有很多是NP-hard而不是npc的问题，比如围棋，停机问题等。 前一段时间比较火的就是一位HP的研究员Vinay Deolalikar声称证明了P≠NP，但是后来被证明是错误的╮(￣▽￣")╭ ，不过我感觉这个可能和哥德巴赫猜想一样，按照哥德尔不完备定理来说，在现有理论的体系下，可能无法证明，需要利用到理论体系之外的东西，当然我也只是猜测，至于到底怎么样我们还是静观其变吧。我猜您可能还会喜欢: 利用comet技术实现web聊天]]></description> <content:encoded><![CDATA[<p><a href="http://www.isnowfy.com/wp-content/uploads/2012/02/800px-P_np_np-complete_np-hard.svg_.png"><img src="http://www.isnowfy.com/wp-content/uploads/2012/02/800px-P_np_np-complete_np-hard.svg_-300x187.png" alt="" title="800px-P_np_np-complete_np-hard.svg" width="300" height="187" class="alignnone size-medium wp-image-422" /></a><br /> 在计算机科学里，有时间复杂度的概念，然后就有P,NP,NPC,NP-hard的概念，平常大家说的这个题是np的，只能搜了，其实是理解错了np的概念，首先要明确np并不是“不是p”的意思，p大家都清楚是指有多项式时间的算法，而np看全称是“nondeterministic polynomial time”，是说非确定多项式时间，进一步说，正如图片上说的p是属于np的，所有p问题都是np问题。<br /> <span id="more-421"></span></p><p>ok，下面仔细说一下，按照官方的解释呢</p><blockquote><p> p是指在多项式时间能由确定型图灵机解决的问题</p></blockquote><blockquote><p> np是指在多项式时间能由非确定型图灵机解决的问题</p></blockquote><p>确定型图灵机可以理解为就是按照某种固定的算法，一步步求出解的程序，而非确定型图灵机其实是概念上的，他的理论价值更大一些，他是指某个程序rp非常好，能猜出答案。怎么叫猜出答案呢，举个例子比如说哈密顿问题（是说经过图上的所有点一次且仅一次的路径），程序猜出了个路径ACDEFB啥的，然后程序要自己看看这个路径是不是哈密顿路，验证了一下，我勒个去，还真是，于是答案就出现了。所以这里的猜是指给出一个正确的答案，就是不仅猜出了个答案，还要自己验证一下是不是正确的，所以在有些地方解释np就是说能在多项式时间验证的问题就是np的，也不能说不对吧。</p><p>我们看到p是属于np的，那么是不是有是np但不是p的问题呢，也就是p是否等于np呢，这是个亘古难题，但是大家普遍倾向于不等于。</p><p>这里有点跳跃啊，我们先要介绍一个规约的概念，规约就是说一个问题A可以在多项式时间转化为问题B，然后问题A有解当前仅当转化后的问题B有解，也就是说只要解决了B那么就可以解决A，注意这个转化是单向的，比如你可以用解二次方程的方法解一次方程，但是反过来却不行。</p><p>然后有个叫Cook的人发现所有的np问题都可以规约到一种叫做SAT的问题，也就是说只要SAT能有效的解决，所有问题都能利这种方法经过相应转化而有效解决，后来人们发现所有的问题能规约到的问题不止一种，而是一大类，有很多个，这类问题就被称作NP-complete问题，俗称np完全问题，就是说这类问题是np里最难的，所有的np问题都可以规约到他们。到这里我们注意到npc问题是有两个条件的：</p><blockquote><p> （1）他是np问题</p></blockquote><blockquote><p> （2）所有的np问题都可以规约到他。</p></blockquote><p>如果只满足条件（2）那么被称作NP-hard，俗称np难问题，也就是说NP-hard和np问题的交集就是npc，那么以后要证明某个问题是npc问题只要先证明他是np问题，再证明某个npc问题可以规约到他（注意这个顺序是某npc规约到你要求的问题，很多人都犯顺序的错误）就可以了，如果你证明了某个问题是npc的，那么你就不用费劲心思的去想优雅的多项式算法了。</p><p>好了，让我们看看传奇的第一个npc问题SAT到底是什么，SAT全称是satisfiability，他是问对于一个合取范式，是否有一种输入使得他的输出是1，具体点就是类似这样的布尔表达式（x1 or x2 or x3）and(x3 or x4)and(x1 or x5)对于所有的x是否有一种01取值，使得最后的结果是1，据说证明这个是npc非常复杂，大体思想就是说给定输入的图灵机操作都可以表示成这种形式的布尔表达式。而对于acmer比较熟悉的2-SAT问题就是SAT的特例，并且他是有多项式算法的，就是2-SAT是p的，而3-SAT就是npc问题了。</p><p>npc问题有<a href="http://en.wikipedia.org/wiki/List_of_NP-complete_problems">很多的</a>，比较有名的有团问题，顶点覆盖集问题，支配集问题，独立集问题，哈密顿路问题，旅行商问题等，同样有很多是NP-hard而不是npc的问题，比如围棋，停机问题等。</p><p>前一段时间比较火的就是一位HP的研究员Vinay Deolalikar声称证明了P≠NP，但是后来被证明是错误的╮(￣▽￣")╭ ，不过我感觉这个可能和哥德巴赫猜想一样，按照哥德尔不完备定理来说，在现有理论的体系下，可能无法证明，需要利用到理论体系之外的东西，当然我也只是猜测，至于到底怎么样我们还是静观其变吧。<br /><strong>我猜您可能还会喜欢:</strong><ul class="similar-posts"><li><a href="http://www.isnowfy.com/comet-web-chat/" rel="bookmark" title="2011 年 08 月 05 日">利用comet技术实现web聊天</a></li></ul><p></p> ]]></content:encoded> <wfw:commentRss>http://www.isnowfy.com/introduction-to-p-and-np/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>理解OAuth</title><link>http://www.isnowfy.com/understand-oauth/</link> <comments>http://www.isnowfy.com/understand-oauth/#comments</comments> <pubDate>Sun, 15 Jan 2012 16:47:14 +0000</pubDate> <dc:creator>isnowfy</dc:creator> <category><![CDATA[web]]></category> <category><![CDATA[math]]></category> <category><![CDATA[密码学]]></category><guid isPermaLink="false">http://www.isnowfy.com/?p=386</guid> <description><![CDATA[现在越来越多的网站开放api了，而且大部分都用了OAuth的认证方式，对于没接触过OAuth的人来说一开始理解起来感觉很困惑，觉得这个东西很麻烦，这篇文章就简单的从什么是OAuth，为什么要有OAuth，OAuth的认证流程，以及OAuth为什么要这样设计来谈一下。但是鉴于现在OAuth都已经有2.0了，但是2.0却不兼容1.0，而2.0主要依赖的是https，所以这里还是主要是来讲OAuth1.0的，确切的说是OAuth1.0a的。 什么是OAuth 当你进入OAuth的官网，就能看到那句最醒目的描述 An open protocol to allow secure API authorization in a simple and standard method from desktop and web applications. OAuth是一种开放的并且简单安全的协议，能够让你可以对桌面程序和web程序进行授权。好吧，看上去还是很抽象，那就接着看吧。 为什么要用OAuth 一个非常常见的需求，就是我想获得用户在其他网站上的数据，比如，我做了个相片集中展示的网站，我希望用户可以导入他在flickr，或者facebook，或者人人上的照片。而OAuth就是一种能够安全方便的让我可以去别的网站获得用户的数据。 ok，你可能会想这个事情不简单嘛，我直接把我在其他网站的用户名密码告诉这个网站不就可以了。于是问题来了，这个网站你信的过吗，把用户名密码告诉他干坏事肿么办，如果我哪天不想用这个网站了，也不想让这个网站再获取数据了我是不是要改密码呢。 他真的没有存储我的密码吗，CSDN都明文了，我还能相信爱情吗╮(￣▽￣")╭ 于是OAuth就是为了解决这些授权问题应运而生的。 OAuth最终会为每一个用户的每一个授权的应用都生成一对access token和access token secret，可以把它当做访问用户数据的特殊的用户名和密码。由于对于每一个用户而言，每一个授权应用的token和secret都是不同的，所以用户可以很方便的收回某个应用的授权而不影响其他的应用，而且不用去改密码，而且如果用户更改了密码，那些授权的token和secret依旧不受影响，这就是OAuth的解决方案了。 那么应用如何去获得token和secret就是下面要讲的了。 OAuth的认证流程 首先奉上一张官网上的流程图 首先要明白整个需要三个角色，user，consumer，provider，首先consumer就是我要做的网站或者是说给用户提供服务的应用，user很明显就是用户了，provider就是consumer想要获取数据的地方。然后我们整个过程其实就是分三步来的。 consumer首先向provider申请，去获得request token consumer吧用户重定向到provider的网站去授权request token &#8230; <a href="http://www.isnowfy.com/understand-oauth/">继续阅读 <span class="meta-nav">&#8594;</span></a>]]></description> <content:encoded><![CDATA[<p><a href="http://www.isnowfy.com/wp-content/uploads/2012/01/My-Endpoints.png"><img src="http://www.isnowfy.com/wp-content/uploads/2012/01/My-Endpoints-300x267.png" alt="" title="My-Endpoints" width="300" height="267" class="alignnone size-medium wp-image-387" /></a><br /> 现在越来越多的网站开放api了，而且大部分都用了OAuth的认证方式，对于没接触过OAuth的人来说一开始理解起来感觉很困惑，觉得这个东西很麻烦，这篇文章就简单的从<a href="#what">什么是OAuth</a>，<a href="#why">为什么要有OAuth</a>，<a href="#progess">OAuth的认证流程</a>，以及<a href="#principle">OAuth为什么要这样设计</a>来谈一下。但是鉴于现在OAuth都已经有2.0了，但是2.0却不兼容1.0，而2.0主要依赖的是https，所以这里还是主要是来讲OAuth1.0的，确切的说是OAuth1.0a的。<br /> <span id="more-386"></span><br /> <a name="what"><br /><h4 style="color: #BF514C">什么是OAuth</h4><p></a></p><p>当你进入OAuth的<a href="http://oauth.net/">官网</a>，就能看到那句最醒目的描述</p><blockquote><p>An open protocol to allow secure API authorization in a simple and standard method from desktop and web applications.</p></blockquote><p>OAuth是一种开放的并且简单安全的协议，能够让你可以对桌面程序和web程序进行授权。好吧，看上去还是很抽象，那就接着看吧。</p><p><a name="why"><br /><h4 style="color: #BF514C">为什么要用OAuth</h4><p></a></p><p>一个非常常见的需求，就是我想获得用户在其他网站上的数据，比如，我做了个相片集中展示的网站，我希望用户可以导入他在flickr，或者facebook，或者人人上的照片。而OAuth就是一种能够安全方便的让我可以去别的网站获得用户的数据。</p><p>ok，你可能会想这个事情不简单嘛，我直接把我在其他网站的用户名密码告诉这个网站不就可以了。于是问题来了，这个网站你信的过吗，把用户名密码告诉他干坏事肿么办，如果我哪天不想用这个网站了，也不想让这个网站再获取数据了我是不是要改密码呢。<br /> <a href="http://www.isnowfy.com/wp-content/uploads/2012/01/daoru.png"><img src="http://www.isnowfy.com/wp-content/uploads/2012/01/daoru.png" alt="" title="daoru" width="558" height="159" class="alignnone size-full wp-image-399" /></a><br /> 他真的没有存储我的密码吗，CSDN都明文了，我还能相信爱情吗╮(￣▽￣")╭ 于是OAuth就是为了解决这些授权问题应运而生的。</p><p>OAuth最终会为每一个用户的每一个授权的应用都生成一对access token和access token secret，可以把它当做访问用户数据的特殊的用户名和密码。由于对于每一个用户而言，每一个授权应用的token和secret都是不同的，所以用户可以很方便的收回某个应用的授权而不影响其他的应用，而且不用去改密码，而且如果用户更改了密码，那些授权的token和secret依旧不受影响，这就是OAuth的解决方案了。</p><p>那么应用如何去获得token和secret就是下面要讲的了。</p><p><a name="progess"><br /><h4 style="color: #BF514C">OAuth的认证流程</h4><p></a></p><p>首先奉上一张官网上的流程图<br /> <a href="http://www.isnowfy.com/wp-content/uploads/2012/01/diagram.png"><img src="http://www.isnowfy.com/wp-content/uploads/2012/01/diagram.png" alt="" title="diagram" width="824" height="548" class="alignnone size-full wp-image-406" /></a><br /> 首先要明白整个需要三个角色，user，consumer，provider，首先consumer就是我要做的网站或者是说给用户提供服务的应用，user很明显就是用户了，provider就是consumer想要获取数据的地方。然后我们整个过程其实就是分三步来的。</p><ol><li>consumer首先向provider申请，去获得request token</li><li>consumer吧用户重定向到provider的网站去授权request token</li><li>consumer通过授权了的request token去向provider获得access token</li></ol><p>由图可以看到左边是流程，右边是每次携带的数据，每次都需要用密钥对数据进行url encode之后HMAC-SHA1签名的，然后oauth_nonce是一个随机的32位字符串和timestamp时间戳配合用来防止重放攻击的。</p><p>在应用创建的时候也就是很久很久以前。。。consumer需要先向provider申请consumer key和consumer secret，这个是每个应用一个，与用户无关的，第一步申请request token的时候就需要用consumer secret来签名。然后provider会返回request token和request token secret。</p><p>第二步就需要用consumer secret和request token secret来加密，重定向到provider用户的网站去让user授权request token，还记得OAuth定义吗，OAuth不仅可以为web应用授权，也可以为桌面应用授权，于是在这一步两种应用会稍有不同，如果是web应用，那么web会提供一个callback，回调地址，provider就可以通过这个地址，把一个vertify code传给consumer，而桌面应用需要用户手动把这个值输入给应用。</p><p>最后通过vertify code这个值和request token向provider申请就会获得access token和access token secret了，之后应用通过access token就可以在provider那里获得用户的数据了。</p><p>ok，其实作为开发者是没有必要对于整个过程亲自去构造的，OAuth是开源的协议，然后官方也提供了各种语言的包在<a href="http://code.google.com/p/oauth/">这里</a>。</p><p><a name="principle"><br /><h4 style="color: #BF514C">OAuth为什么要这样设计</h4><p></a></p><p>对于OAuth过程有些繁琐啊，需要三步才可以，那么我们能不能简化这个过程呢？</p><p>我们考虑如果我们只用一步就是consumer直接向provider去要access token，这显然是不行的，就是这样的话consumer根本不知道去要谁的access token，那么如果用户自己生成一对access token输入给consumer呢，也不行，用户不知道或者说会忘记这个access token是给谁了。再或者consumer把用户重定向到provider的网站，然后直接返回access token不行吗，不行的，别忘了我们还有客户端应用的，为了避免用户输入一大长传的access token还是需要两步的，也就是说我们至少需要两步。</p><p>那么我们能不能用两步呢，就是先把用户重定向到provider的网站，然后，consumer再来获取access token不行吗。恩，这个事情涉及到最早的1.0版本的问题，感谢<a href="http://huoding.com/2011/11/08/126">这篇文章</a>以及文章作者的解答，因为在1.0版本是没有vertify code的，然后再注意stackoverflow上<a href="http://stackoverflow.com/questions/2377541/why-must-we-change-temporary-credentials-for-token-credentials-in-oauth">这个问题的解答</a>也就是说以前是让用户输入request token的，所以需要这个东西设计的简短才行，于是便有现在的双token，来最终获取access token的方案。</p><p><a name="change"><br /><h4 style="color: #BF514C">1.0a的改变</h4><p></a></p><p>最后我们来谈谈为什么从最初的1.0变到现在1.0a的呢，答案很简单，就是有严重的安全漏洞！<a href="http://hueniverse.com/2009/04/explaining-the-oauth-session-fixation-attack/">这篇文章</a>有详细的说明，这里我简单说一下。<br /> <a href="http://www.isnowfy.com/wp-content/uploads/2012/01/OAuth-Flow-Exploit.png"><img src="http://www.isnowfy.com/wp-content/uploads/2012/01/OAuth-Flow-Exploit-169x300.png" alt="" title="OAuth-Flow-Exploit" width="169" height="300" class="alignnone size-medium wp-image-415" /></a><br /> 首先攻击者去访问consumer的网站，然后consumer就去向provider申请request token，之后把攻击者重定向到provider的网站，ok攻击者不去自己授权，而是把这个地址保存下来，之后利用诱骗啊想办法让受害者去点击这个地址，然后受害者进行授权，之后会调用回调地址，而这个回调地址是很容易构造的，于是攻击者就去自己调用回调地址给consumer，这样consumer就会获取到受害者的access token了，这样攻击者就可以利用consumer的网站来获取受害者的数据了。</p><p>于是1.0a就是修复了这个问题，加入了vertify code，并且对于callback也有一些限制。</p><p><a name="last"><br /><h4 style="color: #BF514C">写在最后</h4><p></a></p><p>如果你对1.0或者2.0的流程有兴趣的话，可以来看<a href="http://huoding.com/2011/11/08/126">这篇文章</a>，然后对于2.0似乎还有颇多争议啊<a href="http://www.infoq.com/cn/news/2010/09/oauth2-bad-for-web">OAuth 2.0对Web有害吗？</a><br /><strong>我猜您可能还会喜欢:</strong><ul class="similar-posts"><li><a href="http://www.isnowfy.com/comet-web-chat/" rel="bookmark" title="2011 年 08 月 05 日">利用comet技术实现web聊天</a></li><li><a href="http://www.isnowfy.com/dns-frame/" rel="bookmark" title="2011 年 07 月 10 日">DNS帧的格式</a></li><li><a href="http://www.isnowfy.com/introduction-to-gevent/" rel="bookmark" title="2011 年 12 月 21 日">gevent初步</a></li><li><a href="http://www.isnowfy.com/secret-key-exchange/" rel="bookmark" title="2011 年 07 月 30 日">关于密钥交换</a></li><li><a href="http://www.isnowfy.com/download-doubanfm-songs/" rel="bookmark" title="2011 年 11 月 13 日">自动下载豆瓣FM的加心歌曲</a></li><li><a href="http://www.isnowfy.com/android-sign-and-google-map-api/" rel="bookmark" title="2011 年 07 月 22 日">关于android应用签名以及google map api的申请和使用</a></li></ul><p></p> ]]></content:encoded> <wfw:commentRss>http://www.isnowfy.com/understand-oauth/feed/</wfw:commentRss> <slash:comments>1</slash:comments> </item> <item><title>md5到md5破解的一些科普</title><link>http://www.isnowfy.com/introduction-to-md5/</link> <comments>http://www.isnowfy.com/introduction-to-md5/#comments</comments> <pubDate>Mon, 02 Jan 2012 16:04:32 +0000</pubDate> <dc:creator>isnowfy</dc:creator> <category><![CDATA[数学]]></category> <category><![CDATA[math]]></category> <category><![CDATA[密码学]]></category><guid isPermaLink="false">http://www.isnowfy.com/?p=372</guid> <description><![CDATA[看到网上一些对于md5的介绍还有对于当初王小云所做的破解有很多的误解，或者说不理解，然后觉得对于这些事情只要说明白还是比较好理解的说。 首先md5其实就是一种hash，或者叫散列函数，有的地方叫杂凑函数，都是一个东西啦，其实他就是一种映射，而平常最常见的就是说md5是不可逆的，为什么不可逆呢，有人就说就是像有些函数没有反函数那样了，其实还是有点抽象，考虑md5是多对一的映射，也就是说很多不同的经过md5变换之后可能会是相同的，那么既然多对一，自然是不可逆啦╮(╯▽╰)╭，你怎么会知道他到底是由哪个变换过来的呢。在密码学的应用里，说是单向函数，或者说单向变换，一种是这种多对一不可逆，还有一种是说逆工程会非常困难，举个例子吧，假设f(x)=x^6-x-1，然后你知道f(1)=-1，在知道x=1和f的情况下计算f(1)是很简单的，而知道f(x)=-1和f去求x却是很困难的，这里就不展开说了，大家有个大体的认识就可以了。 刚才说过了由于md5是多对一的，所以肯定会出现变换后的值是一样的情况，这种情况叫做冲突，或者叫碰撞。为了保证安全性，定义了两种，一种叫无弱碰撞，一种叫无强碰撞。 无弱碰撞是说 已知函数M和一段数据H 找到一个H' 使得M(H)=M(H') 是难的 无强碰撞是 已知M 找到一对H和H' 使得M(H)=M(H') 是难的 很明显满足无强碰撞比满足无弱碰撞更难，真的吗？好吧，就不说明显了，为什么说无强碰撞更难呢，换句话说为什么找到强碰撞更简单呢，恩，这就涉及到生日悖论了，或者叫生日攻击了。 来想想以前的概率吧，假设一年365天，那么，至少有多少人使得有两人是同样生日的概率会超过1/2呢，直觉上应该是365/2个人吧，其实答案是23，少的夸张是吧，不然不会叫做悖论了啊，如何计算呢，其实我们是在求一个最小的n，使得1-(1-1/365)*(1-2/365)*...(1-(n-1)*365)>=1/2，随便写个程序验证下就知道是23了，什么你不知道这个式子怎么得来的，考虑第二个人不要和第一个人生日冲突的概率是(1-1/365)然后第三个人不和前两个人生日相同的概率是(1-2/365)后面就知道了吧。然后这个人数其实是O(sqrt(365))。那么回到前面的问题，假设映射空间，就是说最后能够得到的值的个数是m，那么弱碰撞的复杂度是O(m)，而强碰撞呢是O(sqrt(m))，所以说找到强碰撞更简单，也就是说满足无强碰撞更难！ 王小云的贡献呢就是找到了比生日攻击复杂度低得多算法来快速找到一对强碰撞，弱碰撞吗依旧是不行的╮(╯▽╰)╭这里有她的论文，有兴趣的可以看一下。那么也就是说通过密文找到明文依旧是不可能的，并且弱碰撞依旧是很难的。 不过后来又有外国的nb人受到了王小云的启发，得到了一种很快的算法能够在已知前缀x1,x2的情况下构造一对后缀y1,y2使得M(x1y1)=M(x2y2)，不过有两点需要注意，一个是他其实还是一种寻找强碰撞，另一个就是他的复杂度比王小云的直接构造高的多，然后这里有论文，然后利用这个搞了个预测2008年美国大选结果的东西，为啥叫预测呢，因为可以这样 因为我说我知道大选结果，但是必须事后公布，为了保证我没有说谎，我先给出一段md5的值， 之后给出我的结果，只要结果和md5相同不就是我预测成功了吗 这个东西是基于我很难构造两个东西使得他们的md5相同的基础上的，不过有了上面的算法，这个事情的复杂度大大降低，使得变为了可能。 那么这些破解对于我们有什么影响呢，首先需要认识到md5有什么用，现在很多网站都用md5来验证文件的完整性，但是你从非官方的地方下载了文件发现md5相同，那么你依然不能掉以轻心，因为可能是通过上述算法而在程序里加入了某段病毒代码，但是md5还是相同的而已，所以下文件还是从官方地址下吧，还一个就是经常在数字签名里使用了，至于不知道数字签名的这里先不说了，然后这个可以伪造数字签名啥的，不过传说现在貌似没谁用md5来弄数字签名了，也不必太过担心了，ok基本就是这样子了。我猜您可能还会喜欢: 浅析java的hashmap 一个期望问题]]></description> <content:encoded><![CDATA[<p><a href="http://www.isnowfy.com/wp-content/uploads/2012/01/lnqhiq.jpg"><img src="http://www.isnowfy.com/wp-content/uploads/2012/01/lnqhiq-300x199.jpg" alt="" title="Computer Password Security" width="300" height="199" class="alignnone size-medium wp-image-373" /></a><br /> 看到网上一些对于md5的介绍还有对于当初王小云所做的破解有很多的误解，或者说不理解，然后觉得对于这些事情只要说明白还是比较好理解的说。<br /> <span id="more-372"></span></p><p>首先md5其实就是一种hash，或者叫散列函数，有的地方叫杂凑函数，都是一个东西啦，其实他就是一种映射，而平常最常见的就是说md5是不可逆的，为什么不可逆呢，有人就说就是像有些函数没有反函数那样了，其实还是有点抽象，考虑md5是多对一的映射，也就是说很多不同的经过md5变换之后可能会是相同的，那么既然多对一，自然是不可逆啦╮(╯▽╰)╭，你怎么会知道他到底是由哪个变换过来的呢。在密码学的应用里，说是单向函数，或者说单向变换，一种是这种多对一不可逆，还有一种是说逆工程会非常困难，举个例子吧，假设f(x)=x^6-x-1，然后你知道f(1)=-1，在知道x=1和f的情况下计算f(1)是很简单的，而知道f(x)=-1和f去求x却是很困难的，这里就不展开说了，大家有个大体的认识就可以了。</p><p>刚才说过了由于md5是多对一的，所以肯定会出现变换后的值是一样的情况，这种情况叫做冲突，或者叫碰撞。为了保证安全性，定义了两种，一种叫无弱碰撞，一种叫无强碰撞。</p><p>无弱碰撞是说</p><pre>
已知函数M和一段数据H
找到一个H'
使得M(H)=M(H')
是难的
</pre><p>无强碰撞是</p><pre>
已知M
找到一对H和H'
使得M(H)=M(H')
是难的
</pre><p>很明显满足无强碰撞比满足无弱碰撞更难，真的吗？好吧，就不说明显了，为什么说无强碰撞更难呢，换句话说为什么找到强碰撞更简单呢，恩，这就涉及到生日悖论了，或者叫生日攻击了。</p><p>来想想以前的概率吧，假设一年365天，那么，至少有多少人使得有两人是同样生日的概率会超过1/2呢，直觉上应该是365/2个人吧，其实答案是23，少的夸张是吧，不然不会叫做悖论了啊，如何计算呢，其实我们是在求一个最小的n，使得1-(1-1/365)*(1-2/365)*...(1-(n-1)*365)>=1/2，随便写个程序验证下就知道是23了，什么你不知道这个式子怎么得来的，考虑第二个人不要和第一个人生日冲突的概率是(1-1/365)然后第三个人不和前两个人生日相同的概率是(1-2/365)后面就知道了吧。然后这个人数其实是O(sqrt(365))。那么回到前面的问题，假设映射空间，就是说最后能够得到的值的个数是m，那么弱碰撞的复杂度是O(m)，而强碰撞呢是O(sqrt(m))，所以说找到强碰撞更简单，也就是说满足无强碰撞更难！</p><p>王小云的贡献呢就是找到了比生日攻击复杂度低得多算法来快速找到一对强碰撞，弱碰撞吗依旧是不行的╮(╯▽╰)╭<a href="http://merlot.usc.edu/csac-f06/papers/Wang05a.pdf">这里</a>有她的论文，有兴趣的可以看一下。那么也就是说通过密文找到明文依旧是不可能的，并且弱碰撞依旧是很难的。</p><p>不过后来又有外国的nb人受到了王小云的启发，得到了一种很快的算法能够在已知前缀x1,x2的情况下构造一对后缀y1,y2使得M(x1y1)=M(x2y2)，不过有两点需要注意，一个是他其实还是一种寻找强碰撞，另一个就是他的复杂度比王小云的直接构造高的多，然后<a href="http://www.win.tue.nl/hashclash/EC07v2.0.pdf">这里</a>有论文，然后利用这个搞了个<a href="http://www.win.tue.nl/hashclash/Nostradamus/">预测2008年美国大选结果</a>的东西，为啥叫预测呢，因为可以这样</p><pre>
因为我说我知道大选结果，但是必须事后公布，为了保证我没有说谎，我先给出一段md5的值，
之后给出我的结果，只要结果和md5相同不就是我预测成功了吗
</pre><p>这个东西是基于我很难构造两个东西使得他们的md5相同的基础上的，不过有了上面的算法，这个事情的复杂度大大降低，使得变为了可能。</p><p>那么这些破解对于我们有什么影响呢，首先需要认识到md5有什么用，现在很多网站都用md5来验证文件的完整性，但是你从非官方的地方下载了文件发现md5相同，那么你依然不能掉以轻心，因为可能是通过上述算法而在程序里加入了某段病毒代码，但是md5还是相同的而已，所以下文件还是从官方地址下吧，还一个就是经常在数字签名里使用了，至于不知道数字签名的这里先不说了，然后这个可以伪造数字签名啥的，不过传说现在貌似没谁用md5来弄数字签名了，也不必太过担心了，ok基本就是这样子了。<br /><strong>我猜您可能还会喜欢:</strong><ul class="similar-posts"><li><a href="http://www.isnowfy.com/java-hashmap/" rel="bookmark" title="2011 年 12 月 07 日">浅析java的hashmap</a></li><li><a href="http://www.isnowfy.com/expectation-problem/" rel="bookmark" title="2011 年 09 月 12 日">一个期望问题</a></li></ul><p></p> ]]></content:encoded> <wfw:commentRss>http://www.isnowfy.com/introduction-to-md5/feed/</wfw:commentRss> <slash:comments>9</slash:comments> </item> <item><title>gevent初步</title><link>http://www.isnowfy.com/introduction-to-gevent/</link> <comments>http://www.isnowfy.com/introduction-to-gevent/#comments</comments> <pubDate>Tue, 20 Dec 2011 16:54:44 +0000</pubDate> <dc:creator>isnowfy</dc:creator> <category><![CDATA[web]]></category> <category><![CDATA[python]]></category><guid isPermaLink="false">http://www.isnowfy.com/?p=362</guid> <description><![CDATA[话说gevent也没个logo啥的，于是就摆了这张图= =&#124;&#124;&#124;，首先这是一种叫做greenlet的鸟，而在python里，按照官方解释greenlet是轻量级的并行编程，而gevent呢，就是利用greenlet实现的基于协程的python的网络library，好了，关系理清了。。。 话说pycon没有白去阿，了解了很多以前不知道的东西，比如说协程，gevent，greenlet，eventlet。说说协程，进程和线程大家平时了解的都比较多，而协程算是一种轻量级进程，但又不能叫进程，因为操作系统并不知道它的存在。什么意思呢，就是说，协程像是一种在程序级别来模拟系统级别的进程，由于是单进程，并且少了上下文切换，于是相对来说系统消耗很少，而且网上的各种测试也表明，协程确实拥有惊人的速度。并且在实现过程中，协程可以用以前同步思路的写法，而运行起来确是异步的，也确实很有意思。话说有一种说法就是说进化历程是多进程->多线程->异步->协程，暂且不论说的对不对，单从诸多赞誉来看，协程还是有必要理解一下的。 比较惭愧，greenlet没怎么看就直接看gevent，官方文档还是可以看看的，尤其是源码里的examples都相当不错，有助于理解gevent的使用。 gevent封装了很多很方便的接口，其中一个就是monkey from gevent import monkey monkey.patch_all&#40;&#41; 这样两行，就可以使用python以前的socket之类的，因为gevent已经给你自动转化了，真是超级方便阿。 而且安装gevent也是很方便，首先安装依赖libevent和greenlet，再利用pypi安装即可 sudo apt-get install libevent-dev sudo apt-get install python-dev sudo easy-install gevent 然后，gevent中的event，有wait，set等api，方便你可以让某些协程在某些地方等待条件，然后用另一个去唤醒他们。 再就是gevent实现了wsgi可以很方便的当作python的web server服务器使。 最后放送一个我利用gevent实现的一个带有缓存的dns server &#160;# -*- coding: UTF-8 -*- &#160; import gevent import dnslib from gevent &#8230; <a href="http://www.isnowfy.com/introduction-to-gevent/">继续阅读 <span class="meta-nav">&#8594;</span></a>]]></description> <content:encoded><![CDATA[<p><a href="http://www.isnowfy.com/wp-content/uploads/2011/12/Lesser-Greenlet-unionjuarez_9949.jpg"><img src="http://www.isnowfy.com/wp-content/uploads/2011/12/Lesser-Greenlet-unionjuarez_9949-300x259.jpg" alt="" title="Lesser-Greenlet-unionjuarez_9949" width="300" height="259" class="alignnone size-medium wp-image-363" /></a><br /> 话说gevent也没个logo啥的，于是就摆了这张图= =|||，首先这是一种叫做greenlet的鸟，而在python里，按照官方解释greenlet是轻量级的并行编程，而gevent呢，就是利用greenlet实现的基于协程的python的网络library，好了，关系理清了。。。<br /> <span id="more-362"></span></p><p>话说pycon没有白去阿，了解了很多以前不知道的东西，比如说协程，gevent，greenlet，eventlet。说说协程，进程和线程大家平时了解的都比较多，而协程算是一种轻量级进程，但又不能叫进程，因为操作系统并不知道它的存在。什么意思呢，就是说，协程像是一种在程序级别来模拟系统级别的进程，由于是单进程，并且少了上下文切换，于是相对来说系统消耗很少，而且网上的各种测试也表明，协程确实拥有惊人的速度。并且在实现过程中，协程可以用以前同步思路的写法，而运行起来确是异步的，也确实很有意思。话说有一种说法就是说进化历程是多进程->多线程->异步->协程，暂且不论说的对不对，单从诸多赞誉来看，协程还是有必要理解一下的。</p><p>比较惭愧，greenlet没怎么看就直接看gevent，<a href="http://www.gevent.org/contents.html">官方文档</a>还是可以看看的，尤其是源码里的examples都相当不错，有助于理解gevent的使用。</p><p>gevent封装了很多很方便的接口，其中一个就是monkey</p><div class="geshi no python"><ol><li class="li1"><div class="de1"><span class="kw1">from</span> gevent <span class="kw1">import</span> monkey</div></li><li class="li1"><div class="de1">monkey.<span class="me1">patch_all</span><span class="br0">&#40;</span><span class="br0">&#41;</span></div></li></ol></div><p>这样两行，就可以使用python以前的socket之类的，因为gevent已经给你自动转化了，真是超级方便阿。</p><p>而且安装gevent也是很方便，首先安装依赖libevent和greenlet，再利用pypi安装即可</p><div class="geshi no shell"><ol><li class="li1"><div class="de1">sudo apt-get install libevent-dev</div></li><li class="li1"><div class="de1">sudo apt-get install python-dev</div></li><li class="li1"><div class="de1">sudo easy-install gevent</div></li></ol></div><p>然后，gevent中的event，有wait，set等api，方便你可以让某些协程在某些地方等待条件，然后用另一个去唤醒他们。</p><p>再就是gevent实现了wsgi可以很方便的当作python的web server服务器使。</p><p>最后放送一个我利用gevent实现的一个带有缓存的dns server</p><div class="geshi no python"><ol><li class="li1"><div class="de1">&nbsp;<span class="co1"># -*- coding: UTF-8 -*-</span></div></li><li class="li1"><div class="de1">&nbsp;</div></li><li class="li1"><div class="de1"><span class="kw1">import</span> gevent</div></li><li class="li1"><div class="de1"><span class="kw1">import</span> dnslib</div></li><li class="li1"><div class="de1"><span class="kw1">from</span> gevent <span class="kw1">import</span> <span class="kw3">socket</span></div></li><li class="li1"><div class="de1"><span class="kw1">from</span> gevent <span class="kw1">import</span> event</div></li><li class="li1"><div class="de1">&nbsp;</div></li><li class="li1"><div class="de1">rev=<span class="kw3">socket</span>.<span class="kw3">socket</span><span class="br0">&#40;</span><span class="kw3">socket</span>.<span class="me1">AF_INET</span>,<span class="kw3">socket</span>.<span class="me1">SOCK_DGRAM</span><span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">rev.<span class="me1">bind</span><span class="br0">&#40;</span><span class="br0">&#40;</span><span class="st0">&#39;&#39;</span>,<span class="nu0">53</span><span class="br0">&#41;</span><span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">ip=<span class="br0">&#91;</span><span class="br0">&#93;</span></div></li><li class="li1"><div class="de1">cur=<span class="nu0">0</span></div></li><li class="li1"><div class="de1">&nbsp;</div></li><li class="li1"><div class="de1"><span class="kw1">def</span> preload<span class="br0">&#40;</span><span class="br0">&#41;</span>:</div></li><li class="li1"><div class="de1">&nbsp; &nbsp; <span class="kw1">for</span> i <span class="kw1">in</span> <span class="kw2">open</span><span class="br0">&#40;</span><span class="st0">&#39;ip&#39;</span><span class="br0">&#41;</span>:</div></li><li class="li1"><div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; ip.<span class="me1">append</span><span class="br0">&#40;</span>i<span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; <span class="kw1">print</span> <span class="st0">&quot;load &quot;</span>+<span class="kw2">str</span><span class="br0">&#40;</span><span class="kw2">len</span><span class="br0">&#40;</span>ip<span class="br0">&#41;</span><span class="br0">&#41;</span>+<span class="st0">&quot; ip&quot;</span></div></li><li class="li1"><div class="de1">&nbsp;</div></li><li class="li1"><div class="de1"><span class="kw1">def</span> send_request<span class="br0">&#40;</span>data<span class="br0">&#41;</span>:</div></li><li class="li1"><div class="de1">&nbsp; &nbsp; <span class="kw1">global</span> cur</div></li><li class="li1"><div class="de1">&nbsp; &nbsp; ret=rev.<span class="me1">sendto</span><span class="br0">&#40;</span>data,<span class="br0">&#40;</span>ip<span class="br0">&#91;</span>cur<span class="br0">&#93;</span>,<span class="nu0">53</span><span class="br0">&#41;</span><span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; cur=<span class="br0">&#40;</span>cur<span class="nu0">+1</span><span class="br0">&#41;</span><span class="sy0">%</span><span class="kw2">len</span><span class="br0">&#40;</span>ip<span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">&nbsp;</div></li><li class="li1"><div class="de1"><span class="kw1">class</span> Cache:</div></li><li class="li1"><div class="de1">&nbsp; &nbsp; <span class="kw1">def</span> <span class="kw4">__init__</span><span class="br0">&#40;</span><span class="kw2">self</span><span class="br0">&#41;</span>:</div></li><li class="li1"><div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">c</span>=<span class="br0">&#123;</span><span class="br0">&#125;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; <span class="kw1">def</span> get<span class="br0">&#40;</span><span class="kw2">self</span>,key<span class="br0">&#41;</span>:</div></li><li class="li1"><div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">self</span>.<span class="me1">c</span>.<span class="me1">get</span><span class="br0">&#40;</span>key,<span class="kw2">None</span><span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; <span class="kw1">def</span> <span class="kw2">set</span><span class="br0">&#40;</span><span class="kw2">self</span>,key,value<span class="br0">&#41;</span>:</div></li><li class="li1"><div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">c</span><span class="br0">&#91;</span>key<span class="br0">&#93;</span>=value</div></li><li class="li1"><div class="de1">&nbsp; &nbsp; <span class="kw1">def</span> remove<span class="br0">&#40;</span><span class="kw2">self</span>,key<span class="br0">&#41;</span>:</div></li><li class="li1"><div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">c</span>.<span class="me1">pop</span><span class="br0">&#40;</span>key,<span class="kw2">None</span><span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">&nbsp;</div></li><li class="li1"><div class="de1">cache=Cache<span class="br0">&#40;</span><span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">&nbsp;</div></li><li class="li1"><div class="de1"><span class="kw1">def</span> handle_request<span class="br0">&#40;</span>s,data,addr<span class="br0">&#41;</span>:</div></li><li class="li1"><div class="de1">&nbsp; &nbsp; req=dnslib.<span class="me1">DNSRecord</span>.<span class="me1">parse</span><span class="br0">&#40;</span>data<span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; qname=<span class="kw2">str</span><span class="br0">&#40;</span>req.<span class="me1">q</span>.<span class="me1">qname</span><span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; qid=req.<span class="me1">header</span>.<span class="kw2">id</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; ret=cache.<span class="me1">get</span><span class="br0">&#40;</span>qname<span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; <span class="kw1">if</span> ret:</div></li><li class="li1"><div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; ret=dnslib.<span class="me1">DNSRecord</span>.<span class="me1">parse</span><span class="br0">&#40;</span>ret<span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; ret.<span class="me1">header</span>.<span class="kw2">id</span>=qid<span class="sy0">;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; s.<span class="me1">sendto</span><span class="br0">&#40;</span>ret.<span class="me1">pack</span><span class="br0">&#40;</span><span class="br0">&#41;</span>,addr<span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; <span class="kw1">else</span>:</div></li><li class="li1"><div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; e=event.<span class="me1">Event</span><span class="br0">&#40;</span><span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; cache.<span class="kw2">set</span><span class="br0">&#40;</span>qname+<span class="st0">&quot;e&quot;</span>,e<span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; send_request<span class="br0">&#40;</span>data<span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; e.<span class="me1">wait</span><span class="br0">&#40;</span><span class="nu0">60</span><span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; tmp=cache.<span class="me1">get</span><span class="br0">&#40;</span>qname<span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> tmp:</div></li><li class="li1"><div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; tmp=dnslib.<span class="me1">DNSRecord</span>.<span class="me1">parse</span><span class="br0">&#40;</span>tmp<span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; tmp.<span class="me1">header</span>.<span class="kw2">id</span>=qid<span class="sy0">;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; s.<span class="me1">sendto</span><span class="br0">&#40;</span>tmp.<span class="me1">pack</span><span class="br0">&#40;</span><span class="br0">&#41;</span>,addr<span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">&nbsp;</div></li><li class="li1"><div class="de1"><span class="kw1">def</span> handle_response<span class="br0">&#40;</span>data<span class="br0">&#41;</span>:</div></li><li class="li1"><div class="de1">&nbsp; &nbsp; req=dnslib.<span class="me1">DNSRecord</span>.<span class="me1">parse</span><span class="br0">&#40;</span>data<span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; qname=<span class="kw2">str</span><span class="br0">&#40;</span>req.<span class="me1">q</span>.<span class="me1">qname</span><span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; <span class="kw1">print</span> qname</div></li><li class="li1"><div class="de1">&nbsp; &nbsp; cache.<span class="kw2">set</span><span class="br0">&#40;</span>qname,data<span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; e=cache.<span class="me1">get</span><span class="br0">&#40;</span>qname+<span class="st0">&quot;e&quot;</span><span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; cache.<span class="me1">remove</span><span class="br0">&#40;</span>qname+<span class="st0">&quot;e&quot;</span><span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; <span class="kw1">if</span> e:</div></li><li class="li1"><div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; e.<span class="kw2">set</span><span class="br0">&#40;</span><span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; e.<span class="me1">clear</span><span class="br0">&#40;</span><span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">&nbsp;</div></li><li class="li1"><div class="de1"><span class="kw1">def</span> handler<span class="br0">&#40;</span>s,data,addr<span class="br0">&#41;</span>:</div></li><li class="li1"><div class="de1">&nbsp; &nbsp; req=dnslib.<span class="me1">DNSRecord</span>.<span class="me1">parse</span><span class="br0">&#40;</span>data<span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; <span class="kw1">if</span> req.<span class="me1">header</span>.<span class="me1">qr</span>:</div></li><li class="li1"><div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; handle_response<span class="br0">&#40;</span>data<span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; <span class="kw1">else</span>:handle_request<span class="br0">&#40;</span>s,data,addr<span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">&nbsp;</div></li><li class="li1"><div class="de1"><span class="kw1">def</span> main<span class="br0">&#40;</span><span class="br0">&#41;</span>:</div></li><li class="li1"><div class="de1">&nbsp; &nbsp; preload<span class="br0">&#40;</span><span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; <span class="kw1">while</span> <span class="kw2">True</span>:</div></li><li class="li1"><div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; data,addr=rev.<span class="me1">recvfrom</span><span class="br0">&#40;</span><span class="nu0">8192</span><span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; gevent.<span class="me1">spawn</span><span class="br0">&#40;</span>handler,rev,data,addr<span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">&nbsp;</div></li><li class="li1"><div class="de1"><span class="kw1">if</span> __name__ == <span class="st0">&#39;__main__&#39;</span>:</div></li><li class="li1"><div class="de1">&nbsp; &nbsp; main<span class="br0">&#40;</span><span class="br0">&#41;</span></div></li></ol></div><p>这个是直接利用了dict来作为缓存查询了，在<a href="https://github.com/isnowfy/dns">这里</a>还有我将dict换成redis持久化实现的另一个版本(话说redis的python api也可以利用pypi安装，pypi这真是个好东西阿)，话说可以将这段代码放到国外的服务器上去运行，然后修改dns的地址去指向它，然后你懂的。。。<br /><strong>我猜您可能还会喜欢:</strong><ul class="similar-posts"><li><a href="http://www.isnowfy.com/download-doubanfm-songs/" rel="bookmark" title="2011 年 11 月 13 日">自动下载豆瓣FM的加心歌曲</a></li><li><a href="http://www.isnowfy.com/machine-learning-subtitle-script/" rel="bookmark" title="2011 年 10 月 11 日">machine learning公开课的字幕获取脚本</a></li><li><a href="http://www.isnowfy.com/libcurl-fetch-webpage/" rel="bookmark" title="2011 年 08 月 27 日">c中使用libcurl抓取网页</a></li><li><a href="http://www.isnowfy.com/dns-frame/" rel="bookmark" title="2011 年 07 月 10 日">DNS帧的格式</a></li><li><a href="http://www.isnowfy.com/similar-image-search/" rel="bookmark" title="2011 年 09 月 04 日">关于相似图片搜索</a></li><li><a href="http://www.isnowfy.com/lucene-build-search/" rel="bookmark" title="2011 年 07 月 10 日">lucene3.2 简单的建立索引和查询</a></li><li><a href="http://www.isnowfy.com/wordpress-optimization/" rel="bookmark" title="2011 年 08 月 16 日">又折腾了一把wordpress</a></li></ul><p></p> ]]></content:encoded> <wfw:commentRss>http://www.isnowfy.com/introduction-to-gevent/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>浅析java的hashmap</title><link>http://www.isnowfy.com/java-hashmap/</link> <comments>http://www.isnowfy.com/java-hashmap/#comments</comments> <pubDate>Wed, 07 Dec 2011 15:52:09 +0000</pubDate> <dc:creator>isnowfy</dc:creator> <category><![CDATA[program]]></category> <category><![CDATA[hash]]></category> <category><![CDATA[java]]></category><guid isPermaLink="false">http://www.isnowfy.com/?p=349</guid> <description><![CDATA[话说java的hashmap很好用啊，看了java的源代码之后其实发现实现也蛮简单的，map的用法就是key-value的用法，然后对于每一个对象都有一个hashcode，在hashmap内部就是利用这个hashcode来找到value的。 那么hashcode一般而言是对象的在jvm中的一个32位的地址，所以不会重复，可能有人注意到，这样的话如果用string做key那么两个内容相同的串其地址不同，那么hashcode也不同，这样就不合理了，所以实际上在String.java里是override了hashcode的方法的。 public int hashCode&#40;&#41; &#123; &#160; &#160; int h = hash; &#160; &#160; if &#40;h == 0&#41; &#123; &#160; &#160; &#160; &#160; int off = offset; &#160; &#160; &#160; &#160; char val&#91;&#93; = value; &#160; &#160; &#160; &#160; int &#8230; <a href="http://www.isnowfy.com/java-hashmap/">继续阅读 <span class="meta-nav">&#8594;</span></a>]]></description> <content:encoded><![CDATA[<p><a href="http://www.isnowfy.com/wp-content/uploads/2011/12/java.jpg"><img src="http://www.isnowfy.com/wp-content/uploads/2011/12/java.jpg" alt="" title="java" width="300" height="300" class="alignnone size-full wp-image-350" /></a><br /> 话说java的hashmap很好用啊，看了java的源代码之后其实发现实现也蛮简单的，map的用法就是key-value的用法，然后对于每一个对象都有一个hashcode，在hashmap内部就是利用这个hashcode来找到value的。<br /> <span id="more-349"></span></p><p>那么hashcode一般而言是对象的在jvm中的一个32位的地址，所以不会重复，可能有人注意到，这样的话如果用string做key那么两个内容相同的串其地址不同，那么hashcode也不同，这样就不合理了，所以实际上在String.java里是override了hashcode的方法的。</p><div class="geshi no java"><ol><li class="li1"><div class="de1"><span class="kw2">public</span> <span class="kw4">int</span> hashCode<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; <span class="kw4">int</span> h = hash<span class="sy0">;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>h == <span class="nu0">0</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> off = offset<span class="sy0">;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">char</span> val<span class="br0">&#91;</span><span class="br0">&#93;</span> = value<span class="sy0">;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> len = count<span class="sy0">;</span></div></li><li class="li1"><div class="de1">&nbsp;</div></li><li class="li1"><div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">for</span> <span class="br0">&#40;</span><span class="kw4">int</span> i = <span class="nu0">0</span><span class="sy0">;</span> i <span class="sy0">&lt;</span> len<span class="sy0">;</span> i++<span class="br0">&#41;</span> <span class="br0">&#123;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; h = <span class="nu0">31</span><span class="sy0">*</span>h + val<span class="br0">&#91;</span>off++<span class="br0">&#93;</span><span class="sy0">;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; hash = h<span class="sy0">;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; <span class="br0">&#125;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; <span class="kw2">return</span> h<span class="sy0">;</span></div></li><li class="li1"><div class="de1"><span class="br0">&#125;</span></div></li></ol></div><p>其实这就是BKDRHash，详细可以看<a href="http://www.byvoid.com/blog/string-hash-compare/">这里</a>，话说31也是个magic number 呢。</p><p>有了这个可以作为主键的值，剩下的问题就是hash函数和冲突处理了。</p><div class="geshi no java"><ol><li class="li1"><div class="de1"><span class="kw2">static</span> <span class="kw4">int</span> indexFor<span class="br0">&#40;</span><span class="kw4">int</span> h, <span class="kw4">int</span> length<span class="br0">&#41;</span> <span class="br0">&#123;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; <span class="kw2">return</span> h <span class="sy0">&amp;</span> <span class="br0">&#40;</span>length<span class="nu0">-1</span><span class="br0">&#41;</span><span class="sy0">;</span></div></li><li class="li1"><div class="de1"><span class="br0">&#125;</span></div></li></ol></div><p>hash函数用了位运算里常用的&#038;操作，而这里的length是2的幂，这样比一般的取模操作快了很多。</p><p>我们再看get里冲突是如何处理的（put同理）</p><div class="geshi no java"><ol><li class="li1"><div class="de1"><span class="kw2">public</span> V get<span class="br0">&#40;</span><span class="kw3">Object</span> key<span class="br0">&#41;</span> <span class="br0">&#123;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>key == <span class="kw2">null</span><span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">return</span> getForNullKey<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; <span class="kw4">int</span> hash = hash<span class="br0">&#40;</span>key.<span class="me1">hashCode</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; <span class="kw1">for</span> <span class="br0">&#40;</span>Entry<span class="sy0">&lt;</span>K,V<span class="sy0">&gt;</span> e = table<span class="br0">&#91;</span>indexFor<span class="br0">&#40;</span>hash, table.<span class="me1">length</span><span class="br0">&#41;</span><span class="br0">&#93;</span><span class="sy0">;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; e <span class="sy0">!</span>= <span class="kw2">null</span><span class="sy0">;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; e = e.<span class="me1">next</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">Object</span> k<span class="sy0">;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>e.<span class="me1">hash</span> == hash <span class="sy0">&amp;&amp;</span> <span class="br0">&#40;</span><span class="br0">&#40;</span>k = e.<span class="me1">key</span><span class="br0">&#41;</span> == key || key.<span class="me1">equals</span><span class="br0">&#40;</span>k<span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">return</span> e.<span class="me1">value</span><span class="sy0">;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; <span class="br0">&#125;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; <span class="kw2">return</span> <span class="kw2">null</span><span class="sy0">;</span></div></li><li class="li1"><div class="de1"><span class="br0">&#125;</span></div></li></ol></div><p>一般处理冲突的方法有两种，一个是开散列，就是如果这个位置被占了就换个位置。另一个是hash链表，对于每个位置都创建链表来存储所有hash值相同的，而java里就是用了第二种方案。</p><p>注意到还有个hash函数，这是为了让所有位都能够影响到index的计算</p><div class="geshi no java"><ol><li class="li1"><div class="de1"><span class="kw2">static</span> <span class="kw4">int</span> hash<span class="br0">&#40;</span><span class="kw4">int</span> h<span class="br0">&#41;</span> <span class="br0">&#123;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; <span class="co1">// This function ensures that hashCodes that differ only by</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; <span class="co1">// constant multiples at each bit position have a bounded</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; <span class="co1">// number of collisions (approximately 8 at default load factor).</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; h ^= <span class="br0">&#40;</span>h <span class="sy0">&gt;&gt;&gt;</span> <span class="nu0">20</span><span class="br0">&#41;</span> ^ <span class="br0">&#40;</span>h <span class="sy0">&gt;&gt;&gt;</span> <span class="nu0">12</span><span class="br0">&#41;</span><span class="sy0">;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; <span class="kw2">return</span> h ^ <span class="br0">&#40;</span>h <span class="sy0">&gt;&gt;&gt;</span> <span class="nu0">7</span><span class="br0">&#41;</span> ^ <span class="br0">&#40;</span>h <span class="sy0">&gt;&gt;&gt;</span> <span class="nu0">4</span><span class="br0">&#41;</span><span class="sy0">;</span></div></li><li class="li1"><div class="de1"><span class="br0">&#125;</span></div></li></ol></div><p>ok，基本就是这样了，道理还是比较好懂的，利用hashcode使得所有对象都可以作为key还是比较好的想法。<br /> <br /><strong>我猜您可能还会喜欢:</strong><ul class="similar-posts"><li><a href="http://www.isnowfy.com/lucene-build-search/" rel="bookmark" title="2011 年 07 月 10 日">lucene3.2 简单的建立索引和查询</a></li><li><a href="http://www.isnowfy.com/surreal-number/" rel="bookmark" title="2011 年 07 月 15 日">surreal number</a></li><li><a href="http://www.isnowfy.com/download-doubanfm-songs/" rel="bookmark" title="2011 年 11 月 13 日">自动下载豆瓣FM的加心歌曲</a></li><li><a href="http://www.isnowfy.com/android-sign-and-google-map-api/" rel="bookmark" title="2011 年 07 月 22 日">关于android应用签名以及google map api的申请和使用</a></li><li><a href="http://www.isnowfy.com/introduction-to-md5/" rel="bookmark" title="2012 年 01 月 03 日">md5到md5破解的一些科普</a></li><li><a href="http://www.isnowfy.com/comet-web-chat/" rel="bookmark" title="2011 年 08 月 05 日">利用comet技术实现web聊天</a></li><li><a href="http://www.isnowfy.com/dns-frame/" rel="bookmark" title="2011 年 07 月 10 日">DNS帧的格式</a></li></ul><p></p> ]]></content:encoded> <wfw:commentRss>http://www.isnowfy.com/java-hashmap/feed/</wfw:commentRss> <slash:comments>1</slash:comments> </item> <item><title>自动下载豆瓣FM的加心歌曲</title><link>http://www.isnowfy.com/download-doubanfm-songs/</link> <comments>http://www.isnowfy.com/download-doubanfm-songs/#comments</comments> <pubDate>Sun, 13 Nov 2011 03:16:26 +0000</pubDate> <dc:creator>isnowfy</dc:creator> <category><![CDATA[program]]></category> <category><![CDATA[chrome]]></category> <category><![CDATA[python]]></category> <category><![CDATA[script]]></category><guid isPermaLink="false">http://www.isnowfy.com/?p=330</guid> <description><![CDATA[平时比较喜欢听豆瓣电台的，于是加心了很多歌曲，和很多人一样都想把加心的歌曲下载到本地。毕竟豆瓣电台并不会循环播放你的加心歌曲的，于是搜了一下，发现网上只是通过某些手段获得加心歌曲的列表，然后再用其他的工具下载，这里有很多弊端，比如可能会有歌名一样的情况，而且有些小众歌曲无法或者说很难在网上搜到，于是就写了这个用于直接在豆瓣网上下载加心歌曲的小程序。 注意到加心的歌曲其实都是对应到某个专辑上的，并且我们可以让我们喜欢的专辑开始播放利用这个地址http://douban.fm/?context=channel:0&#124;subject_id:2781176 然后手动的话就可以通过抓包来获取你想要的歌曲下载地址了，把这一系列动作写成程序就可以自动下载所有加心歌曲了。 程序使用了BeautifulSoup，可以在这里下载http://www.crummy.com/software/BeautifulSoup/#Download下载BeautifulSoup.py文件和本程序放在同一目录下即可。 下面是程序： # coding: utf-8 &#160; from BeautifulSoup import BeautifulSoup import urllib,urllib2,cookielib,re &#160; def handle&#40;s&#41;: &#160; &#160; return s.replace&#40;&#34;&#38;lt;&#34;,&#34;&#60;&#34;&#41;.replace&#40;&#34;&#38;gt;&#34;,&#34;&#62;&#34;&#41;.replace&#40;&#34;\\&#34;,&#34;&#34;&#41; &#160; &#160; def fhandle&#40;s&#41;: &#160; &#160; return s.replace&#40;&#34;/&#34;,&#34;and&#34;&#41;.replace&#40;&#34; &#34;,&#34;&#34;&#41; &#160; def get&#40;myurl,cookie&#41;: &#160; &#160; url2=&#34;http://douban.fm/j/mine/playlist?type=n&#38;h=&#38;channel=0&#38;context=channel:0&#124;subject_id:%d&#34; &#160; &#160; opener &#8230; <a href="http://www.isnowfy.com/download-doubanfm-songs/">继续阅读 <span class="meta-nav">&#8594;</span></a>]]></description> <content:encoded><![CDATA[<p><a href="http://www.isnowfy.com/wp-content/uploads/2011/11/doubanfm.png"><img src="http://www.isnowfy.com/wp-content/uploads/2011/11/doubanfm-300x124.png" alt="" title="doubanfm" width="300" height="124" class="alignnone size-medium wp-image-334" /></a></p><p>平时比较喜欢听豆瓣电台的，于是加心了很多歌曲，和很多人一样都想把加心的歌曲下载到本地。毕竟豆瓣电台并不会循环播放你的加心歌曲的，于是搜了一下，发现网上只是通过某些手段获得加心歌曲的列表，然后再用其他的工具下载，这里有很多弊端，比如可能会有歌名一样的情况，而且有些小众歌曲无法或者说很难在网上搜到，于是就写了这个用于直接在豆瓣网上下载加心歌曲的小程序。</p><p><span id="more-330"></span></p><p>注意到加心的歌曲其实都是对应到某个专辑上的，并且我们可以让我们喜欢的专辑开始播放利用这个地址<a href="http://douban.fm/?context=channel:0|subject_id:2781176">http://douban.fm/?context=channel:0|subject_id:2781176</a></p><p>然后手动的话就可以通过抓包来获取你想要的歌曲下载地址了，把这一系列动作写成程序就可以自动下载所有加心歌曲了。</p><p>程序使用了BeautifulSoup，可以在这里下载<a href="http://www.crummy.com/software/BeautifulSoup/#Download">http://www.crummy.com/software/BeautifulSoup/#Download</a>下载BeautifulSoup.py文件和本程序放在同一目录下即可。</p><p>下面是程序：</p><div class="geshi no python"><ol><li class="li1"><div class="de1"><span class="co1"># coding: utf-8</span></div></li><li class="li1"><div class="de1">&nbsp;</div></li><li class="li1"><div class="de1"><span class="kw1">from</span> BeautifulSoup <span class="kw1">import</span> BeautifulSoup</div></li><li class="li1"><div class="de1"><span class="kw1">import</span> <span class="kw3">urllib</span>,<span class="kw3">urllib2</span>,<span class="kw3">cookielib</span>,<span class="kw3">re</span></div></li><li class="li1"><div class="de1">&nbsp;</div></li><li class="li1"><div class="de1"><span class="kw1">def</span> handle<span class="br0">&#40;</span>s<span class="br0">&#41;</span>:</div></li><li class="li1"><div class="de1">&nbsp; &nbsp; <span class="kw1">return</span> s.<span class="me1">replace</span><span class="br0">&#40;</span><span class="st0">&quot;&amp;lt;&quot;</span>,<span class="st0">&quot;&lt;&quot;</span><span class="br0">&#41;</span>.<span class="me1">replace</span><span class="br0">&#40;</span><span class="st0">&quot;&amp;gt;&quot;</span>,<span class="st0">&quot;&gt;&quot;</span><span class="br0">&#41;</span>.<span class="me1">replace</span><span class="br0">&#40;</span><span class="st0">&quot;<span class="es0">\\</span>&quot;</span>,<span class="st0">&quot;&quot;</span><span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp;</div></li><li class="li1"><div class="de1"><span class="kw1">def</span> fhandle<span class="br0">&#40;</span>s<span class="br0">&#41;</span>:</div></li><li class="li1"><div class="de1">&nbsp; &nbsp; <span class="kw1">return</span> s.<span class="me1">replace</span><span class="br0">&#40;</span><span class="st0">&quot;/&quot;</span>,<span class="st0">&quot;and&quot;</span><span class="br0">&#41;</span>.<span class="me1">replace</span><span class="br0">&#40;</span><span class="st0">&quot; &quot;</span>,<span class="st0">&quot;&quot;</span><span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">&nbsp;</div></li><li class="li1"><div class="de1"><span class="kw1">def</span> get<span class="br0">&#40;</span>myurl,cookie<span class="br0">&#41;</span>:</div></li><li class="li1"><div class="de1">&nbsp; &nbsp; url2=<span class="st0">&quot;http://douban.fm/j/mine/playlist?type=n&amp;h=&amp;channel=0&amp;context=channel:0|subject_id:%d&quot;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; opener = <span class="kw3">urllib2</span>.<span class="me1">build_opener</span><span class="br0">&#40;</span><span class="kw3">urllib2</span>.<span class="me1">HTTPCookieProcessor</span><span class="br0">&#40;</span><span class="kw3">cookielib</span>.<span class="me1">CookieJar</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; <span class="kw3">urllib2</span>.<span class="me1">install_opener</span><span class="br0">&#40;</span>opener<span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; req=<span class="kw3">urllib2</span>.<span class="me1">Request</span><span class="br0">&#40;</span>myurl<span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; req.<span class="me1">add_header</span><span class="br0">&#40;</span><span class="st0">&#39;User-Agent&#39;</span>,<span class="st0">&#39;Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)&#39;</span><span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; req.<span class="me1">add_header</span><span class="br0">&#40;</span><span class="st0">&#39;Cookie&#39;</span>,cookie<span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; content=<span class="kw3">urllib2</span>.<span class="me1">urlopen</span><span class="br0">&#40;</span>req<span class="br0">&#41;</span>.<span class="me1">read</span><span class="br0">&#40;</span><span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; soup=BeautifulSoup<span class="br0">&#40;</span><span class="kw2">str</span><span class="br0">&#40;</span>content<span class="br0">&#41;</span><span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; soup=soup.<span class="me1">find</span><span class="br0">&#40;</span><span class="st0">&quot;div&quot;</span>, <span class="br0">&#123;</span> <span class="st0">&quot;id&quot;</span> : <span class="st0">&quot;record_viewer&quot;</span> <span class="br0">&#125;</span><span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; <span class="kw1">for</span> div <span class="kw1">in</span> soup.<span class="me1">findAll</span><span class="br0">&#40;</span><span class="st0">&quot;div&quot;</span>, <span class="br0">&#123;</span> <span class="st0">&quot;class&quot;</span> : <span class="st0">&quot;info_wrapper&quot;</span> <span class="br0">&#125;</span><span class="br0">&#41;</span>:</div></li><li class="li1"><div class="de1">&nbsp; &nbsp; &nbsp; div=div.<span class="me1">find</span><span class="br0">&#40;</span><span class="st0">&quot;div&quot;</span>,<span class="br0">&#123;</span> <span class="st0">&quot;class&quot;</span> : <span class="st0">&quot;song_info&quot;</span> <span class="br0">&#125;</span><span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; &nbsp; a=div.<span class="me1">contents</span><span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; &nbsp; p1,p2,p3=div.<span class="me1">contents</span><span class="br0">&#91;</span><span class="nu0">3</span><span class="br0">&#93;</span>.<span class="me1">findAll</span><span class="br0">&#40;</span><span class="st0">&quot;p&quot;</span><span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; &nbsp; <span class="kw1">print</span> a<span class="br0">&#91;</span><span class="st0">&quot;href&quot;</span><span class="br0">&#93;</span>+<span class="st0">&quot;<span class="es0">\n</span>song:&quot;</span>+handle<span class="br0">&#40;</span>p1.<span class="kw3">string</span><span class="br0">&#41;</span>+<span class="st0">&quot;<span class="es0">\n</span>singer:&quot;</span>+handle<span class="br0">&#40;</span>p2.<span class="kw3">string</span><span class="br0">&#41;</span>+<span class="st0">&quot;<span class="es0">\n</span>album:&quot;</span>+handle<span class="br0">&#40;</span>p3.<span class="me1">a</span>.<span class="kw3">string</span><span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; &nbsp; p=<span class="kw3">re</span>.<span class="kw2">compile</span><span class="br0">&#40;</span>r<span class="st0">&#39;(<span class="es0">\d</span>+)&#39;</span><span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; &nbsp; m=p.<span class="me1">search</span><span class="br0">&#40;</span>a<span class="br0">&#91;</span><span class="st0">&quot;href&quot;</span><span class="br0">&#93;</span><span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; &nbsp; num=<span class="kw2">int</span><span class="br0">&#40;</span>m.<span class="me1">groups</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span><span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; &nbsp; url3=url2<span class="sy0">%</span>num</div></li><li class="li1"><div class="de1">&nbsp; &nbsp; &nbsp; <span class="kw1">print</span> url3</div></li><li class="li1"><div class="de1">&nbsp; &nbsp; &nbsp; mark=<span class="kw2">False</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; &nbsp; <span class="kw1">try</span>:</div></li><li class="li1"><div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">for</span> j <span class="kw1">in</span> <span class="kw2">range</span><span class="br0">&#40;</span><span class="nu0">100</span><span class="br0">&#41;</span>:</div></li><li class="li1"><div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; content=<span class="kw3">urllib2</span>.<span class="me1">urlopen</span><span class="br0">&#40;</span>url3<span class="br0">&#41;</span>.<span class="me1">read</span><span class="br0">&#40;</span><span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; c=<span class="kw2">eval</span><span class="br0">&#40;</span>content<span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; c=c<span class="br0">&#91;</span><span class="st0">&#39;song&#39;</span><span class="br0">&#93;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">for</span> i <span class="kw1">in</span> c:</div></li><li class="li1"><div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="kw2">unicode</span><span class="br0">&#40;</span><span class="kw2">str</span><span class="br0">&#40;</span>i<span class="br0">&#91;</span><span class="st0">&#39;title&#39;</span><span class="br0">&#93;</span><span class="br0">&#41;</span>,<span class="st0">&#39;utf-8&#39;</span><span class="br0">&#41;</span>==handle<span class="br0">&#40;</span>p1.<span class="kw3">string</span><span class="br0">&#41;</span>:</div></li><li class="li1"><div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">urllib</span>.<span class="me1">urlretrieve</span><span class="br0">&#40;</span>i<span class="br0">&#91;</span><span class="st0">&#39;url&#39;</span><span class="br0">&#93;</span>.<span class="me1">replace</span><span class="br0">&#40;</span><span class="st0">&#39;<span class="es0">\\</span>&#39;</span>,<span class="st0">&#39;&#39;</span><span class="br0">&#41;</span>, fhandle<span class="br0">&#40;</span>handle<span class="br0">&#40;</span>p1.<span class="kw3">string</span><span class="br0">&#41;</span><span class="br0">&#41;</span>+<span class="st0">&quot;-&quot;</span>+fhandle<span class="br0">&#40;</span>handle<span class="br0">&#40;</span>p2.<span class="kw3">string</span><span class="br0">&#41;</span><span class="br0">&#41;</span>+<span class="st0">&quot;.mp3&quot;</span><span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; mark=<span class="kw2">True</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">break</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> mark:</div></li><li class="li1"><div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">break</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> mark:</div></li><li class="li1"><div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">print</span> <span class="st0">&quot;succeed!<span class="es0">\n</span>&quot;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">else</span>: <span class="kw1">print</span> <span class="st0">&quot;fail!<span class="es0">\n</span>&quot;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; &nbsp; <span class="kw1">except</span> <span class="kw2">Exception</span> as e:</div></li><li class="li1"><div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">print</span> e.<span class="me1">message</span></div></li><li class="li1"><div class="de1">&nbsp;</div></li><li class="li1"><div class="de1"><span class="kw1">def</span> main<span class="br0">&#40;</span><span class="br0">&#41;</span>:</div></li><li class="li1"><div class="de1">&nbsp; &nbsp; url=<span class="st0">&quot;http://douban.fm/mine?start=%d&amp;type=liked&quot;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; cookie=<span class="kw2">raw_input</span><span class="br0">&#40;</span><span class="st0">&#39;cookie:&#39;</span><span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; <span class="kw1">print</span> <span class="st0">&quot;you should enter the pages you want to download&quot;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; page0=<span class="kw2">int</span><span class="br0">&#40;</span><span class="kw2">raw_input</span><span class="br0">&#40;</span><span class="st0">&#39;page from:&#39;</span><span class="br0">&#41;</span><span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; page1=<span class="kw2">int</span><span class="br0">&#40;</span><span class="kw2">raw_input</span><span class="br0">&#40;</span><span class="st0">&#39;page to:&#39;</span><span class="br0">&#41;</span><span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; <span class="kw1">for</span> i <span class="kw1">in</span> <span class="kw2">range</span><span class="br0">&#40;</span>page1-page0<span class="nu0">+1</span><span class="br0">&#41;</span>:</div></li><li class="li1"><div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; get<span class="br0">&#40;</span>url<span class="sy0">%</span><span class="br0">&#40;</span><span class="br0">&#40;</span>i+page0<span class="nu0">-1</span><span class="br0">&#41;</span><span class="sy0">*</span><span class="nu0">15</span><span class="br0">&#41;</span>,cookie<span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">&nbsp;</div></li><li class="li1"><div class="de1"><span class="kw1">if</span> __name__ == <span class="st0">&quot;__main__&quot;</span>:</div></li><li class="li1"><div class="de1">&nbsp; &nbsp; main<span class="br0">&#40;</span><span class="br0">&#41;</span></div></li></ol></div><p>然后程序需要输入你的豆瓣电台的cookie和歌曲的开始和结束的页数（稍微响应下用户需求），当然对于很多人可能不知道如何获得cookie，那下面简单说一下。</p><p>利用chrome，进入豆瓣电台的页面然后右键审查元素，切入到network标签，然后再刷新一下网页（不要忘记是在登录状态下操作哦～）</p><p><a href="http://www.isnowfy.com/wp-content/uploads/2011/11/cookie.png"><img src="http://www.isnowfy.com/wp-content/uploads/2011/11/cookie-235x300.png" alt="" title="cookie" width="235" height="300" class="alignnone size-medium wp-image-335" /></a></p><p>然后左侧选择第一个文件，在header下，如上图就可以看到你的cookie了，ok尽情的下载你的加心歌曲吧！</p><p>ps:<a href="http://scturtle.is-programmer.com/">scturtle</a>提醒说firefox下右键-查看页面信息-安全-查看cookie</p><p>pss：为了方便广大人民群众特推出<a href="http://d.yun.io/h05ncA">exe版本</a>，解压缩后点击里面的doubanfm.exe即可！<br /><strong>我猜您可能还会喜欢:</strong><ul class="similar-posts"><li><a href="http://www.isnowfy.com/introduction-to-gevent/" rel="bookmark" title="2011 年 12 月 21 日">gevent初步</a></li><li><a href="http://www.isnowfy.com/lucene-build-search/" rel="bookmark" title="2011 年 07 月 10 日">lucene3.2 简单的建立索引和查询</a></li><li><a href="http://www.isnowfy.com/dns-frame/" rel="bookmark" title="2011 年 07 月 10 日">DNS帧的格式</a></li><li><a href="http://www.isnowfy.com/wordpress-hotlink-protection/" rel="bookmark" title="2011 年 07 月 08 日">wordpress防盗链</a></li><li><a href="http://www.isnowfy.com/wordpress-optimization/" rel="bookmark" title="2011 年 08 月 16 日">又折腾了一把wordpress</a></li><li><a href="http://www.isnowfy.com/libcurl-fetch-webpage/" rel="bookmark" title="2011 年 08 月 27 日">c中使用libcurl抓取网页</a></li><li><a href="http://www.isnowfy.com/android-sign-and-google-map-api/" rel="bookmark" title="2011 年 07 月 22 日">关于android应用签名以及google map api的申请和使用</a></li></ul><p></p> ]]></content:encoded> <wfw:commentRss>http://www.isnowfy.com/download-doubanfm-songs/feed/</wfw:commentRss> <slash:comments>26</slash:comments> </item> <item><title>machine learning公开课的字幕获取脚本</title><link>http://www.isnowfy.com/machine-learning-subtitle-script/</link> <comments>http://www.isnowfy.com/machine-learning-subtitle-script/#comments</comments> <pubDate>Tue, 11 Oct 2011 02:53:13 +0000</pubDate> <dc:creator>isnowfy</dc:creator> <category><![CDATA[program]]></category> <category><![CDATA[machine learning]]></category> <category><![CDATA[python]]></category> <category><![CDATA[script]]></category><guid isPermaLink="false">http://www.isnowfy.com/?p=313</guid> <description><![CDATA[话说10月10日斯坦福开始的machine learning很有意思，网站在这，而且视频可以下载，观看起来非常方便，但是有个问题就是下载下来的视频没有字幕，而从网上的视频有字幕，于是可以写个程序将字幕搞下来。 感谢scturtle提供的最初的脚本程序 下面是我经过修改的精简版，只要输入视频的文件名（名字中不要有后缀名）就可以下载字幕了 # coding: utf-8 import urllib2,os import sys,re,codecs &#160; limit=&#91;60,60,60,1000&#93; def xml2srt&#40;fi,fo&#41;: &#160; &#160; data=&#39;&#39;.join&#40;&#40;fi.split&#40;&#39;\n&#39;&#41;&#91;9:-4&#93;&#41;&#41;.strip&#40;&#41;.split&#40;&#39;&#60;/p&#62;&#39;&#41; &#160; &#160; for i in range&#40;0,len&#40;data&#41;-1&#41;: &#160; &#160; &#160; &#160; if data&#91;i&#93;: &#160; &#160; &#160; &#160; &#160; &#160; st_st=data&#91;i&#93;.index&#40;&#39;&#34;&#39;&#41; &#160; &#160; &#160; &#8230; <a href="http://www.isnowfy.com/machine-learning-subtitle-script/">继续阅读 <span class="meta-nav">&#8594;</span></a>]]></description> <content:encoded><![CDATA[<p><a href="http://www.isnowfy.com/wp-content/uploads/2011/10/ml.jpg"><img src="http://www.isnowfy.com/wp-content/uploads/2011/10/ml-300x100.jpg" alt="" title="ml" width="300" height="100" class="alignnone size-medium wp-image-314" /></a><br /> 话说10月10日斯坦福开始的machine learning很有意思，<a href="http://www.ml-class.org">网站</a>在这，而且视频可以下载，观看起来非常方便，但是有个问题就是下载下来的视频没有字幕，而从网上的视频有字幕，于是可以写个程序将字幕搞下来。<br /> <span id="more-313"></span><br /> 感谢<a href="http://scturtle.is-programmer.com/posts/30120">scturtle</a>提供的最初的脚本程序</p><p>下面是我经过修改的精简版，只要输入视频的文件名（名字中不要有后缀名）就可以下载字幕了</p><div class="geshi no python"><ol><li class="li1"><div class="de1"><span class="co1"># coding: utf-8</span></div></li><li class="li1"><div class="de1"><span class="kw1">import</span> <span class="kw3">urllib2</span>,<span class="kw3">os</span></div></li><li class="li1"><div class="de1"><span class="kw1">import</span> <span class="kw3">sys</span>,<span class="kw3">re</span>,<span class="kw3">codecs</span></div></li><li class="li1"><div class="de1">&nbsp;</div></li><li class="li1"><div class="de1">limit=<span class="br0">&#91;</span><span class="nu0">60</span>,<span class="nu0">60</span>,<span class="nu0">60</span>,<span class="nu0">1000</span><span class="br0">&#93;</span></div></li><li class="li1"><div class="de1"><span class="kw1">def</span> xml2srt<span class="br0">&#40;</span>fi,fo<span class="br0">&#41;</span>:</div></li><li class="li1"><div class="de1">&nbsp; &nbsp; data=<span class="st0">&#39;&#39;</span>.<span class="me1">join</span><span class="br0">&#40;</span><span class="br0">&#40;</span>fi.<span class="me1">split</span><span class="br0">&#40;</span><span class="st0">&#39;<span class="es0">\n</span>&#39;</span><span class="br0">&#41;</span><span class="br0">&#91;</span><span class="nu0">9</span>:<span class="nu0">-4</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>.<span class="me1">strip</span><span class="br0">&#40;</span><span class="br0">&#41;</span>.<span class="me1">split</span><span class="br0">&#40;</span><span class="st0">&#39;&lt;/p&gt;&#39;</span><span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; <span class="kw1">for</span> i <span class="kw1">in</span> <span class="kw2">range</span><span class="br0">&#40;</span><span class="nu0">0</span>,<span class="kw2">len</span><span class="br0">&#40;</span>data<span class="br0">&#41;</span><span class="nu0">-1</span><span class="br0">&#41;</span>:</div></li><li class="li1"><div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> data<span class="br0">&#91;</span>i<span class="br0">&#93;</span>:</div></li><li class="li1"><div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; st_st=data<span class="br0">&#91;</span>i<span class="br0">&#93;</span>.<span class="me1">index</span><span class="br0">&#40;</span><span class="st0">&#39;&quot;&#39;</span><span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; st_ed=data<span class="br0">&#91;</span>i<span class="br0">&#93;</span>.<span class="me1">index</span><span class="br0">&#40;</span><span class="st0">&#39;&quot;&#39;</span>,st_st<span class="nu0">+1</span><span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> i<span class="nu0">+1</span><span class="sy0">&lt;</span>len<span class="br0">&#40;</span>data<span class="br0">&#41;</span><span class="nu0">-1</span>:</div></li><li class="li1"><div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; nx_st=data<span class="br0">&#91;</span>i<span class="nu0">+1</span><span class="br0">&#93;</span>.<span class="me1">index</span><span class="br0">&#40;</span><span class="st0">&#39;&quot;&#39;</span><span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; nx_ed=data<span class="br0">&#91;</span>i<span class="nu0">+1</span><span class="br0">&#93;</span>.<span class="me1">index</span><span class="br0">&#40;</span><span class="st0">&#39;&quot;&#39;</span>,nx_st<span class="nu0">+1</span><span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fo.<span class="me1">write</span><span class="br0">&#40;</span><span class="kw2">str</span><span class="br0">&#40;</span>i<span class="nu0">+1</span><span class="br0">&#41;</span>+<span class="st0">&#39; <span class="es0">\n</span>&#39;</span><span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; stamps=<span class="br0">&#91;</span>data<span class="br0">&#91;</span>i<span class="br0">&#93;</span><span class="br0">&#91;</span>st_st<span class="nu0">+1</span>:st_ed<span class="br0">&#93;</span>,</div></li><li class="li1"><div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; data<span class="br0">&#91;</span>i<span class="nu0">+1</span><span class="br0">&#93;</span><span class="br0">&#91;</span>nx_st<span class="nu0">+1</span>:nx_ed<span class="br0">&#93;</span> <span class="kw1">if</span> i<span class="nu0">+1</span><span class="sy0">&lt;</span>len<span class="br0">&#40;</span>data<span class="br0">&#41;</span><span class="nu0">-1</span> <span class="kw1">else</span> <span class="st0">&quot;99:59:59.999&quot;</span><span class="br0">&#93;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; word=data<span class="br0">&#91;</span>i<span class="br0">&#93;</span><span class="br0">&#91;</span>data<span class="br0">&#91;</span>i<span class="br0">&#93;</span>.<span class="me1">index</span><span class="br0">&#40;</span><span class="st0">&#39;&gt;&#39;</span><span class="br0">&#41;</span><span class="nu0">+1</span>:<span class="br0">&#93;</span>.<span class="me1">replace</span><span class="br0">&#40;</span><span class="st0">&#39;<span class="es0">\n</span>&#39;</span>,<span class="st0">&#39; &#39;</span><span class="br0">&#41;</span>+<span class="st0">&#39; <span class="es0">\n</span><span class="es0">\n</span><span class="es0">\n</span>&#39;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">for</span> i,stamp <span class="kw1">in</span> <span class="kw2">enumerate</span><span class="br0">&#40;</span>stamps<span class="br0">&#41;</span>:</div></li><li class="li1"><div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; stamp=stamp.<span class="me1">split</span><span class="br0">&#40;</span><span class="st0">&#39;.&#39;</span><span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; stamps<span class="br0">&#91;</span>i<span class="br0">&#93;</span>=<span class="kw2">map</span><span class="br0">&#40;</span><span class="kw2">int</span>,stamp<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span>.<span class="me1">split</span><span class="br0">&#40;</span><span class="st0">&#39;:&#39;</span><span class="br0">&#41;</span><span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; stamps<span class="br0">&#91;</span>i<span class="br0">&#93;</span>.<span class="me1">append</span><span class="br0">&#40;</span><span class="kw2">int</span><span class="br0">&#40;</span>stamp<span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; stamps=<span class="kw2">map</span><span class="br0">&#40;</span><span class="kw1">lambda</span> s:<span class="st0">&quot;%02d:%02d:%02d,%03d&quot;</span> <span class="sy0">%</span> <span class="kw2">tuple</span><span class="br0">&#40;</span>s<span class="br0">&#41;</span>,stamps<span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fo.<span class="me1">write</span><span class="br0">&#40;</span><span class="st0">&quot;%s --&gt; %s <span class="es0">\n</span>&quot;</span> <span class="sy0">%</span> <span class="kw2">tuple</span><span class="br0">&#40;</span>stamps<span class="br0">&#41;</span><span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fo.<span class="me1">write</span><span class="br0">&#40;</span>word<span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; <span class="kw1">print</span> <span class="st0">&#39;OK!&#39;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp;</div></li><li class="li1"><div class="de1">baseurl=<span class="st0">&#39;http://s3.amazonaws.com/stanford_videos/cs229/subtitles/%s-subtitles.xml&#39;</span></div></li><li class="li1"><div class="de1">fn=<span class="kw2">raw_input</span><span class="br0">&#40;</span><span class="st0">&#39;file name:&#39;</span><span class="br0">&#41;</span></div></li><li class="li1"><div class="de1"><span class="kw1">if</span> <span class="kw3">os</span>.<span class="me1">path</span>.<span class="me1">exists</span><span class="br0">&#40;</span>fn+<span class="st0">&#39;.srt&#39;</span><span class="br0">&#41;</span>:</div></li><li class="li1"><div class="de1">&nbsp; &nbsp; <span class="kw1">print</span> <span class="st0">&#39;file exit!&#39;</span></div></li><li class="li1"><div class="de1">&nbsp; &nbsp; exit<span class="br0">&#40;</span><span class="nu0">0</span><span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">fi=<span class="kw3">urllib2</span>.<span class="me1">urlopen</span><span class="br0">&#40;</span>baseurl <span class="sy0">%</span> fn<span class="br0">&#41;</span>.<span class="me1">read</span><span class="br0">&#40;</span><span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">fo=<span class="kw2">file</span><span class="br0">&#40;</span>fn+<span class="st0">&#39;.srt&#39;</span>,<span class="st0">&#39;w&#39;</span><span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">xml2srt<span class="br0">&#40;</span>fi,fo<span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">fo.<span class="me1">close</span><span class="br0">&#40;</span><span class="br0">&#41;</span></div></li><li class="li1"><div class="de1"><span class="kw1">print</span> <span class="st0">&#39;Done&#39;</span></div></li></ol></div><p>为了方便使用，我还制作了windows下可执行的exe的程序，直接运行run.exe输入视频名就可以了，<a href="http://dl.dbank.com/c0ca0lp4d8">这里</a>下载<br /><strong>我猜您可能还会喜欢:</strong><ul class="similar-posts"><li><a href="http://www.isnowfy.com/download-doubanfm-songs/" rel="bookmark" title="2011 年 11 月 13 日">自动下载豆瓣FM的加心歌曲</a></li><li><a href="http://www.isnowfy.com/python-chinese-segmentation/" rel="bookmark" title="2012 年 03 月 17 日">python中文分词</a></li><li><a href="http://www.isnowfy.com/introduction-to-gevent/" rel="bookmark" title="2011 年 12 月 21 日">gevent初步</a></li><li><a href="http://www.isnowfy.com/lucene-build-search/" rel="bookmark" title="2011 年 07 月 10 日">lucene3.2 简单的建立索引和查询</a></li><li><a href="http://www.isnowfy.com/similar-image-search/" rel="bookmark" title="2011 年 09 月 04 日">关于相似图片搜索</a></li><li><a href="http://www.isnowfy.com/android-sign-and-google-map-api/" rel="bookmark" title="2011 年 07 月 22 日">关于android应用签名以及google map api的申请和使用</a></li><li><a href="http://www.isnowfy.com/libcurl-fetch-webpage/" rel="bookmark" title="2011 年 08 月 27 日">c中使用libcurl抓取网页</a></li></ul><p></p> ]]></content:encoded> <wfw:commentRss>http://www.isnowfy.com/machine-learning-subtitle-script/feed/</wfw:commentRss> <slash:comments>5</slash:comments> </item> <item><title>网络涂鸦板</title><link>http://www.isnowfy.com/web-paint/</link> <comments>http://www.isnowfy.com/web-paint/#comments</comments> <pubDate>Mon, 03 Oct 2011 15:08:58 +0000</pubDate> <dc:creator>isnowfy</dc:creator> <category><![CDATA[web]]></category> <category><![CDATA[comet]]></category> <category><![CDATA[jquery]]></category><guid isPermaLink="false">http://www.isnowfy.com/?p=301</guid> <description><![CDATA[之前写这篇文章的时候，就是本来打算写一个有网络涂鸦板功能的web群聊，不过涂鸦板一直是拖到现在才实现，鉴于现在实现的不是很完美就没有把它们合一起了，可以在这里看到效果。 这个网络涂鸦板，是所有人都能看到其他人画了什么，是实时同步的，刷新后就重置了。就是说比如你可以和你的朋友都打开这个页面，然后你绘制的情况，你的朋友也会看到。 注意到网址里其实有个id=1的东西，就是说这个你可以随便写个数字，就相当于创建一个房间了，不同房间的涂鸦板互不影响的。简单来说一下实现吧。 正如开头的图片显示的那样，主要的技术是利用了html5的canvas来绘图的，非常方便，然后整个绘图其实就是在绘制一段一段的线段，然后这是绘制一段线段的写法。 function draw&#40;x1,y1,x2,y2&#41;&#123; context.strokeStyle = &#34;#FF0000&#34;; context.lineJoin = &#34;round&#34;; context.lineWidth = 3; context.beginPath&#40;&#41;; context.moveTo&#40;x1, y1&#41;; context.lineTo&#40;x2, y2&#41;; context.closePath&#40;&#41;; context.stroke&#40;&#41;; &#125; 可以指定画笔的颜色和粗细，非常的方便，基本绘制出来是这个样子的。 然后利用jquery，给鼠标事件加入了监听，使得移动鼠标时坐标位置会被记录下来。mousedown，mousemove和mouseup基本就能搞定涂鸦板了，至于剩下的就是利用原来使用过的comet长连接了，这样网络涂鸦板就算完成了。 不过毕竟是基于http的，而且每次绘制过长都需要传输大量的坐标信息，这样每次都需要http连接，进行三次握手，所以绘制起来，同步不是很流畅，相对于websocket来说建立连接可以一直保持还是有很多劣势的，所以既然都用了html5的canvas，过段时间也来看看websocket吧，这样会使得流畅很多呢。我猜您可能还会喜欢: 利用comet技术实现web聊天 拼写纠正 wordpress防盗链 自动下载豆瓣FM的加心歌曲 关于相似图片搜索 wordpress带有缩略图的相关文章插件 c中使用libcurl抓取网页]]></description> <content:encoded><![CDATA[<p><a href="http://www.isnowfy.com/wp-content/uploads/2011/10/HTML5-canvas1.jpg"><img src="http://www.isnowfy.com/wp-content/uploads/2011/10/HTML5-canvas1.jpg" alt="" title="HTML5-canvas" width="205" height="205" class="alignnone size-full wp-image-303" /></a></p><p>之前写<a href="http://www.isnowfy.com/comet-web-chat/">这篇文章</a>的时候，就是本来打算写一个有网络涂鸦板功能的web群聊，不过涂鸦板一直是拖到现在才实现，鉴于现在实现的不是很完美就没有把它们合一起了，可以在<a href="http://paint.isnowfy.com/index.php?id=1">这里</a>看到效果。<br /> <span id="more-301"></span></p><p>这个网络涂鸦板，是所有人都能看到其他人画了什么，是实时同步的，刷新后就重置了。就是说比如你可以和你的朋友都打开这个页面，然后你绘制的情况，你的朋友也会看到。</p><p>注意到网址里其实有个id=1的东西，就是说这个你可以随便写个数字，就相当于创建一个房间了，不同房间的涂鸦板互不影响的。简单来说一下实现吧。</p><p>正如开头的图片显示的那样，主要的技术是利用了html5的canvas来绘图的，非常方便，然后整个绘图其实就是在绘制一段一段的线段，然后这是绘制一段线段的写法。</p><div class="geshi no javascript"><ol><li class="li1"><div class="de1"><span class="kw2">function</span> draw<span class="br0">&#40;</span>x1,y1,x2,y2<span class="br0">&#41;</span><span class="br0">&#123;</span></div></li><li class="li1"><div class="de1">context.<span class="me1">strokeStyle</span> = <span class="st0">&quot;#FF0000&quot;</span>;</div></li><li class="li1"><div class="de1">context.<span class="me1">lineJoin</span> = <span class="st0">&quot;round&quot;</span>;</div></li><li class="li1"><div class="de1">context.<span class="me1">lineWidth</span> = <span class="nu0">3</span>;</div></li><li class="li1"><div class="de1">context.<span class="me1">beginPath</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;</div></li><li class="li1"><div class="de1">context.<span class="me1">moveTo</span><span class="br0">&#40;</span>x1, y1<span class="br0">&#41;</span>;</div></li><li class="li1"><div class="de1">context.<span class="me1">lineTo</span><span class="br0">&#40;</span>x2, y2<span class="br0">&#41;</span>;</div></li><li class="li1"><div class="de1">context.<span class="me1">closePath</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;</div></li><li class="li1"><div class="de1">context.<span class="me1">stroke</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;</div></li><li class="li1"><div class="de1"><span class="br0">&#125;</span></div></li></ol></div><p>可以指定画笔的颜色和粗细，非常的方便，基本绘制出来是这个样子的。</p><p><a href="http://www.isnowfy.com/wp-content/uploads/2011/10/hello.png"><img src="http://www.isnowfy.com/wp-content/uploads/2011/10/hello-300x169.png" alt="" title="hello" width="300" height="169" class="alignnone size-medium wp-image-307" /></a></p><p>然后利用jquery，给鼠标事件加入了监听，使得移动鼠标时坐标位置会被记录下来。mousedown，mousemove和mouseup基本就能搞定涂鸦板了，至于剩下的就是利用原来使用过的comet长连接了，这样网络涂鸦板就算完成了。</p><p>不过毕竟是基于http的，而且每次绘制过长都需要传输大量的坐标信息，这样每次都需要http连接，进行三次握手，所以绘制起来，同步不是很流畅，相对于websocket来说建立连接可以一直保持还是有很多劣势的，所以既然都用了html5的canvas，过段时间也来看看websocket吧，这样会使得流畅很多呢。<br /><strong>我猜您可能还会喜欢:</strong><ul class="similar-posts"><li><a href="http://www.isnowfy.com/comet-web-chat/" rel="bookmark" title="2011 年 08 月 05 日">利用comet技术实现web聊天</a></li><li><a href="http://www.isnowfy.com/spell-correct/" rel="bookmark" title="2011 年 08 月 14 日">拼写纠正</a></li><li><a href="http://www.isnowfy.com/wordpress-hotlink-protection/" rel="bookmark" title="2011 年 07 月 08 日">wordpress防盗链</a></li><li><a href="http://www.isnowfy.com/download-doubanfm-songs/" rel="bookmark" title="2011 年 11 月 13 日">自动下载豆瓣FM的加心歌曲</a></li><li><a href="http://www.isnowfy.com/similar-image-search/" rel="bookmark" title="2011 年 09 月 04 日">关于相似图片搜索</a></li><li><a href="http://www.isnowfy.com/wordpress-my-related-posts-plugin/" rel="bookmark" title="2011 年 08 月 18 日">wordpress带有缩略图的相关文章插件</a></li><li><a href="http://www.isnowfy.com/libcurl-fetch-webpage/" rel="bookmark" title="2011 年 08 月 27 日">c中使用libcurl抓取网页</a></li></ul><p></p> ]]></content:encoded> <wfw:commentRss>http://www.isnowfy.com/web-paint/feed/</wfw:commentRss> <slash:comments>4</slash:comments> </item> </channel> </rss>
<!-- Performance optimized by W3 Total Cache. Learn more: http://www.w3-edge.com/wordpress-plugins/

Minified using disk: basic
Page Caching using disk: enhanced
Database Caching 20/79 queries in 0.039 seconds using disk: basic
Object Caching 1713/1810 objects using disk: basic

Served from: www.isnowfy.com @ 2012-05-20 07:09:26 -->
