urllib2模块
说明:
- python2.7不需要额外安装urllib2模块,因为urllib2是python2.7的自带模块
- urllib2官方文档:https://docs.python.org/2/library/urllib2.html
- urllib2源码:https://hg.python.org/cpython/file/2.7/Lib/urllib2.py
- urllib2在python3中被修改为urllib.request
1 #! usr/bin/env python 2 #-*-coding:utf-8-*- 3 import urllib2 #引入urllib库 4 response = urllib2.urlopen("http://www.baidu.com") #使用urllib2的urlopen()方法去获取百度主页,返回一个response对象 5 html = response.read() #使用response的read()方法可以将返回的主页信息转换成字符串赋值给html变量 6 print html #打印html
1 ============================================================ 2 Urllib2爬虫 3 ============================================================ 4 5 URLlib2基本操作: 6 1 7 ---------------------------------------------------------------------------------------------------------------------------------------------------------- 8 | import urllib2 9 | response = urllib2.open("http://www.baidu.com") # 使用urllib2.open()方法发送请求,并返回服务器响应的类文件对象 10 | html = response.read() # 类文件对象支持文件对象操作方法,如read()方法读取返回文件对象的全部内容并将其转换成字符串格式并赋值给html变量 11 | print html # 打印html变量,即可显示出整个页面 12 | 13 ---------------------------------------------------------------------------------------------------------------------------------------------------------- 14 15 2 16 ---------------------------------------------------------------------------------------------------------------------------------------------------------- 17 | import urllib2 18 | request = urllib2.Request("http://www.baidu.com") # 使用将urllib2.Request()实例化,需要访问的URL地址则作为Request实例的参数 19 | response = urllib2.urlopen(request) # Request对象作为urlopen()方法的参数,发送给服务器并接收响应的类文件对象 20 | html = response.read() # 类文件对象支持文件对象操作方法,如read()方法读取返回文件对象的全部内容并将其转换成字符串格式并赋值给html变量 21 | print html # 打印字符串 22 | 23 ---------------------------------------------------------------------------------------------------------------------------------------------------------- 24 25 3 26 ---------------------------------------------------------------------------------------------------------------------------------------------------------- 27 | import urllib2 28 | url = "http://www.baidu.com" 29 | ua_header = {"User-Agent":"Mozzila/5.0(compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0;"} 30 | request = urllib2.Reuqest(url,headers=ua_header) # url连同headers一起构造Request请求,这个请求将附带IE9.0浏览器的User-Agent 31 | response = urllib2.urlopen(request) # 向服务器发送这个请求并接收响应的类文件对象 32 | html = response.read() # 类文件对象支持文件对象操作方法,如read()方法读取返回文件对象的全部内容并将其转换成字符串格式并赋值给html变量 33 | print html # 打印字符串 34 | 35 ---------------------------------------------------------------------------------------------------------------------------------------------------------- 36 37 4 38 ---------------------------------------------------------------------------------------------------------------------------------------------------------- 39 | import urllib2 40 | url = "http://www.itcast.cn" 41 | ua = {"User-Agent":"Mozzila/5.0(compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0;"} 42 | request = urllib2.Request(url,headers = ua) # IE9.0的User-Agent 43 | request.add_header("Connection":"keep-alive") # 也可以通过Request.add_header()添加/修改一个特定的header 44 | response = urllib2.urlopen(request) 45 | html = response.read() 46 | print html 47 | print response.code 48 | print request.get_header("Connection") # 查看响应状态码 49 | print request.get_header(header_name = "Connection") # 也可以通过Request.get_header()查看header信息 50 | 51 ---------------------------------------------------------------------------------------------------------------------------------------------------------- 52 53 54 5.随机添加/修改User-Agent 55 ---------------------------------------------------------------------------------------------------------------------------------------------------------- 56 | import urllib2 57 | import random 58 | 59 | url = "http://www.baidu.com" 60 | ua_list = [ 61 | "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv2.0.1) Gecko/20100101 Firefox/4.0.1", 62 | "Mozilla/5.0 (Windows NT 6.1; rv2.0.1) Gecko/20100101 Firefox/4.0.1", 63 | "Opera/9.80 (Macintosh; Intel Mac OS X 10.6.8; U; en) Presto/2.8.131 Version/11.11", 64 | "Opera/9.80 (Windows NT 6.1; U; en) Presto/2.8.131 Version/11.11", 65 | "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_0) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11" 66 | ] 67 | user_agent = random.choice(ua_list) 68 | print user_agent 69 | request = urllib2.Request(url) 70 | request.add_header("User-Agent",user_agent) # 也可以通过Request.add_header()添加/修改一个特定的header 71 | response = urllib2.urlopen(request) 72 | html = response.read() 73 | print html 74 | print response.get_header("User-agent") # 注意:第一个字母大写,后面的全部小写 75 | 76 ---------------------------------------------------------------------------------------------------------------------------------------------------------- 77 78 79 6.网络编码格式转换 ---- urllib2的post之urllib.urlencode() 80 ---------------------------------------------------------------------------------------------------------------------------------------------------------- 81 | import urllib2 82 | import urllib #引入urllib负责url编码处理 83 | 84 | url = "http://www.baidu.com" 85 | word = {"wd":"长城"} 86 | word = urllib.urlencode(word) # 转换成url编码格式(字符串) 87 | fullurl = url + "?" + word # url首个分隔符就是? 88 | headers = {"User-Agent":"Mozilla/5.0 (Windows NT 6.1; rv 2.0.1) Gecko/20100101 Firefox/4.0.1"} 89 | request = urllib2.Reuqest(fullurl,headers=headers) 90 | response = urllib2.urlopen(request) 91 | html = response.read() 92 | print html 93 | 94 ---------------------------------------------------------------------------------------------------------------------------------------------------------- 95 96 97 7.百度贴吧爬取(post请求的应用) 98 ---------------------------------------------------------------------------------------------------------------------------------------------------------- 99 | import urllib 100 | import urllib2 101 | 102 | def load_page(fullurl,filename): 103 | print "正在下载" + filename 104 | headers = {"User-Agent":"Mozilla/5.0 (Windows NT 6.1; rv 2.0.1) Gecko/20100101 Firefox/4.0.1"} 105 | request = urllib.Reuqest(fullurl,headers=headers) 106 | response = urllib2.urlopen(request) 107 | return response.read() 108 | 109 | def write_page(html,filename): 110 | print "正在存储" + str(filename) 111 | with open(filename,"w") as f: 112 | f.write(html) 113 | print "-"*30 114 | 115 | def tieba_spider(url,beginpage,endpage): 116 | for page in range(beginpage,endpage+1): 117 | filename = "第" + str(page) + "页" 118 | pn = (page-1)*50 119 | fullurl = url + "&pn" + str(pn) 120 | html = load_page(fullurl,filename) 121 | write_page(html,filename) 122 | 123 | if __name__ == "__main__": 124 | kw = raw_input("请输入需要爬取的贴吧名:") 125 | beginpage = raw_input("请输入爬取的起始页:") 126 | endpage = raw_input("请输入爬取的终止页:") 127 | url = "http://tieba.baidu.com/f?" 128 | kw = urllib.urlencode(kw) 129 | url = url + kw 130 | 131 | tieba_spider(url,beginpage,endpage) 132 | 133 | 134 ---------------------------------------------------------------------------------------------------------------------------------------------------------- 135 136 137 8.有道翻译(post请求的应用) 138 ---------------------------------------------------------------------------------------------------------------------------------------------------------- 139 | import urllib 140 | import urllib2 141 | 142 | key = raw_input("请输入需要翻译的内容:") 143 | url = "http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule&sessionFrom=null" 144 | headers = { 145 | "Accept" : "application/json, text/javascript, */*; q=0.01", 146 | "X-Requested-With" : "XMLHttpRequest", 147 | "User-Agent" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36", 148 | "Content-Type" : "application/x-www-form-urlencoded; charset=UTF-8", 149 | } 150 | formdata = { 151 | "i" : key, 152 | "from" : "AUTO", 153 | "to" : "AUTO", 154 | "smartresult":"dict", 155 | "client" : "fanyideskweb", 156 | "doctype" : "json", 157 | "version":"2.1", 158 | "keyfrom" : "fanyi.web", 159 | "action" : "FY_BY_ENTER", 160 | "typoResult" : "true" 161 | } 162 | 163 | data = urllib.urlencode(formdata) 164 | request = urllib2.Request(url,data=data,headers=headers) 165 | response = urllib2.urlopen(request) 166 | print response.read() 167 | 168 ---------------------------------------------------------------------------------------------------------------------------------------------------------- 169 170 171 9 获取Ajax加载内容(post请求的应用) 豆瓣电影top100前20 172 ---------------------------------------------------------------------------------------------------------------------------------------------------------- 173 | import urllib 174 | import urllib2 175 | 176 | url = "https://movie.douban.com/j/chart/top_list?type=11&interval_id=100%3A90&action" 177 | headers = {"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"} 178 | formdata = { # 变动的是这两个参数,从start开始往后显示limit个数据 179 | "start":"0", # 这两个参数会在发送post请求的时候自定添加到url中 180 | "limit":"20" 181 | } 182 | data = urllib.urlencode(formdata) 183 | request = urllib2.Request(url,data=data,headers=headers) 184 | response = urllib2.urlopen(request) 185 | print response.read() 186 | 187 ---------------------------------------------------------------------------------------------------------------------------------------------------------- 188 189 190 10.忽略HTTPS请求SSL证书验证(post请求的应用) 12306忽略https证书验证 191 ---------------------------------------------------------------------------------------------------------------------------------------------------------- 192 | import urllib2 193 | import ssl # 导入Python SSL处理模块 194 | 195 | context = ssl._create_unverified_context() # 表示忽略未经核实的SSL证书认证 196 | url = "https://www.12306.cn/mormhweb" 197 | headers = {"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"} 198 | request = urllib2.Request(url,headers=headers) 199 | response = urllib2.urlopen(request,context = context) # 注意这里使用的是context参数,是没有放在Request中的,而是在urlopen中指明context参数 200 | print response.read() 201 | 202 ---------------------------------------------------------------------------------------------------------------------------------------------------------- 203 204 205 URLllib2自定义opener 206 207 208 准备知识:Handler处理器和自定义Opener 209 ---------------------------------------------------------------------------------------------------------------------------------------------------------- 210 | opener是 urllib2.OpenerDirector 的实例,我们之前一直都在使用的urlopen,它是一个特殊的opener(也就是模块帮我们构建好的)。 211 | 212 | 但是基本的urlopen()方法不支持代理、cookie等其他的HTTP/HTTPS高级功能。所以要支持这些功能: 213 | 214 | 步骤1: 创建处理器对象----使用相关的 Handler处理器 来创建特定功能的处理器对象; 215 | 216 | 步骤2: 创建opener对象----通过 urllib2.build_opener()方法使用这些处理器对象,创建自定义opener对象; 217 | 218 | 步骤3: 使用opener对象----调用自定义的opener对象的open()方法发送请求。 219 | 220 | 根据需要,可以使用urllib2.install_opener()将自定义的opener定义为全局opener,表示如果之后凡是调用urlopen,都将使用这个opener 221 | 222 ---------------------------------------------------------------------------------------------------------------------------------------------------------- 223 224 225 1.利用HTTPHandler处理器创建支持处理HTTP请求的opener 226 ---------------------------------------------------------------------------------------------------------------------------------------------------------- 227 | imort urllib2 228 | http_handler = urllib2.HTTPHandler() # 第一步:创建处理器对象(这里:创建一个(支持处理HTTP请求)的HTTPHandler处理器对象) 229 | http_opener = urllib2.build_opener(http_handler) # 第二步:创建opener对象(这里:调用urllib2.build_opener()方法来创建(支持HTTP请求)的opener对象) 230 | http_response = http_opener.open("http://www.baidu.com") # 第三步:使用opener对象(这里:调用opener对象的open()方法发送request请求) 231 | print http_response.read() # 打印服务器响应内容 232 | 233 | 这种方式发送请求得到的结果,和使用urllib2.urlopen()发送HTTP请求得到的结果是一样的。 234 | 如果在 HTTPHandler()增加 debuglevel=1参数,即(HTTPHandler(debuglevel=1)),还会将DebugLog 打开, 235 | 这样程序在执行的时候,会把收包和发包的报头在屏幕上自动打印出来,方便调试,有时可以省去抓包的工作。 236 | 237 ---------------------------------------------------------------------------------------------------------------------------------------------------------- 238 239 240 241 2.利用HTTPShandler处理器创建支持处理HTTPS请求的opener 242 ---------------------------------------------------------------------------------------------------------------------------------------------------------- 243 | import urllib2 244 | https_handler = urllib2.HTTPSHandler() # 第一步:创建处理器对象(这里:创建一个(支持处理HTTP请求)的HTTPHandler处理器对象) 245 | https_opener = urllib2.build_opener(https_handler) # 第二步:创建opener对象(这里:build_opener()方法来创建(支持HTTP请求)的opener对象) 246 | https_response = https_opener.open("https://www.12306.cn/mormhweb/") # 第三步:使用opener对象(这里:调用opener对象的open()方法发送request请求) 247 | print https_response.read() # 打印服务器响应内容 248 | 249 | 这种方式发送请求得到的结果,和使用urllib2.urlopen()发送HTTPS请求得到的结果是一样的。 250 | 如果在 HTTPSHandler()增加 debuglevel=1参数,即(HTTPSHandler(debuglevel=1)),还会将DebugLog 打开, 251 | 这样程序在执行的时候,会把收包和发包的报头在屏幕上自动打印出来,方便调试,有时可以省去抓包的工作。 252 | 253 ---------------------------------------------------------------------------------------------------------------------------------------------------------- 254 255 256 3.利用ProxyHandler处理器创建支持非私密代理访问的opener 257 ---------------------------------------------------------------------------------------------------------------------------------------------------------- 258 | 259 | import urllib2 260 | 261 | have_proxy_handler = urllib2.ProxyHandler({"http":"122.72.18.35:80"}) # 第一步:创建处理器对象(这里:创建一个(支持有代理)和一个(支持无代理)的ProxyHandler处理器对象) 262 | null_proxy_handler = urllib2.ProxyHandler({}) 263 | proxy_switch = True # 创建了一个是否使用代理的开关, 264 | if proxy_switch: # 第二步:创建opener对象(这里:调用build_opener()方法来创建opener对象) 265 | opener = urllib2.build_opener(have_proxy_handler) # 如果代理开关打开,则创建一个支持有代理的opener对象 266 | else: 267 | opener = urllib2.build_opener(null_proxy_handler) # 如果代理开关关闭,则创建一个支持无代理的opener对象 268 | request = urllib2.Request("http://www.baidu.com") 269 | response = opener.open(request) # 第三步:使用opener对象(这里:调用opener对象的open()方法发送request请求) 270 | print response.read() 271 | 272 | 273 | 附加1:选择随机代理去访问制定网页 274 | ------------------------------------------------------------------------------------------------------------------------------------------------------- 275 | #如果代理IP足够多,就可以像随机获取User-Agent一样,随机选择一个代理去访问网站。 276 | 277 | #!/usr/bin/env python 278 | #coding:utf-8 279 | 280 | import urllib2 281 | import random #引入随机模块 282 | 283 | proxy_list = [ # 创建一个可供选择的随机代理列表 284 | {"http":"200.200.200.200:80"}, 285 | {"http":"200.200.200.201:8080"}, 286 | {"http":"200.200.200.202:808"}, 287 | {"http":"200.200.200.203:880"}, 288 | ] 289 | proxy = random.choice(proxy_list) # 从列表中随机选择一个代理 290 | proxy_handler = urllib2.ProxyHandler(proxy_list) # 第一步:创建处理器对象(这里创建一个(支持有代理)的ProxyHandler处理器对象) 291 | proxy_opener = urllib2.build_opener(proxy_handler) # 第二步:创建opener对象(这里:调用urllib2.build_opener()方法来创建opener对象) 292 | response = proxy_opener.open("http://www.baidu.com") # 第三步:使用opener对象(这里:调用opener对象的open()方法发送request请求) 293 | print response.read() 294 | 295 | 296 | 附加2:采用ProxyHandler处理器创建支持私密代理访问的opener(代码中直接显示用户名和密码) 297 | ---------------------------------------------------------------------------------------------------------------------------------------------------------- 298 | #ProxyHandler处理器也能创建支持私密代理的opener 299 | 300 | import urllib2 # 第一步:创建处理器对象(这里创建一个(支持私密代理验证) 的ProxyHandler处理器)----注意验证用户名\密码\代理IP\端口的写法 301 | authproxy_handler = urllib2.ProxyHandler({"http":"mr_mao_hacker:sffqry9r@61.158.163.130:16816"}) 302 | opener = urllib2.build_opener(authproxy_handler) # 第二步:创建opener对象 303 | response = opener.open("http://www.baidu.com") # 第三步:使用opener对象 304 | print response.read() 305 | 306 | 307 | 附加3:采用ProxyHandler处理器创建支持私密代理访问的opener(代码中隐藏用户名和密码) 308 | ---------------------------------------------------------------------------------------------------------------------------------------------------------- 309 | #将用户名和密码保存为环境变量,通过获取环境变量的方式获得用户名和密码,从而在代码中隐藏用户名和密码 310 | 311 | import urllib2 312 | import os 313 | proxyuser = os.environ.get("proxyuser") # 获取存放在环境变量中的授权代理用户名/密码 314 | proxypasswd = os.environ.get("proxypasswd") # 第一步:创建处理器对象(这里创建一个(支持私密代理验证)的ProxyHanlder处理器)------采用用户名/密码/代理IP/端口采用拼接的方式 315 | authproxy_handler = urllib2.ProxyHandler({"http":proxyuser+":"+proxypasswd+"@61.158.163.130:16816"}) 316 | opener = urllib2.build_opener(authproxy_handler) # 第二步:创建opener对象(这里:调用urllib2.build_opener()方法来创建opener对象) 317 | request = urllib2.Request("http://www.baidu.com") # 构建请求 318 | response = opener.open(request) # 第三步:使用opener对象(这里:调用opener对象的open()方法发送request请求) 319 | print response.read() 320 | 321 | #错误知晓:如果私密代理用户名或密码错误,会报407错误(HTTP Error 407: Proxy Authentication Required)表示代理没有通过身份验证. 322 | #注意:ProxyHandler()处理器虽然也能够创建支持私密代理的opener对象,但是专业的还是下面的ProxyBasicAuthHandler()处理器(专门进行私密代理授权验证) 323 | 324 ---------------------------------------------------------------------------------------------------------------------------------------------------------- 325 326 327 4.利用ProxyBasicAuthHandler(代理授权验证)处理器创建支持私密代理访问的opener 328 ---------------------------------------------------------------------------------------------------------------------------------------------------------- 329 | 330 | 准备知识:HTTPPasswordMgrWithDefaultRealm()类 331 | ---------------------------------------------------- 332 | HTTPPasswordMgrWithDefaultRealm()类将创建一个密码管理对象,用来保存HTTP请求相关的用户名和密码,主要有两个应用场景: 333 | (1).验证代理授权的用户名和密码(ProxyBasicAuthHandler) 334 | (2).验证web客户端的用户名和密码(HTTPBasicAuthHandler) 335 | 336 | 代码思路: 337 | (1)使用HTTPPasswordMgrWithDefaultRealm()来保存私密代理的用户名和密码 338 | (2)使用ProxyBasicAuthHandler()来处理代理的身份验证 339 | 340 | import urllib2 341 | user = "mr_mao_hacker" # 设置代理账户/密码/代码IP端口 342 | passwd = "sffqry9r" 343 | proxy_server = "61.158.163.130:16816" 344 | passwdmgr = urllib2.HTTPPasswordMgrWithDefaultRealm() # 创建一个密码管理器对象,用来保存代理账户/密码/代理IP端口 345 | passwdmgr.add_password(None,proxy_server,user,passwd) # 将设置好的代理账户/密码/代理IP端口信息保存到这个密码管理器对象中 346 | proxy_auth_handler = urllib2.ProxyBasicAuthHandler(passwdmgr) # 第一步:创建处理器对象(这里创建一个(私密代理验证)的ProxyBasicAuthHanlder处理器)----传入的参数是密码管理器对象 347 | opener = urllib2.build_opener(proxy_auth_handler) # 第二步:创建opener对象(这里:调用build_opener()方法来创建opener对象) 348 | request = urllib2.Request("http://www.baidu.com") # 构建请求 349 | response = opener.open(request) # 第三步:使用opener对象(这里:调用opener对象的open()方法发送request请求) 350 | print response.read() 351 | 352 | # 也可以采用上述将用户名/密码设置成环境变量的方式,避免直接在代码中出现明显的用户名/密码信息!! 353 | 354 ---------------------------------------------------------------------------------------------------------------------------------------------------------- 355 356 357 5.利用HTTPBasicAuthHandler(web客户端授权验证)处理器创建访问web页面需要用户身份验证的opener 358 ---------------------------------------------------------------------------------------------------------------------------------------------------------- 359 | # 有些web服务器(包括HTTP/FTP等)访问时,需要进行用户身份验证,爬虫直接访问会报HTTP 401错误(HTTP Error 401: Unauthorized)表示访问身份未经授权 360 | # 如果我们有这些web服务器的用户名和密码,就可通过下述方法去访问爬取 361 | 362 | 代码思路: 363 | ---------------------------------------------------- 364 | (1) 使用HTTPPasswordMgrWithDefaultRealm()来保存web客户端的用户名和密码 365 | (2) 使用ProxyBasicAuthHandler()来处理web客户端的身份验证 366 | 367 | import urllib2 368 | user = "zhangsan" # 设置代理账户/密码/代码IP端口 369 | passwd = "123456" 370 | web_server = "http://200.200.200.200:80" 371 | passwdmgr = urllib2.HTTPPasswordMgrWithDefaultRealm() # 创建一个密码管理器对象,用来保存代理账户/密码/代理IP端口 372 | passwdmgr.add_password(None,web_server,user,passwd) # 将设置好的代理账户/密码/代理IP端口信息保存到这个密码管理器对象中 373 | http_auth_handler = urllib2.HTTPBasicAuthHandler(passwdmgr) # 第一步:创建处理器对象(这里创建一个(web客户端授权验证)的HTTPBasicAuthHandler处理器)----传入的参数是密码管理器对象 374 | opener = urllib2.build_opener(http_auth_handler) # 第二步:创建opener对象(这里:调用urllib2.build_opener()方法来创建opener对象) 375 | urllib2.install_opener(opener) # 如果需要,可以选择通过install_opener()方法将自定义的opener定义为全局的opener 376 | request = urllib2.Request("http://www.baidu.com") # 创建请求 377 | response = urllib2.urlopen(request) # 第三步:使用opener对象(因为自定义opener被定义为全局opener,这里:可使用urllib2.urlopen()方法调用opener对象发送request请求) 378 | print response.read() 379 | 380 ---------------------------------------------------------------------------------------------------------------------------------------------------------- 381 382 383 6.利用HTTPCookieProcessor处理器创建支持处理cookie的opener 384 ---------------------------------------------------------------------------------------------------------------------------------------------------------- 385 | 386 | 预先了解:cookie/cookie原理/cookie格式 387 | ---------------------------------------------------- 388 | cookie: 是指某些网站服务器为了辨别用户身份和进行session跟踪,而储存在用户浏览器上的文本文件,cookie可以保持登陆信息到用户下次与服务器的对话. 389 | 390 | cookie原理: HTTP是无状态的面向连接的协议,为了保存连接状态,引入了cookie机制,cookie是http消息头部中的一种属性包括: 391 | cookie名字(Name)/值(Value)/过期时间(Expires/Max-Age)/作用路径(Path)/所在域名(Domain)/使用cookie进行安全连接(Secure) (Name和Value是cookie的必要条件) 392 | 393 | cookie格式: (cookie由变量名和值组成)-----Set-Cookie: NAME=VALUE;Expires=DATE;Path=PATH;Domain=DOMAIN_NAME;SECURE 394 | 395 | 396 | 预先案例:通过post抓包工具抓取到的有登陆信息的完整cookie信息模拟登陆之前已登录的人人网页 397 | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- 398 | | cookie在爬虫方面最典型的应用是判定注册用户是否已经登陆网站,用户可能会得到提示,是否在下一次进入此网站时保留用户信息以便简化登陆手续. 399 | | 400 | | import urllib2 401 | | "Host":"www.renren.com", 402 | | 403 | | headers = { # 1. 构建一个已经登录过的用户的headers信息 404 | | "Connection":"keep-alive", 405 | | "Upgrade-Insercure-Reuqests":"1", 406 | | "User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36", 407 | | "Accept":"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", 408 | | "Accept-Language":"zh-CN,zh;q=0.8,en;q=0.6", 409 | | # Accept-Encoding: gzip, deflate, sdch, # 便于终端阅读,表示不支持压缩文件 410 | | "Cookie": " ln_uact=mr_mao_hacker@163.com; id=327550029; xnsid=745033c5; ver=7.0;...... " 411 | | } # 重点:这个cookie是保存了密码无需重复登录的用户的cookie,这个Cookie里记录了用户名,密码(通常经过RAS加密) 412 | | 413 | | request = urllib2.Request("http://www.renren.com",headers = headers) # 2. 通过headers里的报头信息(主要是Cookie信息),构建Request对象 414 | | response = urllib2.urlopen(request) # 3. 直接访问renren主页,服务器会根据headers报头信息(主要是Cookie信息),判断这是一个已经登录的用户,并返回相应的页面 415 | | print response.read() # 4. 打印响应内容(会看到"人人网-毛兆军") 416 | | 417 | | # 这种方式虽然能够获取一个有登录信息的Cookie实现模拟登陆,但是太过复杂,我们需要首先在浏览器登陆账户,并且设置保存密码,并且通过抓包工具才能获得这个cookie,为了不使 418 | | 用这么复杂的方式,于是下面利用cookielib库和HTTPCookieProcessor处理器的简单方法应运而生! 419 | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- 420 | 421 | 422 | 预先了解:cookielib库 423 | ---------------------------------------------------- 424 | cookielib模块的主要对象有CookieJar、FileCookieJar、MozillaCookieJar、LWPCookieJar 425 | (1)CookieJar(): 整个cookie都存储在内存中,对CookieJar实例进行垃圾回收后cookie也将丢失.用于管理HTTP cookie值、存储HTTP请求生成的cookie、向传出的HTTP请求添加cookie的对象. 426 | (2)FileCookieJar(filename,delayload=None,policy=None): 从CookieJar派生而来,用来创建FileCookieJar实例,检索cookie信息并将cookie存储到文件中。filename是存储cookie的文件名, 427 | delayload为True时支持延迟访问访问文件,即只有在需要时才读取文件或在文件中存储数据。 428 | (3)MozillaCookieJar(filename,delayload=None,policy=None): 从FileCookieJar派生而来,创建与Mozilla浏览器 cookies.txt兼容的FileCookieJar实例。 429 | (4)LWPCookieJar(filename,delayload=None,policy=None): 从FileCookieJar派生而来,创建与libwww-perl标准的 Set-Cookie3 文件格式兼容的FileCookieJar实例。 430 | 注意:大多数情况下,我们只用CookieJar(),如果需要和本地文件交互,就用 MozillaCookjar() 或 LWPCookieJar() 431 | 432 | 433 | 代码思路:结合cookielib库和HTTPCookieProcessor处理器 434 | ---------------------------------------------------- 435 | 在python中处理cookie,一般是通过cookielib模块和urllib2.HTTPCookieProcessor()类一起使用.其各自作用如下: 436 | cookielib模块: 提供存储cookie的对象 437 | HTTPCookieProcessor处理器: 用于处理这些cookie对象,并构建handler对象 438 | 439 | 440 | 实操1:获取cookie并保存到内存中---利用CookieJar()对象 441 | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- 442 | | import urllib2 443 | | import cookielib 444 | | cookie_jar = cookielib.CookieJar() # 创建一个CookieJar对象实例来保存cookie到内存中 445 | | cookie_handler = urllib2.HTTPCookieProcessor(cookie_jar) # 第一步:创建处理器对象(这里创建一个(处理cookie)的HTTPCookieProcessor处理器)----传入的参数是CookieJar()对象 446 | | opener = urllib2.build_opener(cookie_handler) # 第二步:创建opener对象(这里:调用urllib2.build_opener()方法来创建opener对象) 447 | | opener.open("http://www.baidu.com") # 第三步:使用opener对象(这里:调用opener对象的open()方法发送request请求) 448 | | cookie_string = "" 449 | | for item in cookie_jar: 450 | | cookie_string = cookie_string + item.name + "=" + item.value + ";" 451 | | print cookie_string[:-1] # 去掉最后一位分号,这样就按标准格式将保存的cookie打印出来了 452 | | 453 | | # 以上方法将Cookie保存到cookiejar对象中,然后打印出了cookie中的值,也就是访问百度首页的Cookie值。 454 | | 455 | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- 456 | 457 | 458 | 实操2:获取cookie并保存到文件中---利用MozillaCookieJar()对象 459 | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- 460 | | import urllib2 461 | | import cookielkib 462 | | filename = "cookie_save.txt" # 本地保存cookie的文件名 463 | | cookie_save_jar = cookielib.MozillaCookieJar(filename) # 创建一个MozillaCookieJar对象实例来保存cookie到本地文件中---参数是本地文件名 464 | | cookie_handler = urllib2.HTTPCookieProcessor(cookie_save_jar) # 第一步:创建处理器对象(这里创建一个(处理cookie)的HTTPCookieProcessor处理器)----传入的参数是MozillaCookieJar()对象 465 | | opener = urllib2.build_opener(cookie_handler) # 第二步:创建opener对象(这里:调用urllib2.build_opener()方法来创建opener对象) 466 | | opener.open("http://www.baidu.com") # 第三步:使用opener对象(这里:调用opener对象的open()方法发送request请求) 467 | | cookie_save_jar.save() # 保存cookie到本地文件 468 | | 469 | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- 470 | 471 | 472 | 实操3:从文件中获取cookies,做为请求的一部分去访问---利用MozillaCookieJar()对象 473 | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- 474 | | import urllib2 475 | | import cookielib 476 | | cookie_load_jar = cookielib.MozillaCookJar() # 创建一个MozillaCookieJar对象实例来读取本地文件中 477 | | cookie_load_jar.load("cookie_save.txt") # 利用这个MozillaCookieJar对象实例来读取本地存放cookie的文件--cookie_save.txt 478 | | cookie_handler = urllib2.HTTPCookieProcessor(cookie_load_jar) # 第一步:创建处理器对象(这里创建一个(处理cookie)的HTTPCookieProcessor处理器)----传入的参数是MozillaCookieJar()对象 479 | | opener = urllib2.build_opener(cookie_handler) # 第二步:创建opener对象(这里:调用urllib2.build_opener()方法来创建opener对象) 480 | | response=opener.open("http://www.baidu.com") # 第三步:使用opener对象(这里:调用opener对象的open()方法发送request请求) 481 | | print response.read() 482 | | 483 | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- 484 | 485 | 486 | 案例:利用cookielib和post模拟登录人人网 487 | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- 488 | | 即:先通过post用户名和密码登陆人人网并同时保存好本次成功登陆的cookie,然后带着这个cookie第二次直接访问好友主页 489 | | 490 | | import urllib 491 | | import urllib2 492 | | import cookielib 493 | | cookie_jar =cookielib.CookieJar() # 创建一个CookieJar对象实例来保存cookie到内存中 494 | | cookie_handler = urllib2.HTTPCookieProcessor(cookie_jar) # 第一步:创建处理器对象(这里创建一个(处理cookie)的HTTPCookieProcessor处理器)----传入的参数是CookieJar()对象 495 | | opener = urllib2.build_opener(cookie_handler) # 第二步:创建opener对象(这里:调用urllib2.build_opener()方法来创建opener对象) 496 | | opener.addheaders = [("User-Agent","Mozilla/5.0 .....") # 向headers中添加一个User-Agent信息,addheaders接受一个列表,里面每个元素都是一个headers信息的元祖, opener将附带headers信息 497 | | post_data = {"email":"583803258@qq.com","password":"123456"} # 登陆需要的用户名和密码信息 498 | | post_data = urllib.urlencode(post_data) # 将这些登陆需要的信息进行urlencode()转码,转码后才能post 499 | | url = "http://www.renren.com/PLogin.do" # 第一次访问的登陆页面 500 | | request = urllib2.Request(url,data=post_data) # 创建post请求 501 | | first_response = opener.open(request) # 第三步:使用opener对象(这里:调用opener对象的open()方法发送post请求),获取到成功登陆的cookie信息被CookieJar()存放在内存中 502 | | second_response = opener.open("http://www.renren.com/405858138/profile") # 第二次使用opener去请求好友主页时由HTTPCookieProcessor处理器生成的opener就会附带上之前的cookie信息 503 | | print second_response.read() # 打印成功访问到好友的主页信息 504 | | 505 | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- 506 | 507 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 508 509 510 urllib2的异常处理 -----URLError类/HTTPError类 511 512 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 513 | 当我们使用urlopen/opener.open发送一个请求,如果urlopen/opener.open不能处理这个response就会产生错误,这里主要说的是URLError和HTTPError 514 | 515 | URLError类 516 | ---------------------------------------------------- 517 | URLError产生的原因主要有: 518 | (1)没有网络连接 519 | (2)服务器连接失败 520 | (3)找不到制定服务器 521 | 我们可以采用try except语句来捕获异常,例如下面的例子访问一个不存在的域名([Errno 8] nodename nor servname provided, or not known)错误原因找不到制定服务器 522 | 523 | import urllib2 524 | request = urllib2.Request("http://www.abcdxdd.com") 525 | try: 526 | urllib2.urlopen(request,timeout=5) 527 | except urllib2.URLError,err: # 捕获URLlib.URLError时将错误信息保存到err变量并打印err变量值 528 | print err 529 | 运行结果: 530 | <urlopen error [Errno 8] nodename nor servname provided, or not known> 531 | 532 | 533 | HTTPError类 534 | ---------------------------------------------------- 535 | HTTPError是URLError的子类,使用urllib2.HTTPError时会返回服务器的状态响应码和错误信息,使用如下: 536 | 537 | import urllib2 538 | 539 | request = urllib2.Request("http://blog.baidu.com/itcast") 540 | try: 541 | urllib2.urlopen(request) 542 | except urllib2.HTTPError,err: # 捕获URLlib.HTTPError时将错误信息保存到err变量并打印状态码和err信息 543 | print err.code 544 | print err 545 | 运行结果: 546 | 404 547 | HTTP Error 404: Not Found # 404错误,要么URL不对,要么IP被封 548 | 注意: urllib2可以为我们处理重定向的页面(也就是3开头的响应码),100-299范围的号码表示成功,所以我们只能看到400-599的错误号码。 549 | 550 | 551 | 综合编写urllib2异常处理: 552 | ---------------------------------------------------- 553 | 两种错误都能捕获-----由于HTTPError的父类是URLError,所以父类的异常应当写到子类异常的后面 554 | 555 | import urllib2 556 | 557 | request = urllib2.Request("http://blog.baidu.com/itcast") 558 | try: 559 | urllib2.urlopen(request) 560 | except urllib2.HTTPError,err: #如果首先捕获到HTTPError这个子类异常,则打印出错误状态码 561 | print err.code 562 | except urllib2.URLError.err: #如果父类URLError捕获到了(HTTPError子类没有捕获到的)异常,则打印出该异常的内容 563 | print err 564 | else: 565 | print "OK" 566 | 运行结果: 567 | 404 568 | 如上形式便可做到-----首先捕获子类的异常,如果子类捕获不到,那么可以捕获父类的异常。 569 | 570 | 571 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 572 573 附录:HTTP响应状态码参考 574 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 575 | 1xx:信息 576 | 577 | 100 Continue 578 | 服务器仅接收到部分请求,但是一旦服务器并没有拒绝该请求,客户端应该继续发送其余的请求。 579 | 101 Switching Protocols 580 | 服务器转换协议:服务器将遵从客户的请求转换到另外一种协议。 581 | 582 | 583 | 584 | 2xx:成功 585 | 586 | 200 OK 587 | 请求成功(其后是对GET和POST请求的应答文档) 588 | 201 Created 589 | 请求被创建完成,同时新的资源被创建。 590 | 202 Accepted 591 | 供处理的请求已被接受,但是处理未完成。 592 | 203 Non-authoritative Information 593 | 文档已经正常地返回,但一些应答头可能不正确,因为使用的是文档的拷贝。 594 | 204 No Content 595 | 没有新文档。浏览器应该继续显示原来的文档。如果用户定期地刷新页面,而Servlet可以确定用户文档足够新,这个状态代码是很有用的。 596 | 205 Reset Content 597 | 没有新文档。但浏览器应该重置它所显示的内容。用来强制浏览器清除表单输入内容。 598 | 206 Partial Content 599 | 客户发送了一个带有Range头的GET请求,服务器完成了它。 600 | 601 | 602 | 603 | 3xx:重定向 604 | 605 | 300 Multiple Choices 606 | 多重选择。链接列表。用户可以选择某链接到达目的地。最多允许五个地址。 607 | 301 Moved Permanently 608 | 所请求的页面已经转移至新的url。 609 | 302 Moved Temporarily 610 | 所请求的页面已经临时转移至新的url。 611 | 303 See Other 612 | 所请求的页面可在别的url下被找到。 613 | 304 Not Modified 614 | 未按预期修改文档。客户端有缓冲的文档并发出了一个条件性的请求(一般是提供If-Modified-Since头表示客户只想比指定日期更新的文档)。服务器告诉客户,原来缓冲的文档还可以继续使用。 615 | 305 Use Proxy 616 | 客户请求的文档应该通过Location头所指明的代理服务器提取。 617 | 306 Unused 618 | 此代码被用于前一版本。目前已不再使用,但是代码依然被保留。 619 | 307 Temporary Redirect 620 | 被请求的页面已经临时移至新的url。 621 | 622 | 623 | 624 | 4xx:客户端错误 625 | 626 | 400 Bad Request 627 | 服务器未能理解请求。 628 | 401 Unauthorized 629 | 被请求的页面需要用户名和密码。 630 | 401.1 631 | 登录失败。 632 | 401.2 633 | 服务器配置导致登录失败。 634 | 401.3 635 | 由于 ACL 对资源的限制而未获得授权。 636 | 401.4 637 | 筛选器授权失败。 638 | 401.5 639 | ISAPI/CGI 应用程序授权失败。 640 | 401.7 641 | 访问被 Web 服务器上的 URL 授权策略拒绝。这个错误代码为 IIS 6.0 所专用。 642 | 402 Payment Required 643 | 此代码尚无法使用。 644 | 403 Forbidden 645 | 对被请求页面的访问被禁止。 646 | 403.1 647 | 执行访问被禁止。 648 | 403.2 649 | 读访问被禁止。 650 | 403.3 651 | 写访问被禁止。 652 | 403.4 653 | 要求 SSL。 654 | 403.5 655 | 要求 SSL 128。 656 | 403.6 657 | IP 地址被拒绝。 658 | 403.7 659 | 要求客户端证书。 660 | 403.8 661 | 站点访问被拒绝。 662 | 403.9 663 | 用户数过多。 664 | 403.10 665 | 配置无效。 666 | 403.11 667 | 密码更改。 668 | 403.12 669 | 拒绝访问映射表。 670 | 403.13 671 | 客户端证书被吊销。 672 | 403.14 673 | 拒绝目录列表。 674 | 403.15 675 | 超出客户端访问许可。 676 | 403.16 677 | 客户端证书不受信任或无效。 678 | 403.17 679 | 客户端证书已过期或尚未生效。 680 | 403.18 681 | 在当前的应用程序池中不能执行所请求的 URL。这个错误代码为 IIS 6.0 所专用。 682 | 403.19 683 | 不能为这个应用程序池中的客户端执行 CGI。这个错误代码为 IIS 6.0 所专用。 684 | 403.20 685 | Passport 登录失败。这个错误代码为 IIS 6.0 所专用。 686 | 404 Not Found 687 | 服务器无法找到被请求的页面。 688 | 404.0 689 | 没有找到文件或目录。 690 | 404.1 691 | 无法在所请求的端口上访问 Web 站点。 692 | 404.2 693 | Web 服务扩展锁定策略阻止本请求。 694 | 404.3 695 | MIME 映射策略阻止本请求。 696 | 405 Method Not Allowed 697 | 请求中指定的方法不被允许。 698 | 406 Not Acceptable 699 | 服务器生成的响应无法被客户端所接受。 700 | 407 Proxy Authentication Required 701 | 用户必须首先使用代理服务器进行验证,这样请求才会被处理。 702 | 408 Request Timeout 703 | 请求超出了服务器的等待时间。 704 | 409 Conflict 705 | 由于冲突,请求无法被完成。 706 | 410 Gone 707 | 被请求的页面不可用。 708 | 411 Length Required 709 | "Content-Length" 未被定义。如果无此内容,服务器不会接受请求。 710 | 412 Precondition Failed 711 | 请求中的前提条件被服务器评估为失败。 712 | 413 Request Entity Too Large 713 | 由于所请求的实体的太大,服务器不会接受请求。 714 | 414 Request-url Too Long 715 | 由于url太长,服务器不会接受请求。当post请求被转换为带有很长的查询信息的get请求时,就会发生这种情况。 716 | 415 Unsupported Media Type 717 | 由于媒介类型不被支持,服务器不会接受请求。 718 | 416 Requested Range Not Satisfiable 719 | 服务器不能满足客户在请求中指定的Range头。 720 | 417 Expectation Failed 721 | 执行失败。 722 | 423 723 | 锁定的错误。 724 | 725 --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------