• Python爬虫基础(三)urllib2库的高级使用


    Handler处理器 和 自定义Opener

        opener是 urllib2.OpenerDirector 的实例,其中urlopen是模块默认构建的opener。 但是基本的urlopen()方法不支持代理、cookie等其他的HTTP/HTTPS高级功能。如果要支持这些功能,可以使用相关的 Handler处理器来创建特定功能的处理器对象,然后通过 urllib2.build_opener()方法使用这些处理器对象,创建自定义opener对象,最后 使用自定义的opener对象,调用open()方法发送请求。    

    自定义一个简单的opener()

     -*- coding: utf-8 -*-
    import urllib2
    
    # 构建一个HTTPHandler 处理器对象,支持处理HTTP请求
    http_handler = urllib2.HTTPHandler()
    
    # 构建一个HTTPHandler 处理器对象,支持处理HTTPS请求
    # http_handler = urllib2.HTTPSHandler()
    
    # 调用urllib2.build_opener()方法,创建支持处理HTTP请求的opener对象
    opener = urllib2.build_opener(http_handler)
    
    # 构建 Request请求
    request = urllib2.Request("http://www.baidu.com/")
    
    # 调用自定义opener对象的open()方法,发送request请求
    response = opener.open(request)
    
    # 获取服务器响应内容
    print response.read()
    
    
    # 开启Debug Log程序在执行的时候,会把收包和发包的报头在屏幕上自动打印出来
    # 构建一个HTTPHandler 处理器对象,支持处理HTTP请求,同时开启Debug Log,debuglevel 值默认 0
    # http_handler = urllib2.HTTPHandler(debuglevel=1)
    
    # 构建一个HTTPHSandler 处理器对象,支持处理HTTPS请求,同时开启Debug Log,debuglevel 值默认 0
    # https_handler = urllib2.HTTPSHandler(debuglevel=1)

    使用ProxyHandler处理器设置代理

            使用代理IP,这也是爬虫/反爬虫的有效方式,很多网站会检测某一段时间某个IP的访问次数,如果访问频率过高,就有可能被禁止访问。这时可以设置一些代理服务器,每隔一段时间换一个代理,就算IP被禁止,依然可以换个IP继续爬取。

    在urllib2中可以通过ProxyHandler来设置使用代理服务器:

    # -*- coding: utf-8 -*-
    import urllib2
    
    # 构建了两个代理Handler,一个有代理IP,一个没有代理IP
    httpproxy_handler = urllib2.ProxyHandler({"http" : "124.88.67.81:80"})
    nullproxy_handler = urllib2.ProxyHandler({})
    
    proxySwitch = True #定义一个代理开关
    
    # 通过 urllib2.build_opener()方法使用这些代理Handler对象,创建自定义opener对象
    # 根据代理开关是否打开,使用不同的代理模式
    if proxySwitch:  
        opener = urllib2.build_opener(httpproxy_handler)
    else:
        opener = urllib2.build_opener(nullproxy_handler)
    
    request = urllib2.Request("http://www.baidu.com/")
    
    #  只有使用opener.open()方法发送请求才使用自定义的代理,而urlopen()则不使用自定义代理。
    response = opener.open(request)
    
    # 将opener应用到全局,之后不管是opener.open()还是urlopen() 发送请求,都将使用自定义代理。
    # urllib2.install_opener(opener)
    # response = urlopen(request)
    
    print response.read()

    免费的开放代理很容易获取,有不少这样的网站,可以多收集一些代理IP,这样可以像随机获取User-Agent一样,随机选择一个代理去访问网站:

    # -*- coding: utf-8 -*-
    import urllib2
    import random
    
    proxy_list = [
        {"http" : "124.88.67.81:80"},
        {"http" : "124.88.67.81:80"},
        {"http" : "124.88.67.81:80"},
        {"http" : "124.88.67.81:80"},
        {"http" : "124.88.67.81:80"}
    ]
    
    # 随机选择一个代理
    proxy = random.choice(proxy_list)
    # 使用选择的代理构建代理处理器对象
    httpproxy_handler = urllib2.ProxyHandler(proxy)
    
    opener = urllib2.build_opener(httpproxy_handler)
    
    request = urllib2.Request("http://www.baidu.com/")
    response = opener.open(request)
    print response.read()

    免费代理不稳定,如果要求高就购买私密代理,购买私密代理后会得到一个账户和密码作为认证,具体使用如下:

    # -*- coding:utf-8 -*-
    import urllib2
    
    # 私密代理授权的账户
    user = "xxxx"
    # 私密代理授权的密码
    passwd = "****"
    
    # 授权的代理账户密码拼接
    authproxy_handler = urllib2.ProxyHandler({"http" : user+":"+passwd+"@114.215.104.49:16816"})
    
    # 构建一个自定义的opener
    opener = urllib2.build_opener(authproxy_handler)
    
    # 构建请求
    request = urllib2.Request("http://www.baidu.com/")
    
    # 获取响应
    response = opener.open(request)
    
    # 打印内容
    print response.read()

    为避免账户密码泄露可以将其写入环境变量中。

    HTTPBasicAuthHandler处理器(Web客户端授权验证)

    # -*- coding: utf-8 -*-
    from __future__ import unicode_literals
    import urllib
    import urllib2
    
    # 用户名
    user = "xxxx"
    # 密码
    passwd = "****"
    # Web服务器 IP
    webserver = "http://192.168.12.33"
    
    # 构建一个密码管理对象,用来保存需要处理的用户名和密码
    passwdmgr = urllib2.HTTPPasswordMgrWithDefaultRealm()
    
    # 添加账户信息,第一个参数realm是与远程服务器相关的域信息,一般没人管它都是写None,后面三个参数分别是 Web服务器、用户名、密码
    passwdmgr.add_password(None, webserver, user, passwd)
    
    # 构建一个HTTP基础用户名/密码验证的HTTPBasicAuthHandler处理器对象,参数是创建的密码管理对象
    httpauth_handler = urllib2.HTTPBasicAuthHandler(passwdmgr)
    
    # 通过 build_opener()方法使用这些代理Handler对象,创建自定义opener对象,参数包括构建的 proxy_handler
    opener = urllib2.build_opener(httpauth_handler)
    
    # 可以选择通过install_opener()方法定义opener为全局opener
    urllib2.install_opener(opener)
    
    # 构建 Request对象
    request = urllib2.Request("http://192.168.199.107")
    
    # 定义opener为全局opener后,可直接使用urlopen()发送请求
    response = urllib2.urlopen(request)
    
    # 打印响应内容
    print response.read()

    这种网站比较少,遇到时我们可以使用requests库来爬取会方便很多,这种方法过于繁琐。

    Cookie 是指某些网站服务器为了辨别用户身份和进行Session跟踪,而储存在用户浏览器上的文本文件,Cookie可以保持登录信息到用户下次与服务器的会话。

    Cookies在爬虫方面最典型的应用是判定注册用户是否已经登录网站,用户可能会得到提示,是否在下一次进入此网站时保留用户信息以便简化登录手续。

    通过抓包获取一个有登录信息的Cookie来模拟登陆:

    # -*- coding: utf-8 -*-
    import urllib2
    
    # 构建一个已经登录过的用户的headers信息
    headers = {
        "Host":"www.renren.com",
        "Connection":"keep-alive",
        "Upgrade-Insecure-Requests":"1",
        "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",
        "Accept":"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
        "Accept-Language":"zh-CN,zh;q=0.8,en;q=0.6",
        # 这个Cookie是保存了密码无需重复登录的用户的Cookie,通过抓包获取(这里只是一部分)
        "Cookie": "anonymid=efrna3fysufnwv; depovince=GW; _r01_=1; "
    }
    
    # 通过headers里的报头信息(主要是Cookie信息),构建Request对象
    urllib2.Request("http://www.renren.com/", headers = headers)
    
    # 直接访问renren主页,服务器会根据headers报头信息(主要是Cookie信息),判断这是一个已经登录的用户,并返回相应的页面
    response = urllib2.urlopen(request)
    
    # 打印响应内容
    print response.read()

    cookielib库 和 HTTPCookieProcessor处理器

    1、获取Cookie,并保存到CookieJar()对象中
    # -*- coding: utf-8 -*-
    import urllib2
    import cookielib
    
    # 构建一个CookieJar对象实例来保存cookie
    cookiejar = cookielib.CookieJar()
    
    # 使用HTTPCookieProcessor()来创建cookie处理器对象,参数为CookieJar()对象
    handler=urllib2.HTTPCookieProcessor(cookiejar)
    
    # 通过 build_opener() 来构建opener
    opener = urllib2.build_opener(handler)
    
    # 4. 以get方法访问页面,访问之后会自动保存cookie到cookiejar中
    opener.open("http://www.baidu.com")
    2. 访问网站获得cookie,并把获得的cookie保存在cookie文件中
    # -*- coding: utf-8 -*-
    import cookielib
    import urllib2
    
    # 保存cookie的本地磁盘文件名
    filename = 'cookie.txt'
    
    # 声明一个MozillaCookieJar(有save实现)对象实例来保存cookie,之后写入文件
    cookiejar = cookielib.MozillaCookieJar(filename)
    
    # 使用HTTPCookieProcessor()来创建cookie处理器对象,参数为CookieJar()对象
    handler = urllib2.HTTPCookieProcessor(cookiejar)
    
    # 通过 build_opener() 来构建opener
    opener = urllib2.build_opener(handler)
    
    # 创建一个请求,原理同urllib2的urlopen
    response = opener.open("http://www.baidu.com")
    
    # 保存cookie到本地文件
    cookiejar.save()
    3. 从文件中获取cookies,做为请求的一部分去访问
    # -*- coding: utf-8 -*-
    import cookielib
    import urllib2
    
    # 创建MozillaCookieJar(有load实现)实例对象
    cookiejar = cookielib.MozillaCookieJar()
    
    # 从文件中读取cookie内容到变量
    cookie.load('cookie.txt')
    
    # 使用HTTPCookieProcessor()来创建cookie处理器对象,参数为CookieJar()对象
    handler = urllib2.HTTPCookieProcessor(cookiejar)
    
    # 通过 build_opener() 来构建opener
    opener = urllib2.build_opener(handler)
    
    response = opener.open("http://www.baidu.com")

    urllib2 的异常错误处理

    在我们用urlopen或opener.open方法发出一个请求时,如果urlopen或opener.open不能处理这个response,就产生错误。主要有URLError和HTTPError。
    URLError 产生的原因主要有:没有网络连接、服务器连接失败、找不到指定的服务器。
    HTTPError是URLError的子类,我们发出一个请求时,服务器上都会对应一个response应答对象,其中它包含一个数字"响应状态码"。如果urlopen或opener.open不能处理的,会产生一个HTTPError,对应相应的状态码,HTTP状态码表示HTTP协议所返回的响应的状态。

    异常处理程序:

    # -*- coding: utf-8 -*-
    
    # 1、URLError
    import urllib2
    # 访问一个不存在的域名
    requset = urllib2.Request('http://www.ajkfhafwjqh.com')
    try:
        urllib2.urlopen(request, timeout=5)
    except urllib2.URLError, err:
        print err
    
    
    # 2、HTTPError
    import urllib2
    requset = urllib2.Request('http://blog.baidu.com/zhihu')
    try:
        urllib2.urlopen(requset)
    except urllib2.HTTPError, err:
        # 打印状态码
        print err.code
        print err
    
    
    #3、由于HTTPError的父类是URLError,所以父类的异常应当写到子类异常的后面,所以上述的代码可以这么改写:
    
    import urllib2
    
    requset = urllib2.Request('http://blog.baidu.com/zhihu')
    
    try:
        urllib2.urlopen(requset)
    
    except urllib2.HTTPError, err:
        print err.code
    
    except urllib2.URLError, err:
        print err
    
    else:
        print "OK"
  • 相关阅读:
    【Leetcode】92. Reverse Linked List II && 206. Reverse Linked List
    【Leetcode】91. Decode Ways
    记一次面经
    涨知识
    B-Tree 漫谈 (从二叉树到二叉搜索树到平衡树到红黑树到B树到B+树到B*树)
    涨知识
    HDU 1754 I Hate It 【线段树单点修改 维护区间最大值】
    POJ 1632 Vase collection【状态压缩+搜索】
    POJ 1011 Sticks 【DFS 剪枝】
    POJ 1088 滑雪 【记忆化搜索经典】
  • 原文地址:https://www.cnblogs.com/xinyangsdut/p/7686028.html
Copyright © 2020-2023  润新知