摘要:本文将介绍用Python进行的爬虫的各种练习以及涉及到的各种知识,包括Http协议,cookie等等

工具

Fiddler

Python默认不用代理,所以fiddler不能截取它的包。如果想用用fiddler来分析Python的网络访问,需要在Python编程里面设置代理

Python does not use proxy by default, so fiddler cannot intercept its network traffic. You may need to change the Python program a little. Here is another thread on how to see proxy for Python programs.

参考:

[1] Fiddler 如何捕获Python3中的Http访问

[2] fiddler-doesnt-capture-python-http-request & Proxy with urllib2

[3] Fiddler 教程

HTTP协议

HTTP是Hyper Text Transfer Protocol(超文本传输协议)的缩写。是用于从WWW服务器传输超文本到本地浏览器的传送协议。

HTTP的请求响应模型

这样就限制了使用HTTP协议,无法实现在客户端没有发起请求的时候,服务器将消息推送给客户端。

HTTP协议是一个无状态的协议,同一个客户端的这次请求和上次请求是没有对应关系。

工作流程

一次HTTP操作称为一个事务,其工作过程可分为四步:

1)首先客户机与服务器需要建立连接。只要单击某个超级链接,HTTP的工作开始。

2)建立连接后,客户机发送一个请求给服务器,请求方式的格式为:统一资源标识符(URL)、协议版本号,后边是MIME信息包括请求修饰符、客户机信息和可能的内容。

3)服务器接到请求后,给予相应的响应信息,其格式为一个状态行,包括信息的协议版本号、一个成功或错误的代码,后边是MIME信息包括服务器信息、实体信息和可能的内容。

4)客户端接收服务器所返回的信息通过浏览器显示在用户的显示屏上,然后客户机与服务器断开连接。

如果在以上过程中的某一步出现错误,那么产生错误的信息将返回到客户端,有显示屏输出。对于用户来说,这些过程是由HTTP自己完成的,用户只要用鼠标点击,等待信息显示就可以了

数据结构

The following example illustrates a typical message exchange for a GET request  on the URI "http://www.example.com/hello.txt":

Client request:

GET /hello.txt HTTP/1.1

User-Agent: curl/7.16.3 libcurl/7.16.3 OpenSSL/0.9.7l zlib/1.2.3

Host: www.example.com

Accept-Language: en, mi

Server response:

HTTP/1.1 200 OK

Date: Mon, 27 Jul 2009 12:28:53 GMT

Server: Apache

Last-Modified: Wed, 22 Jul 2009 19:15:56 GMT

ETag: "34aa387-d-1568eb00"

Accept-Ranges: bytes

Content-Length: 51

Vary: Accept-Encoding

Content-Type: text/plain

Hello World! My payload includes a trailing CRLF.

请求报头

请求报头允许客户端向服务器端传递请求的附加信息以及客户端自身的信息。

常用的请求报头

Accept

Accept请求报头域用于指定客户端接受哪些类型的信息。eg:Accept:image/gif,表明客户端希望接受GIF图象格式的资源;Accept:text/html,表明客户端希望接受html文本。

Accept-Charset

Accept-Charset请求报头域用于指定客户端接受的字符集。eg:Accept-Charset:iso-8859-1,gb2312.如果在请求消息中没有设置这个域,缺省是任何字符集都可以接受。

Accept-Encoding

Accept-Encoding请求报头域类似于Accept,但是它是用于指定可接受的内容编码。eg:Accept-Encoding:gzip.deflate.如果请求消息中没有设置这个域服务器假定客户端对各种内容编码都可以接受。

Accept-Language

Accept-Language请求报头域类似于Accept,但是它是用于指定一种自然语言。eg:Accept-Language:zh-cn.如果请求消息中没有设置这个报头域,服务器假定客户端对各种语言都可以接受。

Authorization

Authorization请求报头域主要用于证明客户端有权查看某个资源。当浏览器访问一个页面时,如果收到服务器的响应代码为401(未授权),可以发送一个包含Authorization请求报头域的请求,要求服务器对其进行验证。

Host(发送请求时,该报头域是必需的)

Host请求报头域主要用于指定被请求资源的Internet主机和端口号,它通常从HTTP URL中提取出来的,eg:

我们在浏览器中输入:http://www.guet.edu.cn/index.html

浏览器发送的请求消息中,就会包含Host请求报头域,如下:

Host:www.guet.edu.cn

此处使用缺省端口号80,若指定了端口号,则变成:Host:www.guet.edu.cn:指定端口号

User-Agent

我们上网登陆论坛的时候,往往会看到一些欢迎信息,其中列出了你的操作系统的名称和版本,你所使用的浏览器的名称和版本,这往往让很多人感到很神奇,实际上,服务器应用程序就是从User-Agent这个请求报头域中获取到这些信息。User-Agent请求报头域允许客户端将它的操作系统、浏览器和其它属性告诉服务器。不过,这个报头域不是必需的,如果我们自己编写一个浏览器,不使用User-Agent请求报头域,那么服务器端就无法得知我们的信息了。

请求报头举例:

