零基础写python爬虫之urllib2使用指南


Posted in Python onNovember 05, 2014

前面说到了urllib2的简单入门,下面整理了一部分urllib2的使用细节。

1.Proxy 的设置

urllib2 默认会使用环境变量 http_proxy 来设置 HTTP Proxy。
如果想在程序中明确控制 Proxy 而不受环境变量的影响,可以使用代理。
新建test14来实现一个简单的代理Demo:

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) 

这里要注意的一个细节,使用 urllib2.install_opener() 会设置 urllib2 的全局 opener 。
这样后面的使用会很方便,但不能做更细致的控制,比如想在程序中使用两个不同的 Proxy 设置等。
比较好的做法是不使用 install_opener 去更改全局的设置,而只是直接调用 opener 的 open 方法代替全局的 urlopen 方法。

2.Timeout 设置

在老版 Python 中(Python2.6前),urllib2 的 API 并没有暴露 Timeout 的设置,要设置 Timeout 值,只能更改 Socket 的全局 Timeout 值。

import urllib2  

import socket  

socket.setdefaulttimeout(10) # 10 秒钟后超时  

urllib2.socket.setdefaulttimeout(10) # 另一种方式 

在 Python 2.6 以后,超时可以通过 urllib2.urlopen() 的 timeout 参数直接设置。

import urllib2  

response = urllib2.urlopen('http://www.google.com', timeout=10) 

3.在 HTTP Request 中加入特定的 Header

要加入 header,需要使用 Request 对象:

import urllib2  

request = urllib2.Request('http://www.baidu.com/')  

request.add_header('User-Agent', 'fake-client')  

response = urllib2.urlopen(request)  

print response.read() 

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

4.Redirect

urllib2 默认情况下会针对 HTTP 3XX 返回码自动进行 redirect 动作,无需人工配置。要检测是否发生了 redirect 动作,只要检查一下 Response 的 URL 和 Request 的 URL 是否一致就可以了。

import urllib2  

my_url = 'http://www.google.cn'  

response = urllib2.urlopen(my_url)  

redirected = response.geturl() == my_url  

print redirected  

my_url = 'http://rrurl.cn/b1UZuP'  

response = urllib2.urlopen(my_url)  

redirected = response.geturl() == my_url  

print redirected 

如果不想自动 redirect,除了使用更低层次的 httplib 库之外,还可以自定义HTTPRedirectHandler 类。

import urllib2  

class RedirectHandler(urllib2.HTTPRedirectHandler):  

    def http_error_301(self, req, fp, code, msg, headers):  

        print "301"  

        pass  

    def http_error_302(self, req, fp, code, msg, headers):  

        print "303"  

        pass   

opener = urllib2.build_opener(RedirectHandler)  

opener.open('http://rrurl.cn/b1UZuP') 

5.Cookie

urllib2 对 Cookie 的处理也是自动的。如果需要得到某个 Cookie 项的值,可以这么做:

import urllib2  

import cookielib  

cookie = cookielib.CookieJar()  

opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cookie))  

response = opener.open('http://www.baidu.com')  

for item in cookie:  

    print 'Name = '+item.name  

    print 'Value = '+item.value 

运行之后就会输出访问百度的Cookie值:

零基础写python爬虫之urllib2使用指南

6.使用 HTTP 的 PUT 和 DELETE 方法

urllib2 只支持 HTTP 的 GET 和 POST 方法,如果要使用 HTTP PUT 和 DELETE ,只能使用比较低层的 httplib 库。虽然如此,我们还是能通过下面的方式,使 urllib2 能够发出 PUT 或DELETE 的请求:

import urllib2  

request = urllib2.Request(uri, data=data)  

request.get_method = lambda: 'PUT' # or 'DELETE'  

response = urllib2.urlopen(request) 

7.得到 HTTP 的返回码

对于 200 OK 来说,只要使用 urlopen 返回的 response 对象的 getcode() 方法就可以得到 HTTP 的返回码。但对其它返回码来说,urlopen 会抛出异常。这时候,就要检查异常对象的 code 属性了:

import urllib2  

try:  

    response = urllib2.urlopen('http://bbs.csdn.net/why')  

except urllib2.HTTPError, e:  

    print e.code 

8.Debug Log

使用 urllib2 时,可以通过下面的方法把 debug Log 打开,这样收发包的内容就会在屏幕上打印出来,方便调试,有时可以省去抓包的工作

import urllib2  

httpHandler = urllib2.HTTPHandler(debuglevel=1)  

httpsHandler = urllib2.HTTPSHandler(debuglevel=1)  

opener = urllib2.build_opener(httpHandler, httpsHandler)  

urllib2.install_opener(opener)  

response = urllib2.urlopen('http://www.google.com') 

这样就可以看到传输的数据包内容了:

零基础写python爬虫之urllib2使用指南

9.表单的处理

登录必要填表,表单怎么填?
首先利用工具截取所要填表的内容。
比如我一般用firefox+httpfox插件来看看自己到底发送了些什么包。
以verycd为例,先找到自己发的POST请求,以及POST表单项。
可以看到verycd的话需要填username,password,continueURI,fk,login_submit这几项,其中fk是随机生成的(其实不太随机,看上去像是把epoch时间经过简单的编码生成的),需要从网页获取,也就是说得先访问一次网页,用正则表达式等工具截取返回数据中的fk项。continueURI顾名思义可以随便写,login_submit是固定的,这从源码可以看出。还有username,password那就很显然了:

# -*- coding: utf-8 -*-  

import urllib  

import urllib2  

