pythonurllib - juedaiyuer/researchNote GitHub Wiki

#urllib#

##扒网页##

扒下一个网页

import urllib2
response = urllib2.urlopen("http://www.baidu.com")
print response.read()

urlopen的参数

urlopen(url,data,timeout)

data,timeout可以不传送
data默认为空None
timeout默认为socket._GLOBAL_DEFAULT_TIMEOUT

response对象有一个read方法,可以返回获取到的网页内容
直接打印response,打印出了该对象的描述

>>> print response
<addinfourl at 140230693113584 whose fp = <socket._fileobject object at 0x7f8a0334bbd0>>

##构造Request##

urlopen参数可以传入一个request请求,它其实就是一个Request类的实例,构造时需要传入url,data等内容;构建请求时需要加入好多内容,通过构建一个request,服务器响应请求得到应答

import urllib2

request = urllib2.Request("http://www.baidu.com")
response = urllib2.urlopen(request)
print response.read()

##POST和GET数据传送##

动态网页,需要动态地传递参数给它,做出对应的响应,最常见的情况是登录注册

把数据用户名和密码传送到一个URL,得到服务器处理之后的响应

数据传送分为POST和GET两种方式:

  1. GET方式是直接以链接形式访问,链接中包含了所有的参数,如果包含了密码的话是一种不安全的选择,但是可以直接看到自己提交了什么内容
  2. POST则不会在网址上显示所有的参数

###POST方式###

登录CSDN的例子

import urllib
import urllib2

values = {"username":"[email protected]","password":"XXXX"}
data = urllib.urlencode(values) 
url = "https://passport.csdn.net/account/login?from=http://my.csdn.net/my/mycsdn"
request = urllib2.Request(url,data)
response = urllib2.urlopen(request)
print response.read()

下面的代码等价于上面的代码

import urllib
import urllib2

values={}
values['username'] = "[email protected]"
values['password']="XXXX"
data = urllib.urlencode(values) 
url = "http://passport.csdn.net/account/login"
geturl = url + "?"+data
request = urllib2.Request(geturl)
response = urllib2.urlopen(request)
print response.read()

##设置Headers##

有些网站不会同意程序直接用上面的方式进行访问,如果识别有问题,那么站点根本不会响应,为了完全模拟浏览器的工作,需要设置一些Headers的属性

agent就是请求的身份,如果没有写入请求身份,服务器不一定会响应。下面的例子只是说明了怎样设置headers,看一下它的设置格式

import urllib  
import urllib2  

url = 'http://www.server.com/login'
user_agent = 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)'  
values = {'username' : 'cqc',  'password' : 'XXXX' }  
headers = { 'User-Agent' : user_agent }  
data = urllib.urlencode(values)  
request = urllib2.Request(url, data, headers)  
response = urllib2.urlopen(request)  
page = response.read()

对付防盗链,服务器会识别headers中的referer是不是它自己,如果不是,有的服务器不会响应

headers = { 'User-Agent' : 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)','Referer':'http://www.zhihu.com/articles' }

##headers的一些属性##

User-Agent : 有些服务器或Proxy会通过该值来判断是否是浏览器发出的请求
Content-Type : 在使用 REST 接口时,服务器会检查该值,用来确定 HTTP Body 中的内容该怎样解析
application/xml : 在XML RPC,如RESTful/SOAP调用时使用
application/json : 在 SON RPC调用时使用
application/x-www-form-urlencoded : 浏览器提交Web表单时使用
在使用服务器提供的 RESTful 或 SOAP 服务时, Content-Type设置错误会导致服务器拒绝服务

##Proxy(代理)的设置##

urllib2默认会使用环境变量http_proxy来设置HTTP Proxy
假如一个网站它会检测某一段时间某个IP 的访问次数,如果访问次数过多,它会禁止你的访问
所以你可以设置一些代理服务器来帮助你做工作,每隔一段时间换一个代理

import urllib2
enable_proxy = True
proxy_handler = urllib2.ProxyHandler({"http" : 'http://some-proxy.com:8080'})
null_proxy_handler = urllib2.ProxyHandler({})
if enable_proxy:
    opener = urllib2.build_opener(proxy_handler)
else:
    opener = urllib2.build_opener(null_proxy_handler)
urllib2.install_opener(opener)

##使用HTTP的PUT和DELETE方法##

http协议有六种请求方法,get,head,put,delete,post,options

PUT:这个方法比较少见。HTML表单也不支持这个。本质上来讲, PUT和POST极为相似,都是向服务器发送数据,但它们之间有一个重要区别,PUT通常指定了资源的存放位置,而POST则没有,POST的数据存放位置由服务器自己决定。

DELETE:删除某一个资源。基本上这个也很少见,不过还是有一些地方比如amazon的S3云服务里面就用的这个方法来删除资源

##URLError##

存在的原因:

  • 网络无连接,即本机无法上网
  • 连接不到特定的服务器
  • 服务器不存在

在代码中,我们需要用try-except语句来包围并捕获相应的异常

import urllib2

requset = urllib2.Request('http://www.xxxxx.com')
try:
    urllib2.urlopen(requset)
except urllib2.URLError, e:
    print e.reason

##HTTPError##

HTTPError是URLError的子类,在你利用urlopen方法发出一个请求时,服务器上都会对应一个应答对象response,其中它包含一个数字”状态码”

其他不能处理的,urlopen会产生一个HTTPError,对应相应的状态吗,HTTP状态码表示HTTP协议所返回的响应的状态。

HTTPError实例产生后会有一个code属性,这就是是服务器发送的相关错误号

因为urllib2可以为你处理重定向,也就是3开头的代号可以被处理,并且100-299范围的号码指示成功,所以你只能看到400-599的错误号码

import urllib2

req = urllib2.Request('http://blog.csdn.net/cqcre')
try:
    urllib2.urlopen(req)
except urllib2.HTTPError, e:
    print e.code
    print e.reason

运行结果

403
Forbidden

HTTPError的父类是URLError,根据编程经验,父类的异常应当写到子类异常的后面,如果子类捕获不到,那么可以捕获父类的异常,所以上述的代码可以这么改写

import urllib2

req = urllib2.Request('http://blog.csdn.net/cqcre')
try:
    urllib2.urlopen(req)
except urllib2.HTTPError, e:
    print e.code
except urllib2.URLError, e:
    print e.reason
else:
    print "OK"

另外还可以加入 hasattr属性提前对属性进行判断,代码改写如下

import urllib2

req = urllib2.Request('http://blog.csdn.net/cqcre')
try:
    urllib2.urlopen(req)
except urllib2.URLError, e:
    if hasattr(e,"code"):
        print e.code
    if hasattr(e,"reason"):
        print e.reason
else:
    print "OK"

##source##