GET /form.html HTTP/1.1 (CRLF)

Accept:image/gif,image/x-xbitmap,image/jpeg,application/x-shockwave-flash,application/vnd.ms-excel,application/vnd.ms-powerpoint,application/msword,*/* (CRLF)

Accept-Language:zh-cn (CRLF)

Accept-Encoding:gzip,deflate (CRLF)

If-Modified-Since:Wed,05 Jan 2007 11:21:25 GMT (CRLF)

If-None-Match:W/"80b1a4c018f3c41:8317" (CRLF)

User-Agent:Mozilla/4.0(compatible;MSIE6.0;Windows NT 5.0) (CRLF)

Host:www.guet.edu.cn (CRLF)

Connection:Keep-Alive (CRLF)

(CRLF)

响应报头

响应报头允许服务器传递不能放在状态行中的附加响应信息,以及关于服务器的信息和对Request-URI所标识的资源进行下一步访问的信息。

常用的响应报头

Location

Location响应报头域用于重定向接受者到一个新的位置。Location响应报头域常用在更换域名的时候。

Server

Server响应报头域包含了服务器用来处理请求的软件信息。与User-Agent请求报头域是相对应的。下面是

Server响应报头域的一个例子:

Server:Apache-Coyote/1.1

WWW-Authenticate

WWW-Authenticate响应报头域必须被包含在401(未授权的)响应消息中,客户端收到401响应消息时候,并发送Authorization报头域请求服务器对其进行验证时,服务端响应报头就包含该报头域。

eg:WWW-Authenticate:Basic realm="Basic Auth Test!" //可以看出服务器对请求资源采用的是基本验证机制。

https://www.w3.org/Protocols/#Specs

爬虫编程

简单爬虫

import urllib
import sys
url = "http://www.healforce.com/cn/index.php?ac=article&at=read&did=444"
webPage=urllib.urlopen(url)
data = webPage.read()
data = data.decode('utf-8').encode(sys.getfilesystemencoding())

设置代理的代码如下(便于fiddler抓包分析)

import urllib2
import sys
url = "http://www.healforce.com/cn/index.php?ac=article&at=read&did=444"
proxy = urllib2.ProxyHandler({'http': '127.0.0.1:8888'})
opener = urllib2.build_opener(proxy)
urllib2.install_opener(opener)
webPage=urllib2.urlopen(url)
data = webPage.read()
data = data.decode('utf-8').encode(sys.getfilesystemencoding())
print(data)
print(type(webPage))
print(webPage.geturl())
print(webPage.info())
print(webPage.getcode())

打印结果如下

>>> print(type(webPage))
<type 'instance'>
>>> print(webPage.geturl())
http://www.healforce.com/cn/index.php?ac=article&at=read&did=444
>>> print(webPage.info())
Date: Thu, 11 Aug 2016 10:38:48 GMT
Server: Apache/2.4.10 (Win32) OpenSSL/1.0.1h
Connection: close
Transfer-Encoding: chunked
Content-Type: text/html; charset=utf-8
>>> print(webPage.getcode())
200

用Fiddler来抓取数据分析

1. 200表示访问成功

2. 访问的地址

3. Python生成的请求表头

4. 响应返回的html,这个跟print(data)返回的是一样的

伪装成流程器爬虫

有些网页,如果不是从浏览器发起的访问,它会拒绝响应。我们可以自己来写报头,然后发送给网页浏览器,它会认为你是一个正常的浏览器,这样就可以访问了。

import urllib2
url = "http://www.healforce.com/cn/index.php?ac=article&at=read&did=444"
webheader = {'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:23.0) Gecko/20100101 Firefox/23.0'}
proxy = urllib2.ProxyHandler({'http': '127.0.0.1:8888'})
opener = urllib2.build_opener(proxy)
urllib2.install_opener(opener)
request = urllib2.Request(url,headers=webheader)
webPage=urllib2.urlopen(request)
data = webPage.read()
print(data)

可以添加更多的header,从Fiddler截图中可以看到Client里的Header内容增加了。

返回内容没有变化

import urllib2
url = "http://www.healforce.com/cn/index.php?ac=article&at=read&did=444"
webheader = {
'Connection': 'Keep-Alive',
'Accept': 'text/html, application/xhtml+xml, */*',
'Accept-Language': 'en-US,en;q=0.8,zh-Hans-CN;q=0.5,zh-Hans;q=0.3',
'User-Agent': 'Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko',
#'Accept-Encoding': 'gzip, deflate',
'Host': 'www.douban.com',
'DNT': '1'
}
proxy = urllib2.ProxyHandler({'http': '127.0.0.1:8888'})
opener = urllib2.build_opener(proxy)
urllib2.install_opener(opener)
request = urllib2.Request(url,headers=webheader)
request.add_header('User-Agent','Mozilla/5.0 (Windows NT 6.1; WOW64; rv:23.0) Gecko/20100101 Firefox/23.0')
webPage=urllib2.urlopen(request)
data = webPage.read()

参考

[1] Python 标准库 urllib2 的使用细节

[2] Python3中urllib详细使用方法(header,代理,超时,认证,异常处理)

