zoukankan      html  css  js  c++  java
  • python3里的Urllib库

      首先Urllib是python内置的HTTP请求库。

      包括以下模块:

    1. urllib.request 请求模块;
    2. urllib.error 异常处理模块;
    3. urllib.parse url解析模块;
    4. urllib.robotparser robots.txt解析模块。

      urllib常规发送请求方式

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

      运行结果:

    b'{
      "args": {}, 
      "data": "", 
      "files": {}, 
      "form": {
        "word": "hello"
      }, 
      "headers": {
        "Accept-Encoding": "identity", 
        "Connection": "close", 
        "Content-Length": "10", 
        "Content-Type": "application/x-www-form-urlencoded", 
        "Host": "httpbin.org", 
        "User-Agent": "Python-urllib/3.6"
      }, 
      "json": null, 
      "origin": "47.74.11.227", 
      "url": "https://httpbin.org/post"
    }
    '

      需要post数据按指定编码格式编码,在使用urlopen时传递data参数即发送post请求,默认不加就是get请求。

       设置超时时间:

    import urllib.request
    
    response = urllib.request.urlopen('http://httpbin.org/get', timeout=1)
    print(response.read())
    b'{
      "args": {}, 
      "headers": {
        "Accept-Encoding": "identity", 
        "Connection": "close", 
        "Host": "httpbin.org", 
        "User-Agent": "Python-urllib/3.6"
      }, 
      "origin": "36.57.169.42", 
      "url": "https://httpbin.org/get"
    }
    '

      设置超时时间主要是防止爬取某些页面速度极慢,爬的时间过长造成假死状态,从而影响我们的爬虫性能,所以会用到我们的超时时间。

      urlopen打开的是什么类型的数据呢,或者是是什么对象。

    import urllib.request
    
    response = urllib.request.urlopen('https://www.python.org')
    print(type(response))
    <class 'http.client.HTTPResponse'>

      这个对象可以read()方法读取。那么我们都可以读取到那些东西呢。

    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-xss-protection', '1; mode=block'), ('X-Clacks-Overhead', 'GNU Terry Pratchett'), ('Via', '1.1 varnish'), ('Fastly-Debug-Digest', 'a63ab819df3b185a89db37a59e39f0dd85cf8ee71f54bbb42fae41670ae56fd2'), ('Content-Length', '48907'), ('Accept-Ranges', 'bytes'), ('Date', 'Wed, 31 Jan 2018 11:39:52 GMT'), ('Via', '1.1 varnish'), ('Age', '2396'), ('Connection', 'close'), ('X-Served-By', 'cache-iad2150-IAD, cache-hnd18723-HND'), ('X-Cache', 'HIT, HIT'), ('X-Cache-Hits', '6, 11'), ('X-Timer', 'S1517398792.207858,VS0,VE0'), ('Vary', 'Cookie'), ('Strict-Transport-Security', 'max-age=63072000; includeSubDomains')]
    #获取服务器
    nginx
    #获取整个页面的信息
    import urllib.request
    
    response = urllib.request.urlopen('https://www.python.org')
    print(response.read().decode('utf-8'))

      在一般情况下我们都需要对请求对象进行改装,加上请求头等信息,这时候我们就要自己定制request对象,然后给他加buff。

    from urllib import request, parse
    
    url = 'https://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')
    #自定义构造request包含了自定义请求头
    req = request.Request(url=url, data=data, headers=headers, method='POST')
    response = request.urlopen(req)
    print(response.read().decode('utf-8'))
    {
      "args": {}, 
      "data": "", 
      "files": {}, 
      "form": {
        "name": "Germey"
      }, 
      "headers": {
        "Accept-Encoding": "identity", 
        "Connection": "close", 
        "Content-Length": "11", 
        "Content-Type": "application/x-www-form-urlencoded", 
        "Host": "httpbin.org", 
        "User-Agent": "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)"
      }, 
      "json": null, 
      "origin": "36.57.169.42", 
      "url": "https://httpbin.org/post"
    }

      另外一种加请求头的方式

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

      结果与上一种请求一定是一模一样的。上面完成了最基本的http请求,如果我们想要完成更高级的http请求,使用代理或者带上cookie值等,那么我们需要使用handler方法,handler有很多种。

    import urllib.request
    
    # 构建一个HTTPHandler处理器对象,支持处理HTTP的请求
    #http_handler = urllib2.HTTPHandler()
    
    # 在HTTPHandler增加参数"debuglevel=1"将会自动打开Debug log 模式,
    # 程序在执行的时候会打印收发包的信息
    http_handler = urllib.request.HTTPHandler(debuglevel=1)
    
    # 调用build_opener()方法构建一个自定义的opener对象,参数是构建的处理器对象
    opener = urllib.request.build_opener(http_handler)
    
    request = urllib.request.Request("http://www.baidu.com/")
    
    response = opener.open(request)
    
    print(response.read().decode('utf8'))

      这里我们定制了一个自己的opener,构建一个Handler处理器对象,参数是一个字典类型,包括代理类型和代理服务器IP+PROT。

    import urllib.request
    
    # 代理开关,表示是否启用代理
    proxyswitch = True
    # proxyswitch = False
    
    # 构建一个Handler处理器对象,参数是一个字典类型,包括代理类型和代理服务器IP+PROT
    httpproxy_handler = urllib.request.ProxyHandler({"http" : "121.41.175.199:80"})
    
    # 构建了一个没有代理的处理器对象
    nullproxy_handler = urllib.request.ProxyHandler({})
    
    if proxyswitch:
        opener = urllib.request.build_opener(httpproxy_handler)
    else:
        opener = urllib.request.build_opener(nullproxy_handler)
    
    # 构建了一个全局的opener,之后所有的请求都可以用urlopen()方式去发送,也附带Handler的功能
    urllib.request.install_opener(opener)
    
    request = urllib.request.Request("http://www.baidu.com/")
    response = urllib.request.urlopen(request)
    
    #print response.read().decode("gbk")
    print(response.read().decode('utf8'))

      保存cookie的handler

    import http.cookiejar, urllib.request
    
    cookie = http.cookiejar.CookieJar()
    handler = urllib.request.HTTPCookieProcessor(cookie)
    opener = urllib.request.build_opener(handler)
    response = opener.open('http://www.baidu.com')
    for item in cookie:
        print(item.name+"="+item.value)
    #将cookie依次打印出来
    BAIDUID=185CCA6964D4660F71AC56C5FD40F293:FG=1
    BIDUPSID=185CCA6964D4660F71AC56C5FD40F293
    H_PS_PSSID=25641_1460_24565_21125_18559
    PSTM=1517404650
    BDSVRTM=0
    BD_HOME=0

            cookie保存成文本文件

    import http.cookiejar, urllib.request
    filename = "cookie.txt"
    cookie = http.cookiejar.MozillaCookieJar(filename)
    handler = urllib.request.HTTPCookieProcessor(cookie)
    opener = urllib.request.build_opener(handler)
    response = opener.open('http://www.baidu.com')
    cookie.save(ignore_discard=True, ignore_expires=True)

      将本地的cookie读取出来然后使用本地文本里的cookie去访问网址:

    import http.cookiejar, urllib.request
    cookie = http.cookiejar.LWPCookieJar()
    cookie.load('cookie.txt', ignore_discard=True, ignore_expires=True)
    handler = urllib.request.HTTPCookieProcessor(cookie)
    opener = urllib.request.build_opener(handler)
    response = opener.open('http://www.baidu.com')
    print(response.read().decode('utf-8'))

      urlparse将网址分割成多个部分(也可以说是解析)。

    from urllib.parse import urlparse
    
    result = urlparse('http://www.baidu.com/index.html;user?id=5#comment')
    print(type(result), result)

      解析的结果:

    <class 'urllib.parse.ParseResult'> ParseResult(scheme='http', netloc='www.baidu.com', path='/index.html', params='user', query='id=5', fragment='comment')
    #另一种解析
    from urllib.parse import urlparse
    
    result = urlparse('www.baidu.com/index.html;user?id=5#comment', scheme='https')
    print(result)

      并且url里的scheme优先级更高。

    from urllib.parse import urlparse
    #url里有scheme,然后我们又传入一次,结果是什么呢
    result = urlparse('http://www.baidu.com/index.html;user?id=5#comment', scheme='https')
    print(result)
    #url win
    ParseResult(scheme='http', netloc='www.baidu.com', path='/index.html', params='user', query='id=5', fragment='comment')
    #不显示什么字段
    from urllib.parse import urlparse
    
    result = urlparse('http://www.baidu.com/index.html;user?id=5#comment', allow_fragments=False)
    print(result)
    ParseResult(scheme='http', netloc='www.baidu.com', path='/index.html', params='user', query='id=5#comment', fragment='')
    from urllib.parse import urlparse
    
    result = urlparse('http://www.baidu.com/index.html#comment', allow_fragments=False)
    print(result)
    #实际上,这个字段位false那么就减少了一次split,数据还是会存在上一级,但是path之前字段是必须有的
    ParseResult(scheme='http', netloc='www.baidu.com', path='/index.html#comment', params='', query='', fragment='')
    #反向解析
    from urllib.parse import urlunparse
    
    data = ['http', 'www.baidu.com', 'index.html', 'user', 'a=6', 'comment']
    print(urlunparse(data))
    #解析结果还原url
    http://www.baidu.com/index.html;user?a=6#comment

      url拼接

    from urllib.parse import urljoin
    
    print(urljoin('http://www.baidu.com', 'FAQ.html'))
    print(urljoin('http://www.baidu.com', 'https://cuiqingcai.com/FAQ.html'))
    print(urljoin('http://www.baidu.com/about.html', 'https://cuiqingcai.com/FAQ.html'))
    print(urljoin('http://www.baidu.com/about.html', 'https://cuiqingcai.com/FAQ.html?question=2'))
    print(urljoin('http://www.baidu.com?wd=abc', 'https://cuiqingcai.com/index.php'))
    print(urljoin('http://www.baidu.com', '?category=2#comment'))
    print(urljoin('www.baidu.com', '?category=2#comment'))
    print(urljoin('www.baidu.com#comment', '?category=2'))
    from urllib.parse import urlencode
    
    params = {
        'name': 'germey',
        'age': 22
    }
    base_url = 'http://www.baidu.com?'
    url = base_url + urlencode(params)
    print(url)
    http://www.baidu.com?name=germey&age=22

      url编码常用于汉字在url中传输时使用。以上就是urllib库常用的操作了。

      随着深入的爬虫学习,后面要接触功能强大的Requests库,Requests 唯一的一个非转基因的 Python HTTP 库,人类可以安全享用。

      Requests 允许你发送纯天然,植物饲养的 HTTP/1.1 请求,无需手工劳动。你不需要手动为 URL 添加查询字串,也不需要对 POST 数据进行表单编码。Keep-alive 和 HTTP 连接池的功能是 100% 自动化的,一切动力都来自于根植在 Requests 内部的 urllib3。

      官方文档地址:Requests: 让 HTTP 服务人类

  • 相关阅读:
    npm 默认创建项目如何自动配置
    VueJS + TypeScript 入门第一课
    实现类数组转化成数组(DOM 操作获得的返回元素值是一个类数组)
    webpack4(4.41.2) 打包出现 TypeError this.getResolve is not a function
    vue-cli 4.0.5 配置环境变量样例
    关于H5页面在微信浏览器中音视频播放的问题
    ant-design-vue 快速避坑指南
    记elementUI一个大坑
    VUE自定义(有限)库存日历插件
    node转发请求 .csv格式文件下载 中文乱码问题 + 文件上传笔记
  • 原文地址:https://www.cnblogs.com/Jeffding/p/8087267.html
Copyright © 2011-2022 走看看