postdata=urllib.urlencode({  

    'username':'汪小光',  

    'password':'why888',  

    'continueURI':'http://www.verycd.com/',  

    'fk':'',  

    'login_submit':'登录'  

})  

req = urllib2.Request(  

    url = 'http://secure.verycd.com/signin',  

    data = postdata  

)  

result = urllib2.urlopen(req)  

print result.read()  

10.伪装成浏览器访问

某些网站反感爬虫的到访,于是对爬虫一律拒绝请求
这时候我们需要伪装成浏览器,这可以通过修改http包中的header来实现

#…  

  

headers = {  

    'User-Agent':'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6'  

}  

req = urllib2.Request(  

    url = 'http://secure.verycd.com/signin/*/http://www.verycd.com/',  

    data = postdata,  

    headers = headers  

)  

#... 

11.对付"反盗链"

某些站点有所谓的反盗链设置,其实说穿了很简单,
就是检查你发送请求的header里面,referer站点是不是他自己,
所以我们只需要像把headers的referer改成该网站即可,以cnbeta为例:
#...
headers = {
    'Referer':'http://www.cnbeta.com/articles'
}
#...
headers是一个dict数据结构,你可以放入任何想要的header,来做一些伪装。
例如,有些网站喜欢读取header中的X-Forwarded-For来看看人家的真实IP,可以直接把X-Forwarde-For改了。

Python 相关文章推荐
python查看微信好友是否删除自己
Dec 19 Python
python脚本爬取字体文件的实现方法
Apr 29 Python
python 输入一个数n,求n个数求乘或求和的实例
Nov 13 Python
在python中实现强制关闭线程的示例
Jan 22 Python
Python 实现数据结构-循环队列的操作方法
Jul 17 Python
Django Aggregation聚合使用方法解析
Aug 01 Python
django中瀑布流写法实例代码
Oct 14 Python
Python实现图片添加文字
Nov 26 Python
python requests.get带header
May 05 Python
Python with语句用法原理详解
Jul 03 Python
python实现测试工具(一)——命令行发送get请求
Oct 19 Python
selenium+python自动化78-autoit参数化与批量上传功能的实现
Mar 04 Python
零基础写python爬虫之urllib2中的两个重要概念:Openers和Handlers
Nov 05 #Python
零基础写python爬虫之HTTP异常处理
Nov 05 #Python
零基础写python爬虫之使用urllib2组件抓取网页内容
Nov 04 #Python
零基础写python爬虫之爬虫的定义及URL构成
Nov 04 #Python
使用Python编写简单网络爬虫抓取视频下载资源
Nov 04 #Python
Python爬取Coursera课程资源的详细过程
Nov 04 #Python
使用python开发vim插件及心得分享
Nov 04 #Python
You might like
php miniBB中文乱码问题解决方法
2008/11/25 PHP
分享一段php获取linux服务器状态的代码
2014/05/27 PHP
PHP时间和日期函数详解
2015/05/08 PHP
解读PHP中上传文件的处理问题
2016/05/29 PHP
jQuery动态添加删除select项(实现代码)
2013/09/03 Javascript
一款由jquery实现的整屏切换特效
2014/09/15 Javascript
jQuery中$.get、$.post、$.getJSON和$.ajax的用法详解
2014/11/19 Javascript
jQuery实现Flash效果上下翻动的中英文导航菜单代码
2015/09/22 Javascript
深入剖析JavaScript编程中的对象概念
2015/10/21 Javascript
微信小程序中显示html格式内容的方法
2017/04/25 Javascript
使用jQuery实现两个div中按钮互换位置的实例代码
2017/09/21 jQuery
js设置随机切换背景图片的简单实例
2017/11/12 Javascript
JavaScript 中定义函数用 var foo = function () {} 和 function foo()区别介绍
2018/03/01 Javascript
vue v-model动态生成详解
2018/06/30 Javascript
vue检测对象和数组的变化分析
2018/06/30 Javascript
Vue脚手架的简单使用实例
2018/07/10 Javascript
vue实现点击隐藏与显示实例分享
2019/02/13 Javascript
原生JS forEach()和map()遍历的区别、兼容写法及jQuery $.each、$.map遍历操作
2019/02/27 jQuery
迅速了解一下ES10中Object.fromEntries的用法使用
2019/03/05 Javascript
微信小程序分享功能onShareAppMessage(options)用法分析
2019/04/24 Javascript
Vue 动态添加路由及生成菜单的方法示例
2019/06/20 Javascript
Vue数据双向绑定底层实现原理
2019/11/22 Javascript
jQuery实现移动端扭蛋机抽奖
2020/11/08 jQuery
Python 字符串定义
2009/09/25 Python
Python实现字典去除重复的方法示例
2017/07/31 Python
python3.6的venv模块使用详解
2018/08/01 Python
flask session组件的使用示例
2018/12/25 Python
详解Python中的format格式化函数的使用方法
2019/11/20 Python
Python 实现自动登录+点击+滑动验证功能
2020/06/10 Python
关于HTML5 Placeholder新标签低版本浏览器下不兼容的问题分析及解决办法
2016/01/27 HTML / CSS
UNIONBAY官网:美国青少年服装品牌
2019/03/26 全球购物
优秀大专毕业生求职信
2014/08/04 职场文书
应届生个人的求职(自荐信范文2篇)
2019/08/23 职场文书
css3中2D转换之有趣的transform形变效果
2022/02/24 HTML / CSS
spring注解 @PropertySource配置数据源全流程
2022/03/25 Java/Android
Three.js实现雪糕地球的使用示例详解
2022/07/07 Javascript