zoukankan      html  css  js  c++  java
  • urllib详细版

    urllib是python内置的处理HTTP请求的库,主要包含以下四个模块

    • request 模块,是最基本的处理HTTP请求的模块。
    • error 异常处理模块,如果出现请求错误,可以捕获这些错误,保证程序不会意外终止。
    • parse 模块是一个工具模块,提供了处理url的很多方法。拆分,解析,合并等等。
    • robotparser,主要用来识别网站的robots.txt文件,判断哪些网站可以爬取。

    一 、发送请求

    使用urllib的request模块可以发送请求,并且响应response

    • URLopen()
      • urllib.request 模块提供了最基本的构造 HTTP 请求的方法,利用它可以模拟浏览器的一个请求发起过程,同时它还带有处理authenticaton(授权验证),redirections(重定向),cookies(浏览器Cookies)以及其它内容。
        我们来感受一下它的强大之处,以 Python 官网为例,我们来把这个网页抓下来:
    import urllib.request
    
    response = urllib.request.urlopen('https://www.python.org')
    print(response.read().decode('utf-8'))
    

      response返回的是HTTPResposne 类型的对象,包含的方法有read()、readinto()、getheader(name)、getheaders()、fileno() 等方法和 msg、version、status、reason、debuglevel、closed 等属性。

      例如调用 read() 方法可以得到返回的网页内容,调用 status 属性就可以得到返回结果的状态码,如 200 代表请求成功,404 代表网页未找到等。

      

    import urllib.request
    
    response = urllib.request.urlopen('https://www.python.org')
    print(response.status)
    print(response.getheaders())
    print(response.getheader('Server'))
    

      运行结果如下:

    200
    [('Server', 'nginx'), ('Content-Type', 'text/html; charset=utf-8'), ('X-Frame-Options', 'SAMEORIGIN'), ('X-Clacks-Overhead', 'GNU Terry Pratchett'), ('Content-Length', '47397'), ('Accept-Ranges', 'bytes'), ('Date', 'Mon, 01 Aug 2016 09:57:31 GMT'), ('Via', '1.1 varnish'), ('Age', '2473'), ('Connection', 'close'), ('X-Served-By', 'cache-lcy1125-LCY'), ('X-Cache', 'HIT'), ('X-Cache-Hits', '23'), ('Vary', 'Cookie'), ('Strict-Transport-Security', 'max-age=63072000; includeSubDomains')]
    nginx
    

       可见,三个输出分别输出了响应的状态码响应的头信息,以及通过调用 getheader() 方法并传递一个参数 Server 获取了 headers 中的 Server 值,结果是 nginx,意思就是服务器是 nginx 搭建的。
    利用以上最基本的 urlopen() 方法,我们可以完成最基本的简单网页的 GET 请求抓取。
    如果我们想给链接传递一些参数该怎么实现呢?我们首先看一下 urlopen() 函数的API: 

    def urlopen(url, data=None, timeout=socket._GLOBAL_DEFAULT_TIMEOUT,
                *, cafile=None, capath=None, cadefault=False, context=None):
    

      可以发现除了第一个参数可以传递 URL 之外,我们还可以传递其它的内容,比如 data(附加数据)、timeout(超时时间)等等。

    data参数:  

      data的参数是可选的,如果要添加data参数,必须是bytes类型。通过bytes()方法可以转化,data有参数请求方式会从之前的get请求换为post 请求

    import urllib.parse
    import urllib.request
    
    data = bytes(urllib.parse.urlencode({'word': 'hello'}), encoding='utf8')
    response = urllib.request.urlopen('http://httpbin.org/post', data=data)
    print(response.read())
    

      在这里我们传递了一个参数 word,值是 hello。它需要被转码成bytes(字节流)类型。其中转字节流采用了 bytes() 方法,第一个参数需要是 str(字符串)类型,需要用 urllib.parse 模块里的 urlencode() 方法来将参数字典转化为字符串。第二个参数指定编码格式,在这里指定为 utf8。

     timeout参数:

      timeout参数设置超时时间,单位是秒。如果请求超过这个时间还没有得到响应,就会抛出异常。如果没有设定的话,就会使用全局的默认时间。支持HTTP,HTTPS,FTP!

      我们可以设置超时时间来控制网页爬取时间超过规定时间就跳出,使用try except语句是实现。

    import socket
    import urllib.request
    import urllib.error
    
    try:
        response = urllib.request.urlopen('http://httpbin.org/get', timeout=0.1)
    except urllib.error.URLError as e:
        if isinstance(e.reason, socket.timeout):
            print('TIME OUT')
    

     还有 context 参数,它必须是 ssl.SSLContext 类型,用来指定 SSL 设置。
    cafile 和 capath 两个参数是指定 CA 证书和它的路径,这个在请求 HTTPS 链接时会有用。
    cadefault 参数现在已经弃用了,默认为 False。

     详细文档:https://docs.python.org/3/library/urllib.request.html

     Request

      urlopen()可以实现简单的请求,但是不能构建一个完整的请求。所以可以用Request类来构建一个完整的请求。

    import urllib.request
    
    request = urllib.request.Request('https://python.org')
    response = urllib.request.urlopen(request)
    print(response.read().decode('utf-8'))
    

      观察还是用urlopen()来发起的请求,只不过参数不再是url,而是一个request对象。

      Request的参数:

    class urllib.request.Request(url, data=None, headers={}, origin_req_host=None, unverifiable=False, method=None)
    

      参数解释:

      url:请求的url ,必传参数。

      data: 类型是bytes类型,如果是字典,使用urllib.parse中的urlencode()编码!

      headers:参数是一个字典,表示请求的请求标识和载体!可以直接构造,也可以通过调用Request实例的add_header()方法来添加。

      origin_host:表示请求的host名称或者IP地址!

      unverifiable:参数表示这个请求是否是无法验证的,默认是False.意思就是说用户没有足够权限来选择接收这个请求的结果。例如我们请求一个 HTML 文档中的图片,但是我们没有自动抓取图像的权限,这时 unverifiable 的值就是 True。

      method:表示请求的方式GET,POST,PUT等等!!!

    from urllib import request, parse
    
    url = 'http://httpbin.org/post'
    headers = {
        'User-Agent': 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)',
        'Host': 'httpbin.org'
    }
    dict = {
        'name': 'Germey'
    }
    data = bytes(parse.urlencode(dict), encoding='utf8')
    req = request.Request(url=url, data=data, headers=headers, method='POST')
    response = request.urlopen(req)
    print(response.read().decode('utf-8'))
    

     headers 也可以用 add_header() 方法来添加。

    req = request.Request(url=url, data=data, method='POST')
    req.add_header('User-Agent', 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)')
    

    二、处理异常

      在发送Request请求的时候,可能会因为一些情况,导致异常出现,怎么办呢?如果不处理这些异常得话,程序很可能会因为报错而停止运行!所以处理异常非常有必要!

      urllib 的error模块定义了由request模块产生的异常。如果出现了问题,request模块就会抛出error模块中定义的异常!

      主要有URLError和HTTPError

      举例:

    from urllib import request,error
    try:
    response = request.urlopen("http://chuanshengkj.com/index.htm")
    except error.URLError as e :
    print(e.reason)

      我们打开一个不存在的页面,照理来说应该会报错,但是这时我们捕获了 URLError 这个异常,运行结果如下:

    Not Found
    

      

    from urllib import request,error
    try:
        response = request.urlopen("http://cuiqingcai.com/index.htm")
    except error.HTTPError as e :
        print(e.reason,e.code,e.headers,sep='
    ')
    

      运行结果:

    Not Found
    404
    Server: nginx/1.10.3 (Ubuntu)
    Date: Thu, 12 Sep 2019 07:20:12 GMT
    Content-Type: text/html; charset=UTF-8
    Transfer-Encoding: chunked
    Connection: close
    Set-Cookie: PHPSESSID=vsnopftnnk0gfjrk3qfljvq6v5; path=/
    Pragma: no-cache
    Vary: Cookie
    Expires: Wed, 11 Jan 1984 05:00:00 GMT
    Cache-Control: no-cache, must-revalidate, max-age=0
    Link: <https://cuiqingcai.com/wp-json/>; rel="https://api.w.org/"
    

      

    HTTPError,它有三个属性。

      • code,返回 HTTP Status Code,即状态码,比如 404 网页不存在,500 服务器内部错误等等。
      • reason,同父类一样,返回错误的原因。
      • headers,返回 Request Headers。
        因为 URLError 是 HTTPError 的父类,所以我们可以先选择捕获子类的错误,再去捕获父类的错误,所以上述代码更好的写法如下:
    from urllib import request, error
    
    try:
        response = request.urlopen('http://cuiqingcai.com/index.htm')
    except error.HTTPError as e:
        print(e.reason, e.code, e.headers, sep='
    ')
    except error.URLError as e:
        print(e.reason)
    else:
        print('Request Successfully')
    

      这样我们就可以做到先捕获 HTTPError,获取它的错误状态码、原因、Headers 等详细信息。如果非 HTTPError,再捕获 URLError 异常,输出错误原因。最后用 else 来处理正常的逻辑,这是一个较好的异常处理写法

  • 相关阅读:
    Sum Root to Leaf Numbers
    Sum Root to Leaf Numbers
    Sort Colors
    Partition List
    Binary Tree Inorder Traversal
    Binary Tree Postorder Traversal
    Remove Duplicates from Sorted List II
    Remove Duplicates from Sorted List
    Search a 2D Matrix
    leetcode221
  • 原文地址:https://www.cnblogs.com/wqzn/p/11512108.html
Copyright © 2011-2022 走看看