消息解析类型能读取自动分组的正则表达式 分组 捕获分组吗

&figure&&img src=&https://pic3.zhimg.com/v2-7ce2dbb9fa6738adad07629_b.jpg& data-rawwidth=&592& data-rawheight=&302& class=&origin_image zh-lightbox-thumb& width=&592& data-original=&https://pic3.zhimg.com/v2-7ce2dbb9fa6738adad07629_r.jpg&&&/figure&&p&类似的东西在&a href=&https://zhuanlan.zhihu.com/p/& class=&internal&&Python · 神经网络(七)· CNN&/a&里面说过,但我觉得还是单独开一章来讲会更清晰一点;以及我接触 CNN 的时间非常有限,如果本文有讲得不对的地方、还望观众老爷们不吝指出 ( σ'ω')σ&/p&&p&(感谢评论区&a href=&http://www.zhihu.com/people/21d9ee2bcb9& data-hash=&21d9ee2bcb9& class=&member_mention& data-editable=&true& data-title=&@齐显东& data-hovercard=&p$b$21d9ee2bcb9&&@齐显东&/a& 的建议,我把一些我认为比较关键的地方进行了加粗处理)&br&&/p&&h2&CNN 的思想&br&&/h2&&p&从名字也可以看出、卷积神经网络(CNN)其实是神经网络(NN)的一种拓展,而事实上从结构上来说,朴素的 CNN 和朴素的 NN 没有任何区别(当然,引入了特殊结构的、复杂的 CNN 会和 NN 有着比较大的区别)。本章我们主要会说一下 CNN 的思想以及它到底在 NN 的基础上做了哪些改进,同时也会说一下 CNN 能够解决的任务类型&/p&&p&CNN 的主要思想可以概括为如下两点:&/p&&ul&&li&局部连接(Sparse Connectivity)&/li&&li&权值共享(Shared Weights)&/li&&/ul&&p&它们有很好直观。举个栗子,我们平时四处看风景时,都是“一块一块”来看的、信息也都是“一块一块”地接收的(所谓的【局部感受野】)。在这个过程中,我们的思想在看的过程中通常是不怎么变的、而在看完后可能会发出“啊这风景好美”的感慨、然后可能会根据这个感慨来调整我们的思想。在这个栗子中,那“一块一块”的风景就是&b&局部连接&/b&,我们的思想就是&b&权值&/b&。我们在看风景时用的都是自己的思想,这就是权值共享的生物学意义(注:这个栗子是我开脑洞开出来的、&b&完全不能保证其学术严谨性&/b&、还请各位观众老爷们带着批判的眼光去看待它……如果有这方面专长的观众老爷发现我完全就在瞎扯淡、还望不吝指出 ( σ'ω')σ)&/p&&p&光用文字叙述可能还是有些懵懂,我来画张图(参考了一张被引用烂了的图;但由于原图有一定的误导性、所以还是打算自己画一个)(虽然很丑):&/p&&p&&figure&&img src=&https://pic4.zhimg.com/v2-910cd9009edccf519dbd1b27d0b3d667_b.png& data-rawwidth=&947& data-rawheight=&434& class=&origin_image zh-lightbox-thumb& width=&947& data-original=&https://pic4.zhimg.com/v2-910cd9009edccf519dbd1b27d0b3d667_r.jpg&&&/figure&这张图比较了 NN 和 CNN 的思想差别。左图为 NN,可以看到它在处理输入时是&b&全连接的&/b&、亦即它采用的是&b&全局感受野&/b&,同时各个神经元又是相对独立的、这直接导致它难以将原数据样本翻译成一个“视野”。而正如上面所说,CNN
采用的是&b&局部感受野 +
共享权值&/b&,这在右图中的表现为它的神经元可以看成是“一整块”的“视野”,这块视野的每一个组成部分都是共享的权值(右图中那些又粗又长的绿线)在原数据样本的某一个局部上“看到”的东西&/p&&p&用上文中看风景的例子来说的话,CNN 的行为比较像一个正常人的表现、而 NN 的行为就更像是很多个能把整个风景都看在眼底的人同时看了同一个风景、然后分别感慨了一下并把这个感慨传递下去这种表现(???)&/p&&p&再次感谢评论区&a href=&http://www.zhihu.com/people/21d9ee2bcb9& data-hash=&21d9ee2bcb9& class=&member_mention& data-editable=&true& data-title=&@齐显东& data-hovercard=&p$b$21d9ee2bcb9&&@齐显东&/a& 举的小栗子,这里我就做一个搬运工吧:&/p&&blockquote&&p&为什么可以这样?- 因为比如一只猫的头部,一个车的棱角&pattern&只在3*3的像素格就可以表现出来,不必用全连接所有像素点去&获取信息量& &/p&&p&CNN 好处呢? - 共享参数能够显著减少参数的数量&/p&&/blockquote&&p&其中第二点在理解了下述前向传导算法后应该能比较清晰地认识到,我这里就偷个懒、不举具体的栗子了(不过如果有需求的话我还是会补上的 ( σ'ω')σ)&br&&/p&&h2&前向传导算法 &br&&/h2&&p&与 NN 相对应的,CNN 也有前向传导算法、而且与 NN 的相似之处也很多(至少从实现的层面来说它们的结构几乎一模一样)。它们之间的不同之处则主要体现在如下两点:&/p&&ul&&li&接收的输入的形式不同&/li&&li&层与层之间的连接方式不同&/li&&/ul&&p&先看第一点:对于 NN 而言、输入是一个&img src=&http://www.zhihu.com/equation?tex=N%5Ctimes+n& alt=&N\times n& eeimg=&1&&的矩阵&img src=&http://www.zhihu.com/equation?tex=X%3D%5Cleft%28+x_1%2C...%2Cx_N%5Cright%29%5ET& alt=&X=\left( x_1,...,x_N\right)^T& eeimg=&1&&,其中&img src=&http://www.zhihu.com/equation?tex=x_1%2C...%2Cx_N& alt=&x_1,...,x_N& eeimg=&1&&都是&img src=&http://www.zhihu.com/equation?tex=n%5Ctimes1& alt=&n\times1& eeimg=&1&&的列向量;当输入是图像时,NN 的处理方式是将图像拉直成一个列向量。以&img src=&http://www.zhihu.com/equation?tex=3%5Ctimes3%5Ctimes3& alt=&3\times3\times3& eeimg=&1&&的图像为例(第一个 3 代指RGB通道,后两个 3 分别是高和宽),NN 会先把各个图像变成&img src=&http://www.zhihu.com/equation?tex=27%5Ctimes1& alt=&27\times1& eeimg=&1&&的列向量(亦即&img src=&http://www.zhihu.com/equation?tex=n%3D3%5Ctimes3%5Ctimes3& alt=&n=3\times3\times3& eeimg=&1&&),然后再把它们合并、转置成一个&img src=&http://www.zhihu.com/equation?tex=N%5Ctimes27& alt=&N\times27& eeimg=&1&&的大矩阵以当作输入
&/p&&p&CNN 则不会这么大费周章——它会直接以原始的数据作为输入。换句话说、CNN 接收的输入是&img src=&http://www.zhihu.com/equation?tex=N%5Ctimes3%5Ctimes3%5Ctimes3& alt=&N\times3\times3\times3& eeimg=&1&&的矩阵&/p&&p&
可以用下图来直观认知一下该区别:&/p&&figure&&img src=&https://pic1.zhimg.com/v2-04fa196dadb29a95481cb8_b.png& data-rawwidth=&941& data-rawheight=&454& class=&origin_image zh-lightbox-thumb& width=&941& data-original=&https://pic1.zhimg.com/v2-04fa196dadb29a95481cb8_r.jpg&&&/figure&&p&所以两者的前向传导算法就可以用以下两张图来进行直观说明了(NN 在上,CNN 在下): &br&&/p&&figure&&img src=&https://pic1.zhimg.com/v2-a0d2c30a7d8e77f17ae34_b.png& data-rawwidth=&767& data-rawheight=&495& class=&origin_image zh-lightbox-thumb& width=&767& data-original=&https://pic1.zhimg.com/v2-a0d2c30a7d8e77f17ae34_r.jpg&&&/figure&&p&&figure&&img src=&https://pic2.zhimg.com/v2-8c5d58fae623cc7f3ceed11_b.png& data-rawwidth=&1598& data-rawheight=&1022& class=&origin_image zh-lightbox-thumb& width=&1598& data-original=&https://pic2.zhimg.com/v2-8c5d58fae623cc7f3ceed11_r.jpg&&&/figure&(我已经尽我全力来画得好看一点了……)&/p&&p&下面进行进一步的说明:&/p&&ul&&li&对于一个&img src=&http://www.zhihu.com/equation?tex=3%5Ctimes3%5Ctimes3& alt=&3\times3\times3& eeimg=&1&&的输入,我们可以把它拆分成 3 个&img src=&http://www.zhihu.com/equation?tex=3%5Ctimes3& alt=&3\times3& eeimg=&1&&的输入的堆叠(如果把&img src=&http://www.zhihu.com/equation?tex=3%5Ctimes3%5Ctimes3& alt=&3\times3\times3& eeimg=&1&&的输入看成是一个“图像”的话,我们可以把拆分后的 3 个输入看成是该图像的 3 个“频道”;对于原始输入来讲,这 3 个频道通常就是 RGB 通道) &/li&&li&由于 NN 是全连接的,所以输入的所有信息都会直接输入给下一层的某个神经元 &/li&&li&由于 CNN 是局部连接、共享权值的,一个合理的做法就是给拆分后的每个“频道”分配一个共享的“局部视野”(注意上面 CNN 那张图中三个“频道”中间都有 4 个相同颜色的正方形、且三个频道中正方形的颜色彼此不同,这就是局部共享视野的意义)(谁注意得到啊喂)。&b&我们通常会把这三个局部视野视为一个整体并把它称作一个 Kernel 或一个 Filter&/b&&/li&&li&上面 CNN 那张图里面我们用的是&img src=&http://www.zhihu.com/equation?tex=2%5Ctimes2& alt=&2\times2& eeimg=&1&&的局部视野,该局部视野从相应频道左上看到右上、然后看左下、最后看右下,这个过程中一共看了四次、每看一次就会生成一个输出。所以三个局部视野会分别在对应的频道上生成四个输出、亦即一个 Kernel(或说一个 Filter)会生成 3 个&img src=&http://www.zhihu.com/equation?tex=2%5Ctimes2& alt=&2\times2& eeimg=&1&&的输出,将它们直接相加就得到了该 Kernel 的最终输出——一个&img src=&http://www.zhihu.com/equation?tex=2%5Ctimes2& alt=&2\times2& eeimg=&1&&的频道
&/li&&/ul&&p&上面最后提到的“左上&img src=&http://www.zhihu.com/equation?tex=%5Crightarrow& alt=&\rightarrow& eeimg=&1&&右上&img src=&http://www.zhihu.com/equation?tex=%5Crightarrow& alt=&\rightarrow& eeimg=&1&&左下&img src=&http://www.zhihu.com/equation?tex=%5Crightarrow& alt=&\rightarrow& eeimg=&1&&右下”这个“看”的过程其实就是所谓的“卷积”,这也正是卷积神经网络名字的由来。卷积本身的数学定义要比上面这个简单的描述要繁复得多,但幸运的是、实现和应用 CNN 本身并不需要具备这方面的数学理论知识(当然如果想开发更好的 CNN 结构与算法的话、是需要进行相关研究的,不过这些都已超出我们讨论的范围了)&/p&&p&&i&&b&注意:上面 CNN 那张图中的情形为只有一个 Kernel 的情形,通常来说在实际应用中、我们会使用几十甚至几百个 Kernel 以期望网络能够学习出更好的特征——这是因为一个 Kernel 会生成一个频道,几十、几百个 Kernel 就意味着会生成几十、几百个频道,由此可以期待这大量不同的频道能够对数据进行足够强的描述(要知道原始数据可只有 3 个频道)&/b&&/i&&/p&&p&不难根据这些内容总结出 NN 和 CNN 目前为止的异同:&/p&&ul&&li&NN 和 CNN 的主要结构都是层,但是 NN 的层结构是一维的、CNN 的层结构是高维的&/li&&li& NN 处理的一般是“线性”的数据,CNN 则从直观上更适合处理“结构性的”数据&/li&&li&NN 层结构间会有权值矩阵作为连接的桥梁,&b&CNN 则没有层结构之间的权值矩阵、取而代之的是层结构本身的局部视野&/b&。该局部视野会在前向传导算法中与层结构进行卷积运算来得到结果、并会直接将这个结果(或将被激活函数作用后的结果)传给下一层。因此我们常称 NN 中的层结构为“普通层”、称 CNN 中拥有局部视野的层结构为“卷积层”&/li&&/ul&&p&可以看出、CNN 与 NN 区别之关键正在于“卷积”二字。虽然卷积的直观形式比较简单、但是它的实现却并不平凡。常用的解决方案有如下两种:&/p&&ul&&li& 将卷积步骤变换成比较大规模的矩阵相乘(cs231n 里面的 stride trick 把我看哭了……)&/li&&li& 利用快速傅里叶变换(Fast Fourier Transform,简称FFT)求解(只听说过,没实践过)&/li&&/ul&&p&然后介绍一下 Stride 和 Padding 的概念。Stride 可以翻译成“步长”,它描述了局部视野在频道上的“浏览速度”。设想现在有一个&img src=&http://www.zhihu.com/equation?tex=5%5Ctimes5& alt=&5\times5& eeimg=&1&&的频道而我们的局部视野是&img src=&http://www.zhihu.com/equation?tex=2%5Ctimes2& alt=&2\times2& eeimg=&1&&的,那么不同 Stride 下的表现将如下面两张图所示(只以第一排为例):&/p&&figure&&img src=&https://pic3.zhimg.com/v2-798a42d046dd817c3036722_b.png& data-rawwidth=&1070& data-rawheight=&606& class=&origin_image zh-lightbox-thumb& width=&1070& data-original=&https://pic3.zhimg.com/v2-798a42d046dd817c3036722_r.jpg&&&/figure&&figure&&img src=&https://pic2.zhimg.com/v2-f03e73db4f7c773a54a49_b.png& data-rawwidth=&1020& data-rawheight=&578& class=&origin_image zh-lightbox-thumb& width=&1020& data-original=&https://pic2.zhimg.com/v2-f03e73db4f7c773a54a49_r.jpg&&&/figure&&p&(……)&br&&/p&&p&可以看到上图中局部视野每次前进“一步”而下图中每次会前进“三步”&/p&&p&Padding 可以翻译成“填充”、其存在意义有许多种解释,一种最好理解的就是——它能保持输入和输出的频道形状一致。注意目前为止展示过的栗子中,输入频道在被卷积之后、输出的频道都会“缩小”一点。这样在经过相当有限的卷积操作后、输入就会变得过小而不适合再进行卷积,从而就会大大限制了整个网络结构的深度。Padding 正是这个问题的一种解决方案:它会在输入频道进行卷积之前、先在频道的周围“填充”上若干圈的“0”。设想现在有一个&img src=&http://www.zhihu.com/equation?tex=3%5Ctimes3& alt=&3\times3& eeimg=&1&&的频道而我们的局部视野也是&img src=&http://www.zhihu.com/equation?tex=3%5Ctimes3& alt=&3\times3& eeimg=&1&&的,如果按照之前所说的卷积来做的话、不难想象输出将会是&img src=&http://www.zhihu.com/equation?tex=1%5Ctimes1& alt=&1\times1& eeimg=&1&&的频道;不过如果我们将 Padding 设置为 1、亦即在输入的频道周围填充一圈 0 的话,那么卷积的表现将如下图所示:&/p&&p&&figure&&img src=&https://pic2.zhimg.com/v2-4ae81e478c0fe20320cf5_b.png& data-rawwidth=&980& data-rawheight=&496& class=&origin_image zh-lightbox-thumb& width=&980& data-original=&https://pic2.zhimg.com/v2-4ae81e478c0fe20320cf5_r.jpg&&&/figure&&br&可以看到当我们在输入频道外面 Pad 上一圈 0 之后、输出就变成&img src=&http://www.zhihu.com/equation?tex=3%5Ctimes3& alt=&3\times3& eeimg=&1&&的了,这为超深层 CNN 的搭建创造了可能性(比如有名的 ResNet)&/p&&p&在 cs231n 的&a href=&http://link.zhihu.com/?target=http%3A//cs231n.github.io/convolutional-networks/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&这篇文章&/a&里面有一张很好很好很好的动图(大概位于页面中央),请允许我偷个懒不自己动手画了…… ( σ'ω')σ&br&&/p&&h2&全连接层(Fully Connected Layer) &br&&/h2&&p&全连接层常简称为 FC,它是可能会出现在 CNN 中的、一个比较特殊的结构;从名字就可以大概猜想到、FC 应该和普通层息息相关,事实上也正是如此。直观地说、FC 是连接卷积层和普通层的普通层,它将从父层(卷积层)那里得到的高维数据铺平以作为输入、进行一些非线性变换(用激活函数作用)、然后将结果输进跟在它后面的各个普通层构成的系统中:&/p&&figure&&img src=&https://pic1.zhimg.com/v2-bd8e71e6c07bc360f9418_b.png& data-rawwidth=&1228& data-rawheight=&316& class=&origin_image zh-lightbox-thumb& width=&1228& data-original=&https://pic1.zhimg.com/v2-bd8e71e6c07bc360f9418_r.jpg&&&/figure&&p&上图中的 FC 一共有&img src=&http://www.zhihu.com/equation?tex=n_1%3D3%5Ctimes2%5Ctimes2%3D12& alt=&n_1=3\times2\times2=12& eeimg=&1&&个神经元,自 FC 之后的系统其实就是 NN。换句话说、我们可以把 CNN 拆分成如下两块结构:&/p&&ul&&li&自输入开始、至 FC 终止的“&b&卷积块&/b&”,组成卷积块的都是卷积层 &/li&&li&自 FC 开始、至输出终止的“&b&NN 块&/b&”,组成 NN 块的都是普通层&/li&&/ul&&p&&i&&b&注意:值得一提的是,在许多常见的网络结构中、NN 块里都只含有 FC &/b&&/i&&i&&b&这个普通层&/b&&/i&&/p&
&p&那么为什么 CNN 会有 FC 这个结构呢?或者问得更具体一点、为什么要将总体分成卷积块和 NN 块两部分呢?这其实从直观上来说非常好解释:卷积块中的卷积的基本单元是局部视野,用它类比我们的眼睛的话、就是将外界信息翻译成神经信号的工具,&b&它能将接收的输入中的各个特征提取出来&/b&;至于 NN(神经网络)块、则可以类比我们的神经网络(甚至说、类比我们的大脑),&b&它能够利用卷积块得到的信号(特征)来做出相应的决策&/b&。概括地说、CNN 视卷积块为“眼”而视 NN 块为“脑”,眼脑结合则决策自成(???)。用机器学习的术语来说、则卷积块为“特征提取器”而 NN 块为“决策分类器”&/p&&p&
而事实上,CNN 的强大之处其实正在于其卷积块强大的特征提取能力上、NN 块甚至可以说只是用于分类的一个附属品而已。我们完全可以利用 CNN 将特征提取出来后、用之前介绍过的决策树、支持向量机等等来进行分类这一步而无须使用 NN 块&/p&&h2&池化(Pooling) &br&&/h2&&p&池化是 NN 中完全没有的、只属于 CNN 的特殊演算。虽然名字听上去可能有些高大上的感觉,但它的本质其实就是“&b&对局部信息的总结&/b&”。常见的池化有如下两种:&/p&&ul&&li&极大池化(Max Pooling),它会输出接收到的所有输入中的最大值 &/li&&li&平均池化(Average Pooling),它会输出接收到的所有输入的均值&/li&&/ul&&p&池化过程其实与卷积过程类似、可以看成是局部视野对输入信息的转换,只不过卷积过程做的是卷积运算、池化过程做的是极大或平均(或其它)运算而已&/p&
&p&不过池化与卷积有一点通常是差异较大的——池化的 Stride 通常会比卷积的 Stride 要大。比如对于一个&img src=&http://www.zhihu.com/equation?tex=3%5Ctimes3& alt=&3\times3& eeimg=&1&&的输入频道和一个&img src=&http://www.zhihu.com/equation?tex=3%5Ctimes3& alt=&3\times3& eeimg=&1&&的局部视野而言: &/p&&ul&&li&卷积常常选取 Stride 和 Padding 都为 1,从而输出频道是&img src=&http://www.zhihu.com/equation?tex=3%5Ctimes3& alt=&3\times3& eeimg=&1&&的 &/li&&li&池化常常选取 Stride 为 2、Padding 为 1,从而输出频道是&img src=&http://www.zhihu.com/equation?tex=2%5Ctimes2& alt=&2\times2& eeimg=&1&&的&/li&&/ul&&p&将 Stride 选大是符合池化的内涵的:池化是对局部信息的总结、所以自然希望池化能够将得到的信息进行某种“压缩处理”。如果将 Stride 选得比较小的话、总结出来的信息就很可能会产生“冗余”,这就违背了池化的本意。&/p&
&p&不过为什么最常见的两种池化——极大池化和平均池化确实能够压缩信息呢?这主要是因为 CNN 一般处理的都是图像数据。由经验可知、&b&图像在像素级间隔上的差异是很小的&/b&,这就为上述两种池化提供了一定的合理性&/p&&p&以上就比较泛地说了一下 CNN 的诸多概念,可以看到我没有讲(也不打算讲)(喂)最重要的反向传播算法。这是因为 Tensorflow 能够帮我们处理梯度,所以单就使用 Tensorflow 来实现 CNN 而言、完全不用管反向传播算法应该怎么推 ( σ'ω')σ&/p&&p&不过如果我有空的话,可能会在带星号的章节中讲讲反向传播算法……&/p&&p&希望观众老爷们能够喜欢~&/p&
类似的东西在里面说过,但我觉得还是单独开一章来讲会更清晰一点;以及我接触 CNN 的时间非常有限,如果本文有讲得不对的地方、还望观众老爷们不吝指出 ( σ'ω')σ(感谢评论区 的建议,我把一些我认为比较关键的地…
&figure&&img src=&https://pic4.zhimg.com/v2-93f148a965ceac6ae337fe_b.jpg& data-rawwidth=&1620& data-rawheight=&1080& class=&origin_image zh-lightbox-thumb& width=&1620& data-original=&https://pic4.zhimg.com/v2-93f148a965ceac6ae337fe_r.jpg&&&/figure&&p&在系列文章的&a href=&https://link.zhihu.com/?target=https%3A//foofish.net/understand-http.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&第一篇&/a&中介绍了 HTTP 协议,Python 提供了很多模块来基于 HTTP 协议的网络编程,urllib、urllib2、urllib3、httplib、httplib2,都是和 HTTP 相关的模块,看名字觉得很反人类,更糟糕的是这些模块在 Python2 与 Python3 中有很大的差异,如果业务代码要同时兼容 2 和 3,写起来会让人崩溃。&/p&&br&&p&幸运地是,繁荣的 Python 社区给开发者带来了一个非常惊艳的 HTTP 库 requests,一个真正给人用的HTTP库。它是 GitHUb 关注数最多的 Python 项目之一,requests 的作者是 &em&Kenneth Reitz&/em& 大神。&/p&&p&requests 实现了 HTTP 协议中绝大部分功能,它提供的功能包括 Keep-Alive、连接池、Cookie持久化、内容自动解压、HTTP代理、SSL认证、连接超时、Session等很多特性,最重要的是它同时兼容 python2 和 python3。&/p&&h3&快速入门&/h3&&p&requests 的安装可以直接使用 pip 方法:pip install requests&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&&&& import requests
# GET 请求
&&& response = requests.get(&https://foofish.net&)
&/code&&/pre&&/div&&p&返回的时 Response 对象,Response 对象是 对 HTTP 协议中服务端返回给浏览器的响应数据的封装,响应的中的主要元素包括:状态码、原因短语、响应首部、响应体等等,这些属性都封装在Response 对象中。&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&# 状态码
&&& response.status_code
# 原因短语
&&& response.reason
# 响应首部
&&& for name,value in response.headers.items():
print(&%s:%s& % (name, value))
Content-Encoding:gzip
Server:nginx/1.10.2
Date:Thu, 06 Apr :01 GMT
# 响应内容
&&& response.content
'&html&&body&此处省略一万字...&/body&&/html&
&/code&&/pre&&/div&&p&requests 除了支持 GET 请求外,还支持 HTTP 规范中的其它所有方法,包括 POST、PUT、DELTET、HEADT、OPTIONS方法。&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&&&& r = requests.post('http://httpbin.org/post', data = {'key':'value'})
&&& r = requests.put('http://httpbin.org/put', data = {'key':'value'})
&&& r = requests.delete('http://httpbin.org/delete')
&&& r = requests.head('http://httpbin.org/get')
&&& r = requests.options('http://httpbin.org/get')
&/code&&/pre&&/div&&h3&构建请求查询参数&/h3&&p&很多URL都带有很长一串参数,我们称这些参数为URL的查询参数,用&?&附加在URL链接后面,多个参数之间用&&&隔开,比如:&a href=&https://link.zhihu.com/?target=https%3A//link.juejin.im/%3Ftarget%3Dhttp%253A%252F%252Ffav.foofish.net%252F%253Fp%253D4%2526amp%253Bs%253D20& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&http://fav.foofish.net/?p=4&s=20&/a& ,现在你可以用字典来构建查询参数:&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&&&& args = {&p&: 4, &s&: 20}
&&& response = requests.get(&http://fav.foofish.net&, params = args)
&&& response.url
'http://fav.foofish.net/?p=4&s=2'
&/code&&/pre&&/div&&h3&构建请求首部 Headers&/h3&&p&requests 可以很简单地指定请求首部字段 Headers,比如有时要指定 User-Agent 伪装成浏览器发送请求,以此来蒙骗服务器。直接传递一个字典对象给参数 headers 即可。&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&&&& r = requests.get(url, headers={'user-agent': 'Mozilla/5.0'})
&/code&&/pre&&/div&&h3&构建 POST 请求数据&/h3&&p&requests 可以非常灵活地构建 POST 请求需要的数据,如果服务器要求发送的数据是表单数据,则可以指定关键字参数 data,如果要求传递 json 格式字符串参数,则可以使用json关键字参数,参数的值都可以字典的形式传过去。&/p&&p&作为表单数据传输给服务器&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&&&& payload = {'key1': 'value1', 'key2': 'value2'}
&&& r = requests.post(&http://httpbin.org/post&, data=payload)
&/code&&/pre&&/div&&p&作为 json 格式的字符串格式传输给服务器&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&&&& import json
&&& url = 'http://httpbin.org/post'
&&& payload = {'some': 'data'}
&&& r = requests.post(url, json=payload)
&/code&&/pre&&/div&&h3&Response中的响应体&/h3&&p&HTTP返回的响应消息中很重要的一部分内容是响应体,响应体在 requests 中处理非常灵活,与响应体相关的属性有:content、text、json()。&/p&&p&content 是 byte 类型,适合直接将内容保存到文件系统或者传输到网络中&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&&&& r = requests.get(&https://pic1.zhimg.com/v2-2e92ebadb4a967829dcd7d05908ccab0_b.jpg&)
&&& type(r.content)
&class 'bytes'&
# 另存为 test.jpg
&&& with open(&test.jpg&, &wb&) as f:
f.write(r.content)
&/code&&/pre&&/div&&p&text 是 str 类型,比如一个普通的 HTML 页面,需要对文本进一步分析时,使用 text。&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&&&& r = requests.get(&https://foofish.net/understand-http.html&)
&&& type(r.text)
&class 'str'&
&&& re.compile('xxx').findall(r.text)
&/code&&/pre&&/div&&p&如果使用第三方开放平台或者API接口爬取数据时,返回的内容是json格式的数据时,那么可以直接使用json()方法返回一个经过json.loads()处理后的对象。&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&&&& r = requests.get('https://www.v2ex.com/api/topics/hot.json')
&&& r.json()
[{'id': 352833, 'title': '在长沙,父母同住...
&/code&&/pre&&/div&&h3&代理设置&/h3&&p&当爬虫频繁地对服务器进行抓取内容时,很容易被服务器屏蔽掉,因此要想继续顺利的进行爬取数据,使用代理是明智的选择。如果你想爬取墙外的数据,同样设置代理可以解决问题,requests 完美支持代理。&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&import requests
proxies = {
'http': 'http://10.10.1.10:3128',
'https': 'http://10.10.1.10:1080',
requests.get('http://example.org', proxies=proxies)
&/code&&/pre&&/div&&h3&超时设置&/h3&&p&requests 发送请求时,默认请求下线程一直阻塞,直到有响应返回才处理后面的逻辑。如果遇到服务器没有响应的情况时,问题就变得很严重了,它将导致整个应用程序一直处于阻塞状态而没法处理其他请求。&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&&&& import requests
&&& r = requests.get(&http://www.google.coma&)
...一直阻塞中
&/code&&/pre&&/div&&p&正确的方式的是给每个请求显示地指定一个超时时间。&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&&&& r = requests.get(&http://www.google.coma&, timeout=5)
Traceback (most recent call last):
socket.timeout: timed out
&/code&&/pre&&/div&&h3&Session&/h3&&p&在&a href=&https://link.zhihu.com/?target=https%3A//link.juejin.im/%3Ftarget%3Dhttps%253A%252F%252Ffoofish.net%252Funderstand-http.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&爬虫入门系列(一):快速理解HTTP协议&/a&中介绍过HTTP协议是一中无状态的协议,为了维持客户端与服务器之间的通信状态,使用 Cookie 技术使之保持双方的通信状态。&/p&&p&有些网页是需要登录才能进行爬虫操作的,而登录的原理就是浏览器首次通过用户名密码登录之后,服务器给客户端发送一个随机的Cookie,下次浏览器请求其它页面时,就把刚才的 cookie 随着请求一起发送给服务器,这样服务器就知道该用户已经是登录用户。&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&import requests
# 构建会话
= requests.Session()
# 登录url
session.post(login_url, data={username, password})
# 登录后才能访问的url
r = session.get(home_url)
session.close()
&/code&&/pre&&/div&&p&构建一个session会话之后,客户端第一次发起请求登录账户,服务器自动把cookie信息保存在session对象中,发起第二次请求时requests 自动把session中的cookie信息发送给服务器,使之保持通信状态。&/p&&h3&项目实战&/h3&&p&最后是一个实战项目,如何用 requests 实现知乎自动登录并给用户发私信,我会在下一篇文章中进行讲解,关注公众号 ‘Python之禅’。&/p&&p&延伸阅读:&/p&&ul&&li&Python实现知乎自动登录:&a href=&https://link.zhihu.com/?target=https%3A//link.juejin.im/%3Ftarget%3Dhttps%253A%252F%252Ffoofish.net%252Fpython-auto-login-zhihu.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&https://foofish.net/python-auto-login-zhihu.html&/a&&/li&&li&requests文档:&a href=&https://link.zhihu.com/?target=https%3A//link.juejin.im/%3Ftarget%3Dhttp%253A%252F%252Fdocs.python-requests.org%252Fen%252Fmaster%252F& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&http://docs.python-requests.org/en/master/&/a&&/li&&li&如何阅读 requests 源码:&a href=&https://link.zhihu.com/?target=https%3A//link.juejin.im/%3Ftarget%3Dhttps%253A%252F%252Fwww.slideshare.net%252Fonceuponatimeforever%252Flets-read-code-pythonrequests-library%253Fqid%253D9f3099df-4c9e-419a-ae62-b601f55b39f3%2526amp%253Bv%253D%2526amp%253Bb%253D%2526amp%253Bfrom_search%253D3& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&& https://www.slideshare.net/onceuponatimeforever/lets-read-code-pythonrequests-library?qid=9f3099df-4c9e-419a-ae62-b601f55b39f3&v=&b=&from_search=3&/a&&/li&&/ul&
在系列文章的中介绍了 HTTP 协议,Python 提供了很多模块来基于 HTTP 协议的网络编程,urllib、urllib2、urllib3、httplib、httplib2,都是和 HTTP 相关的模块,看名字觉得很反人类,更糟糕的是这些模块在 Python2 与 Python3 中有很大的差异,如果业…
&figure&&img src=&https://pic2.zhimg.com/v2-b78ed9ecbeddfc1106aad2a771d1fc5f_b.jpg& data-rawwidth=&900& data-rawheight=&600& class=&origin_image zh-lightbox-thumb& width=&900& data-original=&https://pic2.zhimg.com/v2-b78ed9ecbeddfc1106aad2a771d1fc5f_r.jpg&&&/figure&&h2&&b&实例1:京东商品页面的爬取&/b&&/h2&&figure&&img src=&https://pic3.zhimg.com/v2-0bfc623fe03bd_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&836& data-rawheight=&474& class=&origin_image zh-lightbox-thumb& width=&836& data-original=&https://pic3.zhimg.com/v2-0bfc623fe03bd_r.jpg&&&/figure&&figure&&img src=&https://pic2.zhimg.com/v2-b1853fbbb5e932df00504_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&839& data-rawheight=&361& class=&origin_image zh-lightbox-thumb& width=&839& data-original=&https://pic2.zhimg.com/v2-b1853fbbb5e932df00504_r.jpg&&&/figure&&figure&&img src=&https://pic1.zhimg.com/v2-cdc5dc455a0c99a88dddc3_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&628& data-rawheight=&372& class=&origin_image zh-lightbox-thumb& width=&628& data-original=&https://pic1.zhimg.com/v2-cdc5dc455a0c99a88dddc3_r.jpg&&&/figure&&p&&br&&/p&&h2&&b&实例2:亚马逊商品页面的爬取&/b&&/h2&&figure&&img src=&https://pic1.zhimg.com/v2-4836ade11abb722cc94e0a9e6395f61e_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&840& data-rawheight=&427& class=&origin_image zh-lightbox-thumb& width=&840& data-original=&https://pic1.zhimg.com/v2-4836ade11abb722cc94e0a9e6395f61e_r.jpg&&&/figure&&figure&&img src=&https://pic3.zhimg.com/v2-1c0af3e6a69bcbaf463077_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&822& data-rawheight=&482& class=&origin_image zh-lightbox-thumb& width=&822& data-original=&https://pic3.zhimg.com/v2-1c0af3e6a69bcbaf463077_r.jpg&&&/figure&&p&在爬取中,我们发现了错误,应该是网站限制了爬虫爬取,所以我们这里用user_agent字段伪装成浏览器。&/p&&figure&&img src=&https://pic2.zhimg.com/v2-49b81a866c210a0bc2ca3d756c1308d8_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&856& data-rawheight=&361& class=&origin_image zh-lightbox-thumb& width=&856& data-original=&https://pic2.zhimg.com/v2-49b81a866c210a0bc2ca3d756c1308d8_r.jpg&&&/figure&这里注意,r.request.headers返回我们程序发起http请求的header部分。&br&&figure&&img src=&https://pic1.zhimg.com/v2-1df53f92986_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&824& data-rawheight=&422& class=&origin_image zh-lightbox-thumb& width=&824& data-original=&https://pic1.zhimg.com/v2-1df53f92986_r.jpg&&&/figure&&h2&&b&实例3:百度/360搜索关键字提交&/b&&/h2&&figure&&img src=&https://pic1.zhimg.com/v2-20a9b1d0a0c6bfa8279c9_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&761& data-rawheight=&416& class=&origin_image zh-lightbox-thumb& width=&761& data-original=&https://pic1.zhimg.com/v2-20a9b1d0a0c6bfa8279c9_r.jpg&&&/figure&&p&我们先要查看关键词提交接口,随便输入个123之类的,看看url变化,试试就能发现:&/p&&figure&&img src=&https://pic2.zhimg.com/v2-5dca3d50610d_b.jpg& data-size=&normal& data-rawwidth=&734& data-rawheight=&438& class=&origin_image zh-lightbox-thumb& width=&734& data-original=&https://pic2.zhimg.com/v2-5dca3d50610d_r.jpg&&&figcaption&百度的是s?/wd=&/figcaption&&/figure&&figure&&img src=&https://pic2.zhimg.com/v2-0ab0bd1bd610d_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&817& data-rawheight=&266& class=&origin_image zh-lightbox-thumb& width=&817& data-original=&https://pic2.zhimg.com/v2-0ab0bd1bd610d_r.jpg&&&/figure&&figure&&img src=&https://pic3.zhimg.com/v2-1b24ae646ab5ba2a59ea98df2f8b9ad4_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&835& data-rawheight=&404& class=&origin_image zh-lightbox-thumb& width=&835& data-original=&https://pic3.zhimg.com/v2-1b24ae646ab5ba2a59ea98df2f8b9ad4_r.jpg&&&/figure&&p&360的方法也是一样滴&/p&&h2&&b&实例4:网络图片的爬取和存储&/b&&/h2&&figure&&img src=&https://pic1.zhimg.com/v2-34ac338c5b074bcbc4f82ce3ee222514_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&766& data-rawheight=&395& class=&origin_image zh-lightbox-thumb& width=&766& data-original=&https://pic1.zhimg.com/v2-34ac338c5b074bcbc4f82ce3ee222514_r.jpg&&&/figure&&figure&&img src=&https://pic4.zhimg.com/v2-b1f9f68dca5cdb9a43c46b75_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&796& data-rawheight=&386& class=&origin_image zh-lightbox-thumb& width=&796& data-original=&https://pic4.zhimg.com/v2-b1f9f68dca5cdb9a43c46b75_r.jpg&&&/figure&&figure&&img src=&https://pic1.zhimg.com/v2-41ad629b14a1b5dc6bd3c_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&823& data-rawheight=&420& class=&origin_image zh-lightbox-thumb& width=&823& data-original=&https://pic1.zhimg.com/v2-41ad629b14a1b5dc6bd3c_r.jpg&&&/figure&&h2&&b&实例5:IP地址归属地的自动查询&/b&&/h2&&figure&&img src=&https://pic2.zhimg.com/v2-54bf46dabc70ba12a5dda_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&797& data-rawheight=&470& class=&origin_image zh-lightbox-thumb& width=&797& data-original=&https://pic2.zhimg.com/v2-54bf46dabc70ba12a5dda_r.jpg&&&/figure&&figure&&img src=&https://pic4.zhimg.com/v2-12d0a21dd520b71e4abfbb43bc869efc_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&857& data-rawheight=&386& class=&origin_image zh-lightbox-thumb& width=&857& data-original=&https://pic4.zhimg.com/v2-12d0a21dd520b71e4abfbb43bc869efc_r.jpg&&&/figure&&figure&&img src=&https://pic4.zhimg.com/v2-0b60bec014a3f0eba415ab1a_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&763& data-rawheight=&423& class=&origin_image zh-lightbox-thumb& width=&763& data-original=&https://pic4.zhimg.com/v2-0b60bec014a3f0eba415ab1a_r.jpg&&&/figure&
实例1:京东商品页面的爬取 实例2:亚马逊商品页面的爬取在爬取中,我们发现了错误,应该是网站限制了爬虫爬取,所以我们这里用user_agent字段伪装成浏览器。这里注意,r.request.headers返回我们程序发起http请求的header部分。 实例3:百度/360搜索关键字…
&figure&&img src=&https://pic4.zhimg.com/v2-fbe653c5ca5a_b.jpg& data-rawwidth=&900& data-rawheight=&600& class=&origin_image zh-lightbox-thumb& width=&900& data-original=&https://pic4.zhimg.com/v2-fbe653c5ca5a_r.jpg&&&/figure&&p&requests库是学习爬虫的第一步,它的作用是可以代替浏览器发起http请求,并返回内容,知乎上之前已经有相关的介绍:&/p&&p&&a href=&https://zhuanlan.zhihu.com/p/& class=&internal&&requests:你爬虫的第一步&/a&&/p&&p&&a href=&https://zhuanlan.zhihu.com/p/& class=&internal&&爬虫入门系列(二):优雅的HTTP库requests&/a&&/p&&p&&br&&/p&&p&由于我是从中国大学mooc的爬虫教程中学习的,所以这里就直接搬运课程的文档并加以解析。&/p&&p&其实入门大概就是这些东西,先按下不表:&/p&&figure&&img src=&https://pic2.zhimg.com/v2-dac7759aca19fc090c4fb97506ddd135_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&778& data-rawheight=&421& class=&origin_image zh-lightbox-thumb& width=&778& data-original=&https://pic2.zhimg.com/v2-dac7759aca19fc090c4fb97506ddd135_r.jpg&&&/figure&&p&安装这种弱智过程就跳过了,这里直接讲方法,直接上图:&/p&&figure&&img src=&https://pic3.zhimg.com/v2-2d0e6aadc4fd1bcecb4f3e_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&915& data-rawheight=&463& class=&origin_image zh-lightbox-thumb& width=&915& data-original=&https://pic3.zhimg.com/v2-2d0e6aadc4fd1bcecb4f3e_r.jpg&&&/figure&&p&这是向服务器发起请求的七个方法。&/p&&p&最基础的方法是request方法:&/p&&figure&&img src=&https://pic3.zhimg.com/v2-ba47e194e_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&800& data-rawheight=&310& class=&origin_image zh-lightbox-thumb& width=&800& data-original=&https://pic3.zhimg.com/v2-ba47e194e_r.jpg&&&/figure&&p&其他方法都是从这个方法里封装出来的,为了进一步简便使用才用的,不然的话,其实用这一个方法都行,我们也可以说,就这么一个方法。&/p&&p&目前我能用到的,就是第二个get()方法,其他的先不表,不过也好理解。&/p&&figure&&img src=&https://pic3.zhimg.com/v2-3ee4ce9d3a7467985cace_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&917& data-rawheight=&384& class=&origin_image zh-lightbox-thumb& width=&917& data-original=&https://pic3.zhimg.com/v2-3ee4ce9d3a7467985cace_r.jpg&&&/figure&&p&get()方法构造了一个&b&Response对象,包含了爬虫返回的内容,&/b&这个对象有&b&属性和方法。&/b&&/p&&p&&br&&/p&&p&&b&这个是异常:&/b&&/p&&figure&&img src=&https://pic4.zhimg.com/v2-d79b05d203ad49dce4c9e8ced143d157_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&913& data-rawheight=&430& class=&origin_image zh-lightbox-thumb& width=&913& data-original=&https://pic4.zhimg.com/v2-d79b05d203ad49dce4c9e8ced143d157_r.jpg&&&/figure&&p&把这个用在try-except语句中的时候,如果一旦有异常,他就会自己蹦到except那处理异常,总共有以下几种异常。&/p&&figure&&img src=&https://pic2.zhimg.com/v2-bbabcd_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&911& data-rawheight=&444& class=&origin_image zh-lightbox-thumb& width=&911& data-original=&https://pic2.zhimg.com/v2-bbabcd_r.jpg&&&/figure&&p&&br&&/p&&p&&br&&/p&&p&&b&下面是response对象的属性&/b&&/p&&figure&&img src=&https://pic3.zhimg.com/v2-2bb691e2b3ca884766ce_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&915& data-rawheight=&394& class=&origin_image zh-lightbox-thumb& width=&915& data-original=&https://pic3.zhimg.com/v2-2bb691e2b3ca884766ce_r.jpg&&&/figure&&figure&&img src=&https://pic3.zhimg.com/v2-9c979e06bda526da9d2e2e_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&915& data-rawheight=&424& class=&origin_image zh-lightbox-thumb& width=&915& data-original=&https://pic3.zhimg.com/v2-9c979e06bda526da9d2e2e_r.jpg&&&/figure&&p&&br&&/p&&p&就是说,我们一般会用r.status_code检查浏览器返回的状态码,如果返回的是200,就表示成功了。&/p&&figure&&img src=&https://pic2.zhimg.com/v2-15aa87a52e8b45ee7d187e1_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&912& data-rawheight=&403& class=&origin_image zh-lightbox-thumb& width=&912& data-original=&https://pic2.zhimg.com/v2-15aa87a52e8b45ee7d187e1_r.jpg&&&/figure&&p&r.encoding貌似经常会解析错的,所以我们会使用一行:&/p&&div class=&highlight&&&pre&&code class=&language-python3&&&span&&/span&&span class=&n&&r&/span&&span class=&o&&.&/span&&span class=&n&&encoding&/span&&span class=&o&&=&/span&&span class=&n&&r&/span&&span class=&o&&.&/span&&span class=&n&&apprent_encoding&/span&&span class=&p&&()&/span&
&/code&&/pre&&/div&&p&这行代码可以将python程序显示的浏览器的编码形式,转换成从网页内容中猜测的形式,貌似可以解决乱码的问题。&/p&&p&&br&&/p&&p&&br&&/p&&p&get()方法还有几个可选参数:&/p&&figure&&img src=&https://pic1.zhimg.com/v2-2f780d9bfbce311d2347c_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&918& data-rawheight=&284& class=&origin_image zh-lightbox-thumb& width=&918& data-original=&https://pic1.zhimg.com/v2-2f780d9bfbce311d2347c_r.jpg&&&/figure&&figure&&img src=&https://pic1.zhimg.com/v2-ee00848bbb1c4afa42724_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&915& data-rawheight=&413& class=&origin_image zh-lightbox-thumb& width=&915& data-original=&https://pic1.zhimg.com/v2-ee00848bbb1c4afa42724_r.jpg&&&/figure&&p&这里先按下不表。&/p&&p&&br&&/p&&p&最后看看爬取网页的通用代码框架,一般来讲,我们要写三个函数,这是第一个函数,用来爬去内容的:&/p&&figure&&img src=&https://pic4.zhimg.com/v2-05acd542dc17f_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&909& data-rawheight=&442& class=&origin_image zh-lightbox-thumb& width=&909& data-original=&https://pic4.zhimg.com/v2-05acd542dc17f_r.jpg&&&/figure&&p&&br&&/p&&p&&br&&/p&&p&后面还讲了http协议的内容,不过这些我基本上会。&/p&&figure&&img src=&https://pic4.zhimg.com/v2-e6dd071d1eb_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&787& data-rawheight=&395& class=&origin_image zh-lightbox-thumb& width=&787& data-original=&https://pic4.zhimg.com/v2-e6dd071d1eb_r.jpg&&&/figure&&figure&&img src=&https://pic2.zhimg.com/v2-6defce0e0f05_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&827& data-rawheight=&430& class=&origin_image zh-lightbox-thumb& width=&827& data-original=&https://pic2.zhimg.com/v2-6defce0e0f05_r.jpg&&&/figure&&p&下面解析一下这些方法:&/p&&figure&&img src=&https://pic2.zhimg.com/v2-80a3b4face9_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&858& data-rawheight=&443& class=&origin_image zh-lightbox-thumb& width=&858& data-original=&https://pic2.zhimg.com/v2-80a3b4face9_r.jpg&&&/figure&&p&这就很简单,返回http内容的head头部信息。&/p&&p&还有post方法和put方法:&/p&&figure&&img src=&https://pic1.zhimg.com/v2-68b16c69fe30bc8e11cca2f245b512e8_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&863& data-rawheight=&465& class=&origin_image zh-lightbox-thumb& width=&863& data-original=&https://pic1.zhimg.com/v2-68b16c69fe30bc8e11cca2f245b512e8_r.jpg&&&/figure&&figure&&img src=&https://pic2.zhimg.com/v2-0d0aa114bb4bad244bc1c5_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&887& data-rawheight=&407& class=&origin_image zh-lightbox-thumb& width=&887& data-original=&https://pic2.zhimg.com/v2-0d0aa114bb4bad244bc1c5_r.jpg&&&/figure&&figure&&img src=&https://pic2.zhimg.com/v2-6bdf93f30b3ff9_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&893& data-rawheight=&482& class=&origin_image zh-lightbox-thumb& width=&893& data-original=&https://pic2.zhimg.com/v2-6bdf93f30b3ff9_r.jpg&&&/figure&&p&&/p&
requests库是学习爬虫的第一步,它的作用是可以代替浏览器发起http请求,并返回内容,知乎上之前已经有相关的介绍: 由于我是从中国大学mooc的爬虫教程中学习的,所以这里就直接搬运课程的…
爬虫爬取资源,不能绕开登录态模拟这个话题,为此,以百度网站为例,进行了相关实验,中间遇到不少坑,现将思路和源码分享出来。期望对其他人有益。&p&注:此实验过程中未出现要求输入图形验证码的情况,因此,该实验并未考虑解决图形验证码的问题。&/p&&h2&一、实验目标&/h2&&p&使用scrapy编写一个爬虫程序,完成百度网站的模拟登陆动作。&/p&&p&百度网站域名为:&a href=&https://link.zhihu.com/?target=https%3A//www.baidu.com& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&https://www.&/span&&span class=&visible&&baidu.com&/span&&span class=&invisible&&&/span&&/a&&/p&&p&其登录域名为:&a href=&https://link.zhihu.com/?target=https%3A//passport.baidu.com& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&https://&/span&&span class=&visible&&passport.baidu.com&/span&&span class=&invisible&&&/span&&/a&&/p&&h2&二、实验步骤&/h2&&p&1、分析百度网站的登陆流程,获取登陆过程中的http请求列表、流程;&/p&&p&2、细化每个请求的请求参数。通过对比两次登陆操作,搞清楚那些请求参数是变化的,那些是不变的;&/p&&p&3、搞清楚变化参数的来源。是否是前置请求的响应结果,如token值等,是否是通过某个随机因子计算出来的,计算规则是什么;&/p&&p&4、细化 cookie操作。这里的cookie操作包括request中上送的cookie项,及response中返回的cookie项;&/p&&p&5、根据1~4步的分析结果,进行编码测试。&/p&&h2&三、实验过程&/h2&&p&&b&注意事项:&/b&在进行登陆流程分析时,请先将浏览器的缓存数据(cookie、密码、localstorage)清除,使浏览器和scrapy所处的环境保持一致。&/p&&p&&b&1、分析百度网站的登陆流程&/b&&/p&&p&使用chrome的开发者工具(使用F12打开),监控Network,发现百度网站的登陆过程包含了如下关键请求:&/p&&p&由百度文库跳转到登陆页时初始化请求列表:&/p&&p&&figure&&img src=&https://pic1.zhimg.com/v2-6c5acc4c7_b.jpg& data-rawwidth=&1254& data-rawheight=&621& class=&origin_image zh-lightbox-thumb& width=&1254& data-original=&https://pic1.zhimg.com/v2-6c5acc4c7_r.jpg&&&/figure&输完用户名和密码之后的请求列表:&/p&&figure&&img src=&https://pic1.zhimg.com/v2-c5cc69a3d9eed972b9ed_b.jpg& data-rawwidth=&1354& data-rawheight=&622& class=&origin_image zh-lightbox-thumb& width=&1354& data-original=&https://pic1.zhimg.com/v2-c5cc69a3d9eed972b9ed_r.jpg&&&/figure&&p&点击‘登录’发起登陆操作后的请求列表:&br&&figure&&img src=&https://pic1.zhimg.com/v2-51ebd8a24ba1faa4fb24906cdaa41ac9_b.jpg& data-rawwidth=&1342& data-rawheight=&372& class=&origin_image zh-lightbox-thumb& width=&1342& data-original=&https://pic1.zhimg.com/v2-51ebd8a24ba1faa4fb24906cdaa41ac9_r.jpg&&&/figure&综上,初步看下来大致有如下几个请求:&/p&&ul&&li&getapi
GET&br&&/li&&li&loginhistory
GET&br&&/li&&li&logincheck
GET&br&&/li&&li&getpublickey
GET&br&&/li&&li&login
POST&/li&&/ul&&br&&b&2、分析每个请求的参数,找出变化的参数和未变化的参数&/b&&p&方法很简单:两次发起同一请求,比较两次请求的参数,那些变化了,那些没变。这里给出分析结果:&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&https://passport.baidu.com/v2/api/?getapi&tpl=pp&apiver=v3&tt=7&class=login&gid=7F1AC21-9F66-4C21-F06D93&logintype=basicLogin&callback=bd__cbs__d1anqs
&/code&&/pre&&/div&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&https://passport.baidu.com/v2/api/?loginhistory&token=dc6e33af80fbf3a882a29&tpl=pp&apiver=v3&tt=2&gid=7F1AC21-9F66-4C21-F06D93&callback=bd__cbs__z9eq8i
&/code&&/pre&&/div&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&https://passport.baidu.com/v2/api/?logincheck&token=dc6e33af80fbf3a882a29&tpl=pp&apiver=v3&tt=2&sub_source=leadsetpwd&username=&isphone=false&callback=bd__cbs__cbbfcv
&/code&&/pre&&/div&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&https://passport.baidu.com/v2/getpublickey?token=dc6e33af80fbf3a882a29&tpl=pp&apiver=v3&tt=0&gid=7F1AC21-9F66-4C21-F06D93&callback=bd__cbs__ayyugw
&/code&&/pre&&/div&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&https://passport.baidu.com/v2/api/?login POST
staticpage=https%3A%2F%2Fpassport.baidu.com%2Fstatic%2Fpasspc-account%2Fhtml%2Fv3Jump.html&charset=UTF-8&token=dc6e33af80fbf3a882a29&tpl=pp&subpro=&apiver=v3&tt=1&codestring=&safeflg=0&u=http%3A%2F%2Fwenku.baidu.com%2Ftask%2Fbrowse%2Fdaily&isPhone=&detect=1&gid=7F1AC21-9F66-4C21-F06D93&quick_user=0&logintype=basicLogin&logLoginType=pc_loginBasic&idc=&loginmerge=true&username=&password=IolkrLQPeeXlLRizlJxC5Sh4MRk9%2BVIJGYdAvfXdDRtH4cQVkHHVDVNX2COmHu4EBu06RkxL4bHuQMCeXIk%2FoIllKF0ud41ycI0TntjTFik1OtWyl6EotcP5CthrF%2BbhR3c%2F2U9ajurtT0a%2FrsCR4F890RiJXi2GiNS1DZTPTrM%3D&mem_pass=on&rsakey=lcvtPIIp75bKVqAvxmjUN7pLJghntkqZ&crypttype=12&ppui_logintime=548964&countrycode=&callback=parent.bd__pcbs__n14l9t
&/code&&/pre&&/div&&p&所有请求共用的变化参数:tt、gid、callback、token(getapi请求没有此参数);&/p&&p&login独有的变化参数:username、password、rsakey&/p&&p&其余参数为固定参数,可以copy浏览器的入参。&/p&&p&&b&3、找到变化参数的来源&/b&&/p&&p&从字面理解,大致可以猜测到一些参数的含义,并找到请来源,如果无法猜到,则需要对source或者Network的response做全局搜索,找到来源。&/p&&p&以token 和 password为例讲解。&/p&&p&&i&3.1 token参数来源分析&/i&&/p&&p&我们发现loginhistory 的请求参数token是可变的,很显然这个值表面上应当表示一个交互用的令牌,那么狠可能是前面请求返回的,于是追溯loginhistory 之前的请求,发现getapi的response包含了该参数,且和loginhistory reqeust中的token一致,因此,我们断定token是由getapi返回的。&/p&&p&&figure&&img src=&https://pic4.zhimg.com/v2-2cb314e65b4b_b.jpg& data-rawwidth=&1377& data-rawheight=&237& class=&origin_image zh-lightbox-thumb& width=&1377& data-original=&https://pic4.zhimg.com/v2-2cb314e65b4b_r.jpg&&&/figure&&figure&&img src=&https://pic3.zhimg.com/v2-0d5ef453d6bb88e7eea2049_b.jpg& data-rawwidth=&1255& data-rawheight=&249& class=&origin_image zh-lightbox-thumb& width=&1255& data-original=&https://pic3.zhimg.com/v2-0d5ef453d6bb88e7eea2049_r.jpg&&&/figure&&i&3.2 password参数来源分析&/i&&/p&&p&对于password,可以看到是一个密文,联想到前面的getpublickey请求,可以确定是rsa加密,但是具体的加密算法不知道,因此需要翻源码,折腾了很久,这里要感谢‘七夜的故事’这个博主,他的博文&a href=&https://link.zhihu.com/?target=http%3A//www.cnblogs.com/qiyeboy/p/5728293.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&百度登录加密协议分析(下)&/a& 提供了很好的参考。&/p&&p&在source中搜索‘password’,锁定关键js文件:&a href=&https://link.zhihu.com/?target=http%3A//passport.bdimg.com/passApi/js/login_tangram_a829ef5.js& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&login_tangram_9afb80e.js&/a&&/p&&p&&figure&&img src=&https://pic4.zhimg.com/v2-ae5e43d5a3da064a135b0a7b_b.jpg& data-rawwidth=&1451& data-rawheight=&392& class=&origin_image zh-lightbox-thumb& width=&1451& data-original=&https://pic4.zhimg.com/v2-ae5e43d5a3da064a135b0a7b_r.jpg&&&/figure&将js源码拷贝到文本编辑器,逐个排查,确定目标代码位置:&/p&&p&&figure&&img src=&https://pic3.zhimg.com/v2-bec9dd9e54f19f24f425cc_b.jpg& data-rawwidth=&1126& data-rawheight=&128& class=&origin_image zh-lightbox-thumb& width=&1126& data-original=&https://pic3.zhimg.com/v2-bec9dd9e54f19f24f425cc_r.jpg&&&/figure&继续搜索关键方法encrypt:&br&&figure&&img src=&https://pic1.zhimg.com/v2-5905cabc1be4fa0f2f408_b.jpg& data-rawwidth=&1261& data-rawheight=&63& class=&origin_image zh-lightbox-thumb& width=&1261& data-original=&https://pic1.zhimg.com/v2-5905cabc1be4fa0f2f408_r.jpg&&&/figure&继续搜索关键方法xn:&/p&&p&&figure&&img src=&https://pic1.zhimg.com/v2-61ac83e978b62a6f62d0_b.jpg& data-rawwidth=&1237& data-rawheight=&79& class=&origin_image zh-lightbox-thumb& width=&1237& data-original=&https://pic1.zhimg.com/v2-61ac83e978b62a6f62d0_r.jpg&&&/figure&读代码可能猜不到这是做base64,但是通过其他地方的代码可以猜测到:&/p&&p&&figure&&img src=&https://pic2.zhimg.com/v2-c9db20cefccdbcf99f2b2e0331afb699_b.jpg& data-rawwidth=&1210& data-rawheight=&63& class=&origin_image zh-lightbox-thumb& width=&1210& data-original=&https://pic2.zhimg.com/v2-c9db20cefccdbcf99f2b2e0331afb699_r.jpg&&&/figure&因此,最终确定password的加密规则为:Base64.encode(RSA(pwd))&/p&&p&&i&3.3 给出所有变化参数的来源结论:&/i&&/p&&ul&&li&tt:时间戳&br&&/li&&li&gid:生成的34位随机字符,未找到生成算法和来源,后来发现固定写死也没有影响&br&&/li&&li&callback:代码生成方法名后缀,算法参考源码,理论上只要是随机字符就可以&br&&/li&&li&rsakey:rsa公钥key,getpublickey放回&br&&/li&&li&password:rsa 加密得到,加密算法从js源码中找到,具体可以参考文章的描述。&br&&/li&&/ul&&h2&4、细化cookie操作&/h2&&p&请求链上的每个请求前后存在依赖,通常除了请求参数上的依赖,还有cookie的依赖,前一个请求写入cookie到浏览器,下一个请求request中带上这个cookie。&/p&&p&scrapy有一个很好的地方在于:他自动保存了请求链产生的所有cookie(确保setting.py文件中COOKIE_ENABLE = True,默认是True),通常不需要特别关注,但是有些时候,会遇到一些奇怪的问题,这时候需要去审视下scrapy发起的请求和浏览器原生请求之间在cookie上是否存在差异。&/p&&p&scrapy可以输出request和response对cookie的操作,在setting.py中配置:&br&&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&# Enable cookies debug,(disabeld by default)
COOKIES_DEBUG = True
&/code&&/pre&&/div&&br&&p&在这里举两个例子加以说明。&/p&&p&4.1 getapi需要上送BAIDUID cookie&/p&&p&这个cookie是百度网站为客户端生成的唯一标识,所以在发起getapi之前,需要请求一次&a href=&https://link.zhihu.com/?target=http%3A//www.baidu.com& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&百度一下,你就知道&/a&主页,写入这个cookie,否则直接调用getapi会报错。&/p&&p&4.2 login需要上送FP_UID cookie&/p&&p&代码调试过程中,login一直报错:err_no=257(请输入验证码)。后来对比了原生浏览器请求,发现缺少了这个cookie,手动写入后,通过。&/p&&p&可以参考代码中的逻辑实现。&/p&&h2&5、编码测试&/h2&&p&talk is cheep,show you the code!&/p&&p&其实编码和调试是同时进行的,包括分析的后面部分,涉及到细节也是在编码过程中才丰富起来的。因此,初期做一个概要分析,大致了解到参数的来源即可,编码过程中逐步丰富完成。&/p&&div class=&highlight&&&pre&&code class=&language-python&&&span&&/span&&span class=&c1&&# -*- coding: utf-8 -*-&/span&
&span class=&n&&__Author__&/span& &span class=&o&&=&/span& &span class=&s2&&&Leng Fuping&&/span&
&span class=&n&&__Doc__&/span& &span class=&o&&=&/span& &span class=&s2&&&baidu wenku sign everyday.&&/span&&span class=&p&&;&/span&
&span class=&kn&&from&/span& &span class=&nn&&scrapy.spiders&/span& &span class=&kn&&import&/span& &span class=&n&&Spider&/span&
&span class=&kn&&import&/span& &span class=&nn&&logging&/span&
&span class=&kn&&import&/span& &span class=&nn&&logging.config&/span&
&span class=&kn&&from&/span& &span class=&nn&&scrapy.http&/span& &span class=&kn&&import&/span& &span class=&n&&Request&/span&
&span class=&kn&&import&/span& &span class=&nn&&time&/span&
&span class=&kn&&import&/span& &span class=&nn&&urllib&/span&
&span class=&kn&&import&/span& &span class=&nn&&re&/span&
&span class=&kn&&from&/span& &span class=&nn&&Crypto.Cipher&/span& &span class=&kn&&import&/span& &span class=&n&&PKCS1_v1_5&/span&
&span class=&kn&&from&/span& &span class=&nn&&Crypto.PublicKey&/span& &span class=&kn&&import&/span& &span class=&n&&RSA&/span&
&span class=&kn&&import&/span& &span class=&nn&&base64&/span&
&span class=&kn&&import&/span& &span class=&nn&&math&/span&
&span class=&kn&&import&/span& &span class=&nn&&random&/span&
&span class=&n&&logging&/span&&span class=&o&&.&/span&&span class=&n&&basicConfig&/span&&span class=&p&&(&/span&&span class=&n&&level&/span&&span class=&o&&=&/span&&span class=&n&&logging&/span&&span class=&o&&.&/span&&span class=&n&&INFO&/span&&span class=&p&&,&/span&
&span class=&n&&format&/span&&span class=&o&&=&/span&&span class=&s1&&'&/span&&span class=&si&&%(asctime)s&/span&&span class=&s1&& &/span&&span class=&si&&%(filename)s&/span&&span class=&s1&&[line:&/span&&span class=&si&&%(lineno)d&/span&&span class=&s1&&] &/span&&span class=&si&&%(levelname)s&/span&&span class=&s1&& &/span&&span class=&si&&%(message)s&/span&&span class=&s1&&'&/span&&span class=&p&&,&/span&
&span class=&n&&datefmt&/span&&span class=&o&&=&/span&&span class=&s1&&'%a, &/span&&span class=&si&&%d&/span&&span class=&s1&& %b %Y %H:%M:%S'&/span&&span class=&p&&,&/span&
&span class=&n&&filename&/span&&span class=&o&&=&/span&&span class=&s1&&'baidu_wenku_signin_spider.log'&/span&&span class=&p&&,&/span&
&span class=&n&&filemode&/span&&span class=&o&&=&/span&&span class=&s1&&'a'&/span&&span class=&p&&)&/span& &span class=&c1&&#default 'a', if set 'w', the log file will be rewrite every runtime.&/span&
&span class=&n&&BAIDU_HOME_PAGE_URL&/span& &span class=&o&&=&/span& &span class=&s2&&&https://www.baidu.com/&&/span&
&span class=&n&&BAIDU_GET_TOKEN_URL&/span& &span class=&o&&=&/span& &span class=&s1&&'https://passport.baidu.com/v2/api/?getapi&tpl=pp&apiver=v3&class=login&logintype=basicLogin'&/span&
&span class=&n&&BAIDU_GET_LOGIN_HISTORY_URL&/span& &span class=&o&&=&/span& &span class=&s1&&'https://passport.baidu.com/v2/api/?loginhistory&tpl=pp&apiver=v3'&/span&
&span class=&n&&BAIDU_LOGIN_CHECK_URL&/span& &span class=&o&&=&/span& &span class=&s1&&'https://passport.baidu.com/v2/api/?logincheck&tpl=pp&apiver=v3&sub_source=leadsetpwd&username=&isphone=false&callback=bd__cbs__u1vvyu'&/span&
&span class=&n&&BAIDU_GET_PUBLIC_KEY_URL&/span& &span class=&o&&=&/span& &span class=&s1&&'https://passport.baidu.com/v2/getpublickey?tpl=pp&apiver=v3'&/span&
&span class=&n&&BAIDU_LOGIN_URL&/span& &span class=&o&&=&/span& &span class=&s2&&&https://passport.baidu.com/v2/api/?login&&/span&
&span class=&n&&BAIDU_WENKU_SIGNIN_URL&/span& &span class=&o&&=&/span& &span class=&s2&&&http://wenku.baidu.com/task/submit/signin&&/span&
&span class=&n&&COMMON_HEADERS&/span& &span class=&o&&=&/span& &span class=&p&&{&/span&
&span class=&s2&&&Content-Type&&/span&&span class=&p&&:&/span& &span class=&s2&&&application/x-www-form-urlencoded&&/span&&span class=&p&&,&/span&
&span class=&s2&&&Accept&&/span&&span class=&p&&:&/span& &span class=&s2&&&text/html,application/xhtml+xml,application/q=0.9,image/webp,*/*;q=0.8&&/span&&span class=&p&&,&/span&
&span class=&s2&&&Accept-Language&&/span&&span class=&p&&:&/span& &span class=&s2&&&zh-CN,q=0.8&&/span&&span class=&p&&,&/span&
&span class=&s2&&&Accept-Encoding&&/span&&span class=&p&&:&/span& &span class=&s2&&&gzip, deflate, sdch, br&&/span&&span class=&p&&,&/span&
&span class=&s2&&&Connection&&/span&&span class=&p&&:&/span& &span class=&s2&&&keep-alive&&/span&&span class=&p&&,&/span&
&span class=&s2&&&Cache-Control&&/span&&span class=&p&&:&/span& &span class=&s2&&&Cache-Control&&/span&&span class=&p&&,&/span&
&span class=&s2&&&User-Agent&&/span&&span class=&p&&:&/span& &span class=&s2&&&Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0. Safari/537.36&&/span&&span class=&p&&,&/span&
&span class=&s2&&&Pragma&&/span&&span class=&p&&:&/span&&span class=&s2&&&no-cache&&/span&
&span class=&p&&}&/span&
&span class=&k&&class&/span& &span class=&nc&&BaiduWenkuSigninSpider&/span&&span class=&p&&(&/span&&span class=&n&&Spider&/span&&span class=&p&&):&/span&
&span class=&n&&name&/span&&span class=&o&&=&/span&&span class=&s2&&&baidu_wenku_signin&&/span&
&span class=&n&&start_urls&/span& &span class=&o&&=&/span& &span class=&p&&[&/span&&span class=&s1&&'https://www.yinxiang.com/'&/span&&span class=&p&&]&/span&
&span class=&k&&def&/span& &span class=&nf&&parse&/span&&span class=&p&&(&/span&&span class=&bp&&self&/span&&span class=&p&&,&/span& &span class=&n&&response&/span&&span class=&p&&):&/span&
&span class=&k&&yield&/span& &span class=&bp&&self&/span&&span class=&o&&.&/span&&span class=&n&&get_home_page&/span&&span class=&p&&()&/span&
&span class=&k&&def&/span& &span class=&nf&&get_callback_method_name&/span&&span class=&p&&(&/span&&span class=&bp&&self&/span&&span class=&p&&):&/span&
&span class=&n&&method_name_str&/span& &span class=&o&&=&/span& &span class=&s1&&'bd__cbs__'&/span& &span class=&o&&+&/span& &span class=&nb&&str&/span&&span class=&p&&(&/span&&span class=&n&&math&/span&&span class=&o&&.&/span&&span class=&n&&floor&/span&&span class=&p&&(&/span&&span class=&mi&&&/span& &span class=&o&&*&/span& &span class=&n&&random&/span&&span class=&o&&.&/span&&span class=&n&&random&/span&&span class=&p&&()))&/span&
&span class=&n&&logging&/span&&span class=&o&&.&/span&&span class=&n&&info&/span&&span class=&p&&(&/span&&span class=&s2&&&get callback method name is &/span&&span class=&si&&%s&/span&&span class=&s2&&&&/span&&span class=&p&&,&/span&&span class=&n&&method_name_str&/span&&span class=&p&&)&/span&
&span class=&k&&return&/span& &span class=&n&&method_name_str&/span&
&span class=&k&&def&/span& &span class=&nf&&get_gid&/span&&span class=&p&&(&/span&&span class=&bp&&self&/span&&span class=&p&&):&/span&
&span class=&k&&return&/span& &span class=&s1&&'F970A89-DB7D-4F4B-B1CF-8CE2AA219D49'&/span&
&span class=&k&&def&/span& &span class=&nf&&get_home_page&/span&&span class=&p&&(&/span&&span class=&bp&&self&/span&&span class=&p&&):&/span&
&span class=&n&&COMMON_HEADERS&/span&&span class=&p&&[&/span&&span class=&s2&&&Host&&/span&&span class=&p&&]&/span& &span class=&o&&=&/span& &span class=&s2&&&www.baidu.com&&/span&
&span class=&n&&request&/span& &span class=&o&&=&/span& &span class=&n&&Request&/span&&span class=&p&&(&/span&&span class=&n&&BAIDU_HOME_PAGE_URL&/span&&span class=&p&&,&/span& &span class=&n&&headers&/span&&span class=&o&&=&/span&&span class=&n&&COMMON_HEADERS&/span&&span class=&p&&,&/span&&span class=&n&&callback&/span&&span class=&o&&=&/span&&span class=&bp&&self&/span&&span class=&o&&.&/span&&span class=&n&&parse_get_home_page_result&/span&&span class=&p&&)&/span&
&span class=&k&&return&/span& &span class=&n&&request&/span&
&span class=&k&&def&/span& &span class=&nf&&parse_get_home_page_result&/span&&span class=&p&&(&/span&&span class=&bp&&self&/span&&span class=&p&&,&/span& &span class=&n&&response&/span&&span class=&p&&):&/span&
&span class=&k&&if&/span& &span class=&n&&response&/span&&span class=&o&&.&/span&&span class=&n&&status&/span& &span class=&ow&&is&/span& &span class=&mi&&200&/span&&span class=&p&&:&/span&
&span class=&n&&logging&/span&&span class=&o&&.&/span&&span class=&n&&info&/span&&span class=&p&&(&/span&&span class=&s2&&&get baidu home page success!&&/span&&span class=&p&&)&/span&
&span class=&k&&yield&/span& &span class=&bp&&self&/span&&span class=&o&&.&/span&&span class=&n&&get_token&/span&&span class=&p&&()&/span&
&span class=&k&&else&/span&&span class=&p&&:&/span&
&span class=&n&&logging&/span&&span class=&o&&.&/span&&span class=&n&&error&/span&&span class=&p&&(&/span&&span class=&s2&&&get baidu home page failed, the httpstatus is: &/span&&span class=&si&&%s&/span&&span class=&s2&&&&/span&&span class=&p&&,&/span& &span class=&n&&response&/span&&span class=&o&&.&/span&&span class=&n&&status&/span&&span class=&p&&)&/span&
&span class=&k&&def&/span& &span class=&nf&&get_token&/span&&span class=&p&&(&/span&&span class=&bp&&self&/span&&span class=&p&&):&/span&
&span class=&n&&COMMON_HEADERS&/span&&span class=&p&&[&/span&&span class=&s2&&&Host&&/span&&span class=&p&&]&/span& &span class=&o&&=&/span& &span class=&s2&&&passport.baidu.com&&/span&
&span class=&n&&full_baidu_get_token_url&/span& &span class=&o&&=&/span& &span class=&n&&BAIDU_GET_TOKEN_URL&/span&&span class=&o&&+&/span&&span class=&s2&&&&tt=&&/span&&span class=&o&&+&/span&&span class=&s1&&'&/span&&span class=&si&&%d&/span&&span class=&s1&&'&/span& &span class=&o&&%&/span& &span class=&p&&(&/span&&span class=&n&&time&/span&&span class=&o&&.&/span&&span class=&n&&time&/span&&span class=&p&&()&/span& &span class=&o&&*&/span& &span class=&mi&&1000&/span&&span class=&p&&)&/span&&span class=&o&&+&/span&&span class=&s2&&&&callback=&&/span&&span class=&o&&+&/span&&span class=&bp&&self&/span&&span class=&o&&.&/span&&span class=&n&&get_callback_method_name&/span&&span class=&p&&()&/span&&span class=&o&&+&/span&&span class=&s2&&&&gid=&&/span&&span class=&o&&+&/span&&span class=&bp&&self&/span&&span class=&o&&.&/span&&span class=&n&&get_gid&/span&&span class=&p&&()&/span&
&span class=&n&&request&/span& &span class=&o&&=&/span& &span class=&n&&Request&/span&&span class=&p&&(&/span&&span class=&n&&full_baidu_get_token_url&/span&&span class=&p&&,&/span& &span class=&n&&headers&/span&&span class=&o&&=&/span&&span class=&n&&COMMON_HEADERS&/span&&span class=&p&&,&/span& &span class=&n&&callback&/span&&span class=&o&&=&/span&&span class=&bp&&self&/span&&span class=&o&&.&/span&&span class=&n&&parse_get_token_result&/span&&span class=&p&&)&/span&
&span class=&k&&return&/span& &span class=&n&&request&/span&
&span class=&k&&def&/span& &span class=&nf&&parse_get_token_result&/span&&span class=&p&&(&/span&&span class=&bp&&self&/span&&span class=&p&&,&/span&&span class=&n&&response&/span&&span class=&p&&):&/span&
&span class=&k&&if&/span& &span class=&n&&response&/span&&span class=&o&&.&/span&&span class=&n&&status&/span& &span class=&ow&&is&/span& &span class=&mi&&200&/span&&span class=&p&&:&/span&
&span class=&n&&reg_token&/span& &span class=&o&&=&/span& &span class=&n&&re&/span&&span class=&o&&.&/span&&span class=&n&&compile&/span&&span class=&p&&(&/span&&span class=&s2&&&&/span&&span class=&se&&\&&/span&&span class=&s2&&token&/span&&span class=&se&&\&&/span&&span class=&s2&&\s+:\s+&/span&&span class=&se&&\&&/span&&span class=&s2&&(\w+)&/span&&span class=&se&&\&&/span&&span class=&s2&&&&/span&&span class=&p&&)&/span&
&span class=&bp&&self&/span&&span class=&o&&.&/span&&span class=&n&&_token&/span& &span class=&o&&=&/span& &span class=&n&&reg_token&/span&&span class=&o&&.&/span&&span class=&n&&findall&/span&&span class=&p&&(&/span&&span class=&nb&&str&/span&&span class=&p&&(&/span&&span class=&n&&response&/span&&span class=&o&&.&/span&&span class=&n&&body&/span&&span class=&p&&))[&/span&&span class=&mi&&0&/span&&span class=&p&&]&/span&
&span class=&n&&logging&/span&&span class=&o&&.&/span&&span class=&n&&info&/span&&span class=&p&&(&/span&&span class=&s2&&&get token success! the token is: &/span&&span class=&si&&%s&/span&&span class=&s2&&&&/span&&span class=&p&&,&/span&&span class=&bp&&self&/span&&span class=&o&&.&/span&&span class=&n&&_token&/span&&span class=&p&&)&/span&
&span class=&k&&yield&/span& &span class=&bp&&self&/span&&span class=&o&&.&/span&&span class=&n&&login_history&/span&&span class=&p&&()&/span&
&span class=&k&&else&/span&&span class=&p&&:&/span&
&span class=&n&&logging&/span&&span class=&o&&.&/span&&span class=&n&&error&/span&&span class=&p&&(&/span&&span class=&s2&&&get baidu login token failed, the httpstatus is: &/span&&span class=&si&&%s&/span&&span class=&s2&&&&/span&&span class=&p&&,&/span& &span class=&n&&response&/span&&span class=&o&&.&/span&&span class=&n&&status&/span&&span class=&p&&)&/span&
&span class=&k&&def&/span& &span class=&nf&&login_history&/span&&span class=&p&&(&/span&&span class=&bp&&self&/span&&span class=&p&&):&/span&
&span class=&n&&COMMON_HEADERS&/span&&span class=&p&&[&/span&&span class=&s2&&&Host&&/span&&span class=&p&&]&/span& &span class=&o&&=&/span& &span class=&s2&&&passport.baidu.com&&/span&
&span class=&n&&COMMON_HEADERS&/span&&span class=&p&&[&/span&&span class=&s2&&&Referer&&/span&&span class=&p&&]&/span& &span class=&o&&=&/span& &span class=&s2&&&https://passport.baidu.com/v2/?login&u=http://wenku.baidu.com/task/browse/daily&&/span&
&span class=&n&&COMMON_HEADERS&/span&&span class=&p&&[&/span&&span class=&s2&&&Accept&&/span&&span class=&p&&]&/span& &span class=&o&&=&/span& &span class=&s2&&&*/*&&/span&
&span class=&n&&COMMON_HEADERS&/span&&span class=&p&&[&/span&&span class=&s2&&&Cache-Control&&/span&&span class=&p&&]&/span& &span class=&o&&=&/span& &span class=&s2&&&no-cache&&/span&
&span class=&n&&full_baidu_get_login_history_url&/span& &span class=&o&&=&/span& &span class=&n&&BAIDU_GET_LOGIN_HISTORY_URL&/span&&span class=&o&&+&/span&&span class=&s2&&&&token=&&/span&&span class=&o&&+&/span&&span class=&bp&&self&/span&&span class=&o&&.&/span&&span class=&n&&_token&/span&&span class=&o&&+&/span&&span class=&s2&&&&tt=&&/span&&span class=&o&&+&/span&&span class=&s1&&'&/span&&span class=&si&&%d&/span&&span class=&s1&&'&/span& &span class=&o&&%&/span& &span class=&p&&(&/span&&span class=&n&&time&/span&&span class=&o&&.&/span&&span class=&n&&time&/span&&span class=&p&&()&/span& &span class=&o&&*&/span& &span class=&mi&&1000&/span&&span class=&p&&)&/span&&span class=&o&&+&/span&&span class=&s2&&&&callback=&&/span&&span class=&o&&+&/span&&span class=&bp&&self&/span&&span class=&o&&.&/span&&span class=&n&&get_callback_method_name&/span&&span class=&p&&()&/span&&span class=&o&&+&/span&&span class=&s2&&&&gid=&&/span&&span class=&o&&+&/span&&span class=&bp&&self&/span&&span class=&o&&.&/span&&span class=&n&&get_gid&/span&&span class=&p&&()&/span&
&span class=&n&&request&/span& &span class=&o&&=&/span& &span class=&n&&Request&/span&&span class=&p&&(&/span&&span class=&n&&full_baidu_get_login_history_url&/span&&span class=&p&&,&/span& &span class=&n&&headers&/span&&span class=&o&&=&/span&&span class=&n&&COMMON_HEADERS&/span&&span class=&p&&,&/span& &span class=&n&&callback&/span&&span class=&o&&=&/span&&span class=&bp&&self&/span&&span class=&o&&.&/span&&span class=&n&&parse_login_history_result&/span&&span class=&p&&)&/span&
&span class=&k&&return&/span& &span class=&n&&request&/span&
&span class=&k&&def&/span& &span class=&nf&&parse_login_history_result&/span&&span class=&p&&(&/span&&span class=&bp&&self&/span&&span class=&p&&,&/span&&span class=&n&&response&/span&&span class=&p&&):&/span&
&span class=&k&&if&/span& &span class=&n&&response&/span&&span class=&o&&.&/span&&span class=&n&&status&/span& &span class=&ow&&is&/span& &span class=&mi&&200&/span&&span class=&p&&:&/span&
&span class=&n&&logging&/span&&span class=&o&&.&/span&&span class=&n&&info&/span&&span class=&p&&(&/span&&span class=&s2&&&get login history response is: &/span&&span class=&si&&%s&/span&&span class=&s2&&&&/span&&span class=&p&&,&/span&&span class=&n&&response&/span&&span class=&o&&.&/span&&span class=&n&&body&/span&&span class=&p&&)&/span&
&span class=&k&&yield&/span& &span class=&bp&&self&/span&&span class=&o&&.&/span&&span class=&n&&login_check&/span&&span class=&p&&()&/span&
&span class=&k&&else&/span&&span class=&p&&:&/span&
&span class=&n&&logging&/span&&span class=&o&&.&/span&&span class=&n&&error&/span&&span class=&p&&(&/span&&span class=&s2&&&get baidu login token failed, the httpstatus is: &/span&&span class=&si&&%s&/span&&span class=&s2&&&&/span&&span class=&p&&,&/span& &span class=&n&&response&/span&&span class=&o&&.&/span&&span class=&n&&status&/span&&span class=&p&&)&/span&
&span class=&k&&def&/span& &span class=&nf&&login_check&/span&&span class=&p&&(&/span&&span class=&bp&&self&/span&&span class=&p&&):&/span&
&span class=&n&&full_baidu_login_check_url&/span& &span class=&o&&=&/span& &span class=&n&&BAIDU_LOGIN_CHECK_URL&/span& &span class=&o&&+&/span& &span class=&s2&&&&token=&&/span& &span class=&o&&+&/span& &span class=&bp&&self&/span&&span class=&o&&.&/span&&span class=&n&&_token&/span&&span class=&o&&+&/span&&span class=&s2&&&&tt=&&/span&&span class=&o&&+&/span&&span class=&s1&&'&/span&&span class=&si&&%d&/span&&span class=&s1&&'&/span& &span class=&o&&%&/span& &span class=&p&&(&/span&&span class=&n&&time&/span&&span class=&o&&.&/span&&span class=&n&&time&/span&&span class=&p&&()&/span& &span class=&o&&*&/span& &span class=&mi&&1000&/span&&span class=&p&&)&/span&&span class=&o&&+&/span&&span class=&s2&&&&callback=&&/span&&span class=&o&&+&/span&&span class=&bp&&self&/span&&span class=&o&&.&/span&&span class=&n&&get_callback_method_name&/span&&span class=&p&&()&/span&&span class=&o&&+&/span&&span class=&s2&&&&gid=&&/span&&span class=&o&&+&/span&&span class=&bp&&self&/span&&span class=&o&&.&/span&&span class=&n&&get_gid&/span&&span }

我要回帖

更多关于 正则表达式 分组 捕获 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信