[3] python中使用urllib2伪造HTTP报头的2个方法

关注下面二维码获取更多资讯

[Python] spides的更多相关文章

  1. Python中的多进程与多线程(一)

    一.背景 最近在Azkaban的测试工作中,需要在测试环境下模拟线上的调度场景进行稳定性测试.故而重操python旧业,通过python编写脚本来构造类似线上的调度场景.在脚本编写过程中,碰到这样一个 ...

  2. Python高手之路【六】python基础之字符串格式化

    Python的字符串格式化有两种方式: 百分号方式.format方式 百分号的方式相对来说比较老,而format方式则是比较先进的方式,企图替换古老的方式,目前两者并存.[PEP-3101] This ...

  3. Python 小而美的函数

    python提供了一些有趣且实用的函数,如any all zip,这些函数能够大幅简化我们得代码,可以更优雅的处理可迭代的对象,同时使用的时候也得注意一些情况   any any(iterable) ...

  4. JavaScript之父Brendan Eich,Clojure 创建者Rich Hickey,Python创建者Van Rossum等编程大牛对程序员的职业建议

    软件开发是现时很火的职业.据美国劳动局发布的一项统计数据显示,从2014年至2024年,美国就业市场对开发人员的需求量将增长17%,而这个增长率比起所有职业的平均需求量高出了7%.很多人年轻人会选择编 ...

  5. 可爱的豆子——使用Beans思想让Python代码更易维护

    title: 可爱的豆子--使用Beans思想让Python代码更易维护 toc: false comments: true date: 2016-06-19 21:43:33 tags: [Pyth ...

  6. 使用Python保存屏幕截图(不使用PIL)

    起因 在极客学院讲授<使用Python编写远程控制程序>的课程中,涉及到查看被控制电脑屏幕截图的功能. 如果使用PIL,这个需求只需要三行代码: from PIL import Image ...

  7. Python编码记录

    字节流和字符串 当使用Python定义一个字符串时,实际会存储一个字节串: "abc"--[97][98][99] python2.x默认会把所有的字符串当做ASCII码来对待,但 ...

  8. Apache执行Python脚本

    由于经常需要到服务器上执行些命令,有些命令懒得敲,就准备写点脚本直接浏览器调用就好了,比如这样: 因为线上有现成的Apache,就直接放它里面了,当然访问安全要设置,我似乎别的随笔里写了安全问题,这里 ...

  9. python开发编译器

    引言 最近刚刚用python写完了一个解析protobuf文件的简单编译器,深感ply实现词法分析和语法分析的简洁方便.乘着余热未过,头脑清醒,记下一点总结和心得,方便各位pythoner参考使用. ...

随机推荐

  1. Flexslider图片轮播、文字图片相结合滑动切换效果

    Flexslider是一款基于的jQuery内容滚动插件.它能让你轻松的创建内容滚动的效果,具有非常高的可定制性.开发者可以使用Flexslider轻松创建各种图片轮播效果.焦点图效果.图文混排滚动效 ...

  2. python基础-更新篇

    对于windows来说就很简单了: 下载最新版本的python,然后卸载老版本,重新安装即可 对于linux系统的主机来说就有点复杂了: 现在linux主机自带的python版本都使2.x版的,而且L ...

  3. json_encode不编码中文字符的方式

    json_encode($array,JSON_UNESCAPED_UNICODE);

  4. 用sql实现汉字转拼音

    有时我们会需要将汉字转为拼音,例如需要将省市转为拼音后当做编码存储(尽管国家有统一的标识码,但有时候我们还是会用到),网络上也有工具提供汉字转拼音的功能,但各有优劣,一般转拼音后还会存在带声调的字母, ...

  5. invalid receiver type

    Because in a case like this: type I int type P *I func (i I) Get() int { return int(i) } func (p P) ...

  6. Mysql基础知识整

    web项目部署 Java项目使用的web服务器:Tomcat.weblogic.webshare.jetty Php.python使用的web服务器:nginx.apache 搭建环境过程: 部署.发 ...

  7. img的问题

    一个div的宽高比和 里面的img的宽高比是一样的 ,div  img { width:100%:height:100%;} img {border:0}   img{ 设置为border:none无 ...

  8. ACdream 1728 SJY's First Task

    简单题. 先建树,我用邻接表来存了.然后对于每个叶子结点DFS一下,DFS深度超过了K就return,找到了叶子节点就记录下来,最后排个序,然后输出答案. 由于结点编号比较奇葩,所以用两个map来转换 ...

  9. jdbc连接数据库的步骤

    1.加载JDBC驱动程序: 在连接数据库之前,首先要加载想要连接的数据库的驱动到JVM(Java虚拟机), 这通过java.lang.Class类的静态方法forName(String  classN ...

  10. 《JS权威指南学习总结--6.5枚举属性》

    内容要点: 一.for/in循环 1.for/in循环可以在循环体中遍历对象中所有可枚举的属性(包括自有属性和继承的属性),把属性名称赋值给循环变量.对象继承的内置方法不可枚举,但在代码中给对象添加的 ...