6

爬虫-urllib模块的使用

 3 years ago
source link: https://www.daqianduan.com/20432.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

urllib是Python中请求url连接的官方标准库,在Python3中将Python2中的urllib和urllib2整合成了urllib。urllib中一共有四个模块,分别如下:

  • request:主要负责构造和发起网络请求,定义了适用于在各种复杂情况下打开 URL (主要为 HTTP) 的函数和类
  • error:处理异常
  • parse:解析各种数据格式
  • robotparser:解析robot.txt文件

一、request模块

1.urlopen()方法:

  • 在urlopen()方法中,直接写入要访问的url地址字符串,该方法就会主动的访问目标网址,然后返回访问结果,返回的访问结果是一个http.client.HTTPResponse对象,该对象的常见方法有:
  1. read() :获取访问网页获取的数据,bytes类型
  2. info():返回响应头信息
  3. getcode():返回Http状态码。
  4. geturl():返回请求的url
  • 发送简单的GET请求

    from urllib.request import urlopen
    
    #向指定的url发送请求,并返回服务器响应的类文件对象
    resp = urlopen('https://www.baidu.com') 
    print(resp.read().decode())
  • 发送简单的POST请求(data参数)

    from urllib.reuqest import urlopen
    from urllib.parse import urlencode
    
    #将字典类型的数据转换成表单类型的数据格式,如"world=hello"
    data = urlencode({"word":"hello"}).encode()
    response = request.urlopen('http://httpbin.org/post', data=data)
    
    print(response.read().decode())

    默认的访问方式是GET,当在urlopen()方法中传入data参数时,则会发起POST请求。注意:传递的data数据需要为bytes格式

2.Request

  • 如果需要执行更复杂的操作,比如增加HTTP报头,必须创建一个 Request 实例来作为urlopen()的参数;而需要访问的url地址则作为 Request 实例的参数。
  • 为了使爬虫程序更像一个真实用户,那我们第一步就是需要伪装成一个被公认的浏览器,在发送请求的时候带上User-Agent头
    from urllib.request import Request,urlopen
    
    url = 'https://www.baidu.com/'
    ua_header = {"User-Agent" : "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0;"}
    #url连同headers一起构造request请求,这个请求附带IE 9.0浏览器的User-Agent
    request = Request(url,headers=ua_header)
    #向服务器发送请求
    resp = urlopen(request)
    print(resp.read().decode)

3.ProxyHandler处理器(代理IP)

  • 使用爬虫来爬取数据的时候,如果过于频繁的访问,而且网站还设有限制的话,很有可能会禁封我们的ip地址,这个时候就需要设置代理,来隐藏我们的真实IP。
  • 代理IP的原理:以本机先访问代理IP,再通过代理IP地址访问服务器,这样服务器接受到的访问IP就是代理IP地址。

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

    如果代理需要授权验证,简单的方式是只需要在ProxyHandler传入的参数字典中,将值改为’用户名:密码@ip:端口号’这种形式,比如{“http”:”myname:[email protected]:80″},复杂一点的需要创建一个密码管理对象,下面会有介绍。

4.HTTPPasswordMgrWithDefaultRealm()

  • 利用这个 类创建一个密码管理对象,用来保存 HTTP 请求相关的用户名和密码,主要应用两个场景:
  1. 验证代理授权的用户名和密码 ( ProxyBasicAuthHandler())
  2. 验证Web客户端的的用户名和密码 ( HTTPBasicAuthHandler())

5.ProxyBasicAuthHandler(代理授权验证)

  • 在使用私密代理时,需要通过授权验证身份

    from urllib.request import HTTPPasswordMgrWithDefaultRealm,ProxyBasicAuthHandler,build_opener,Request
    
    # 私密代理授权的账户
    user = "mr_mao_hacker"
    # 私密代理授权的密码
    passwd = "sffqry9r"
    # 私密代理 IP
    proxyserver = "61.158.163.130:16816"
    
    # 1. 构建一个密码管理对象,用来保存需要处理的用户名和密码
    passwdmgr = HTTPPasswordMgrWithDefaultRealm()
    
    # 2. 添加账户信息,第一个参数realm是与远程服务器相关的域信息,一般没人管它都是写None,后面三个参数分别是代理服务器、用户名、密码
    passwdmgr.add_password(None, proxyserver, user, passwd)
    
    # 3. 构建一个代理基础用户名/密码验证的ProxyBasicAuthHandler处理器对象,参数是创建的密码管理对象
    #   注意,这里不再使用普通ProxyHandler类了
    proxyauth_handler = ProxyBasicAuthHandler(passwdmgr)
    
    # 4. 通过 build_opener()方法使用这些代理Handler对象,创建自定义opener对象,参数包括构建的 proxy_handler 和 proxyauth_handler
    opener = build_opener(proxyauth_handler)
    
    request = urllib2.Request("https://www.baidu.com/")
    resp = opener.open(request)
    print (resp.read().decode())

    注:通常用户名和密码不直接写在程序中,而是存放在环境变量,或者单独写入一个模块,然后从模块导入

6.HTTPBasicAuthHandler(WEB客户端授权验证)

  • 有些Web服务器(包括HTTP/FTP等)访问时,需要进行用户身份验证,爬虫直接访问会报HTTP 401 错误,表示访问身份未经授权
  • 如果我们有客户端的用户名和密码,只需要将上述代理授权验证代码中的ProxyBasicAuthHandler改成HTTPBasicAuthHandler即可

