## python 实现 HTTP 请求的三中方式: urllib2/urllib,httplib/urllib 以及 Requests
urllib2/urllib 实现
urllib2 和 urllib 是 python 两个内置的模块, 要实现 HTTP 功能, 实现方式是以 urllib2 为主, urllib 为辅
1 首先实现一个完整的请求与响应模型
urllib2 提供基础函数 urlopen,
- import urllib2
- response = urllib2.urlopen('http://www.cnblogs.com/guguobao')
- html = response.read()
- print html
改进, 分两步: 请求和响应
- #!coding:utf-8
- import urllib2
- # 请求
- request = urllib2.Request('http://www.cnblogs.com/guguobao')
- # 响应
- response = urllib2.urlopen(request)
- html = response.read()
- print html
上面使用 GET 请求, 下面改为 POST 请求, 使用 urllib.
- #!coding:utf-8
- import urllib
- import urllib2
- url = 'http://www.cnblogs.com/login'
- postdata = {'username' : 'qiye',
- 'password' : 'qiye_pass'}
- #info 需要被编码为 urllib2 能理解的格式, 这里用到的是 urllib
- data = urllib.urlencode(postdata)
- req = urllib2.Request(url, data)
- response = urllib2.urlopen(req)
- html = response.read()
然而运行结果没有输出, 因为服务器拒绝你的访问, 需要检验请求头信息, 来判断是否是来自浏览器的请求
2 请求头 headers 处理
把上面的列子添加 User-Agent 域和 Referer 域信息
User-Agent: 有些服务器或 Proxy 会检查该值是否是浏览器发出的信息
Content-Type: 在使用 REST 接口时, 服务器会检查该值, 确定 HTTP body 用什么解析. 否则报错, 拒绝回应. 取值详情: http://www.runoob.com/http/http-content-type.html
Referer: 服务器检查防盗链
- #coding:utf-8
- # 请求头 headers 处理: 设置一下请求头中的 User-Agent 域和 Referer 域信息
- import urllib
- import urllib2
- url = 'http://www.xxxxxx.com/login'
- user_agent = 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)'
- referer='http://www.xxxxxx.com/'
- postdata = {'username' : 'qiye',
- 'password' : 'qiye_pass'}
- # 将 user_agent,referer 写入头信息
- headers={'User-Agent':user_agent,'Referer':referer}
- data = urllib.urlencode(postdata)
- req = urllib2.Request(url, data,headers)
- response = urllib2.urlopen(req)
- html = response.read()
3 Cookie 处理
urllib2 对 Cookie 的处理也是自动, 使用 CookieJar 函数进行 Cookie 的管理, 如果需要得到某个 Cookie 项的值, 可以这样:
- import urllib2,cookielib
- cookie = cookielib.CookieJar()
- opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cookie))
- response = opener.open('http://www.zhihu.com')
- for item in cookie:
- print item.name+':'+item.name
但有时遇到情况, 我们不想让 urllib2 自动处理, 我们想自己添加 Cookie 的内容, 可以通过设置请求头中的 cookie 域来做
- import urllib2,cookielib
- opener = urllib2.build_opener()
- opener.addheaders.append(('Cookie','email='+'helloguguobao@gmail.com'))#Cookie 和 email 替换什么值都可以, 但不能没有
- req = urllib2.Request('http://www.zhihu.com')
- response = opener.open(req)
- print response.headers
- retdata = response.read()
运行截图
4 设置 Timeout 超时
在 python2.6 及新版中, urlopen 函数提供对 Timeout 的设置:
- import urllib2
- request=urllib2.Request('http://www.zhihu.com')
- response = urllib2.urlopen(request,timeout=2)
- html=response.read()
- print html
5 获取 HTTP 响应码
只要使用 urlopen 返回的 response 对象的 getcode() 方法就可以得到 HTTP 返回码.
- import urllib2
- try:
- response = urllib2.urlopen('http://www.google.com')
- print response
- except urllib2.HTTPError as e:
- if hasattr(e, 'code'):
- print 'Error code:',e.code
6. 重定向
urllib2 默认情况下会对 HTTP 3XX 返回码自动进行重定向动作. 要检测是否发生重定向动作, 只要检查一下 Response 的 URL 和 Request 的 URL 是否一致:
- import urllib2
- response = urllib2.urlopen('http://www.zhihu.cn')
- isRedirected = response.geturl() == 'http://www.zhihu.cn'
如果不想自动重定向, 可以自定义 HTTPRedirectHandler 类:
- import urllib2
- class RedirectHandler(urllib2.HTTPRedirectHandler):
- def http_error_301(self, req, fp, code, msg, headers):
- pass
- def http_error_302(self, req, fp, code, msg, headers):
- result =urllib2.HTTPRedirectHandler.http_error_301(self,req,fp,code,msg,headers)
- result.status =code
- result.newurl = result.geturl()
- return result
- opener = urllib2.build_opener(RedirectHandler)
- opener.open('http://www.zhihu.cn')
7 Proxy 的设置
在做爬虫开发中, 可能会用到代理. urllib2 默认会使用环境变量 http_proxy 来设置 HTTP Proxy. 但是我们一般不采用这种方法, 而是使用 ProxyHandler 在程序中动态设置代理
- import urllib2
- proxy = urllib2.ProxyHandler({'http': '127.0.0.1:1080'})# 运行时需要把 socketsocks 关闭系统代理. 并使用 1080 端口, 或者直接退出 socketsocks 软件
- opener = urllib2.build_opener(proxy)
- urllib2.install_opener(opener)
- response = urllib2.urlopen('http://www.zhihu.com/')
- print response.read()
这里要注意一个细节, 使用 urllib2.install_opener() 会设置 urllib2 的全局 opener, 之后, 所有的 HTTP 访问都会使用这个代理, 这样很方便, 但是, 想在程序中使用两个不同的代理, 就不能使用 install_opener 去更改全局的设置, 而是直接调用 urllib2.open()
- import urllib2
- proxy = urllib2.ProxyHandler({'http': '127.0.0.1:1080'})
- opener = urllib2.build_opener(proxy,)
- response = opener.open("http://www.google.com/")
- print response.read()
运行时需要把 socketsocks 关闭系统代理.
来源: https://www.cnblogs.com/guguobao/p/9403730.html