7.Cookies

  • Cookies在爬虫方面最典型的应用是判定注册用户是否已经登录网站,用户可能会得到提示,是否在下一次进入此网站时保留用户信息以便简化登录手续。
  • 由于urllib并没有很好的处理cookie的对象,所以在这里我们需要用到一个别的库,即http库,并使用里面的cookiejar来进行cookie的管理,该模块主要的对象有主要的对象有CookieJar、FileCookieJar、MozillaCookieJar、LWPCookieJar:
    • CookieJar:管理HTTP cookie值、存储HTTP请求生成的cookie、向传出的HTTP请求添加cookie的对象。整个cookie都存储在内存中,对CookieJar实例进行垃圾回收后cookie也将丢失。

    • FileCookieJar (filename,delayload=None,policy=None):从CookieJar派生而来,用来创建FileCookieJar实例,检索cookie信息并将cookie存储到文件中。filename是存储cookie的文件名。delayload为True时支持延迟访问访问文件,即只有在需要时才读取文件或在文件中存储数据。

    • MozillaCookieJar (filename,delayload=None,policy=None):从FileCookieJar派生而来,创建与 Mozilla浏览器 cookies.txt兼容 的FileCookieJar实例。

    • LWPCookieJar (filename,delayload=None,policy=None):从FileCookieJar派生而来,创建与 libwww-perl标准的 Set-Cookie3 文件格式 兼容的FileCookieJar实例。

  • 大多数情况下,我们只需要用到CookieJar(),如果需要和本地文件进行交互,就要用MozillaCookieJar()和LWPCookieJar(),下面就介绍几种案例:
  1. 获取cookie,并保存到CookieJar()中

    from http.cookiejar import CookieJar
    from urllib.request import Request,build_opener,HTTPCookieProcessor
    
    # 构建一个CookieJar对象实例来保存cookie
    cookiejar = cookielib.CookieJar()
    
    # 使用HTTPCookieProcessor()来创建cookie处理器对象,参数为CookieJar()对象
    handler=HTTPCookieProcessor(cookiejar)
    
    opener = build_opener(handler)
    
    # 4. 以get方法访问页面,访问之后会自动保存cookie到cookiejar中
    resp = opener.open("http://www.baidu.com")
    
    ## 可以按标准格式将保存的Cookie打印出来
    cookieStr = ""
    for item in cookiejar:
        cookieStr = cookieStr + item.name + "=" + item.value + ";"
    
    ## 舍去最后一位的分号
    print cookieStr[:-1]
  2. 访问网站获得cookie,并将cookie保存在本地文件中

    from http.cookiejar import MozillaCookieJar
    from urllib.request import Request,build_opener,HTTPCookieProcessor
    
    # 保存cookie的本地磁盘文件名
    filename = 'cookie.txt'
    
    #声明一个MozillaCookieJar(有save实现)对象实例来保存cookie,之后写入文件
    cookiejar = MozillaCookieJar(filename)
    
    # 使用HTTPCookieProcessor()来创建cookie处理器对象,参数为CookieJar()对象
    handler = HTTPCookieProcessor(cookiejar)
    
    opener = build_opener(handler)
    response = opener.open("https://www.baidu.com/")
    
    # 保存cookie到本地文件
    cookiejar.save()
  3. 从文件中获取cookie

    from http.cookiejar import MozillaCookieJar
    from urllib.request import Request,build_opener,HTTPCookieProcessor
    
    #创建MozillaCookieJar(有load实现)实例对象
    cookiejar = MozillaCookieJar(filename)
    
    #从文件中读取cookie内容到对象
    cookiejar.load('cookie.txt')
    
    # 使用HTTPCookieProcessor()来创建cookie处理器对象,参数为CookieJar()对象
    handler = HTTPCookieProcessor(cookiejar)
    
    opener = build_opener(handler)
    response = opener.open("https://www.baidu.com/")

8.处理HTTPS请求SSL证书验证

  • 最简单的方法就是通过添加忽略ssl证书验证关闭证书验证,由于urllib并没有很好的处理ssl的对象,所以在这里我们需要用到一个别的库,即ssl库,如下:
    import ssl
    from urllib.request import urlopen,Request
    
    # 表示忽略未经核实的SSL证书认证
    context = ssl._create_unverified_context()
    
    url = "https://www.12306.cn/mormhweb/"
    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"}
    request = Request(url,headers=headers)
    
    # 在urlopen()方法里 指明添加 context 参数
    resp = urlopen(request, context=context)
    print(resp.read().decode())

二、error模块

  • 在urllib中主要设置了两个异常,一个是URLError,一个是HTTPError,HTTPError是URLError的子类。

1.URLError

  • URLError产生的原因主要有:
  1. 没有网络连接
  2. 服务器连接失败
  3. 找不到指定的服务器
  • 下面访问一个不存在的域名:
    from urllib.error import URLError
    from urllib.request import Request,urlopen
    
    request = Request('http://www.fafafasfdaffaf.com/')
    try:
        resp = urlopen(request)
    except URLError as e:
        print(e)

2.HTTPError

  • HTTPError包含了三个属性:
  1. code:请求的状态码
  2. reason:错误的原因
  3. headers:响应的报头
    from urllib.error import HTTPError
    from urllib.request import Request,urlopen
    
    requset = Request('http://www.baidu.com/lfafdaflafapae.html')
    
    try:
        resp = urlopen(requset)
    except HTTPError as e:
        print(e)
        print(e.code)
        print(e.reason)
        print(e.headers)

三、parse模块

data参数需要用urllib.parse模块对其进行数据格式处理。

  • urllib.parse.quote(url):(URL编码处理)主要对URL中的非ASCII码编码处理
  • urllib.parse.unquote(url):(URL解码处理)URL上的特殊字符还原
  • urllib.parse.urlencode(data):对请求数据data进行格式转换
#感谢您访问本站#
#本文转载自互联网,若侵权,请联系删除,谢谢!657271#qq.com#

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK