精华内容
下载资源
问答
  • urllib

    2018-12-02 21:44:30
    urllib post  一、如同postman的数据在请求体中,并为json数据,并不在URL中 import urllib import json from urllib.request import urlopen from urllib.request import Request from urllib.parse import ...

    urllib

    post

     一、如同postman的数据在请求体中,并为json数据,并不在URL中

    import urllib
    import json
    from urllib.request import urlopen
    from urllib.request import Request
    from urllib.parse import urlencode
    
    # 准备url,拼接好
    login_url = 'http://{server}:{port}{login_url}'.format(**Params)
    
    # 准备登录数据
    dict_data = {}
    dict_data['username'] = Params['username']
    dict_data['password'] = Params['password']
    
    json_data = json.dumps(dict_data)       # dict -> json字符串, 要发送的数据是json数据
    
    # 调整请求格式
    data = bytes(json_data, 'utf8')     # json -> bytes     b'{"username": "asafx", "password": "qyskhfa"}'
    
    request = Request(url=login_url, data=data, headers=Params['headers'])    # 处理成为一个Request实例对象,urllib.request.Request object
    response = urlopen(request)     # 获取响应
    
    json_data = response.read().decode('utf-8')      # 读取数据为bytes,然后解码为json字符串
    dict_data = json.loads(json_data)           # dict字典数据
    

    草稿:

     

    展开全文
  • Python urlliburllib2、urllib3用法及区别

    万次阅读 多人点赞 2019-02-18 01:06:08
    `urllib`、`urllib2`、`urllib3`介绍

    简介1

    在可供使用的网络库中,urlliburllib2可能是投入产出比最高的两个,是Python中操作url的官方标准库。它们让你能够通过网络访问文件,就像这些文件位于你的计算机中一样。只需一个简单的函数调用,就几乎可将统一资源定位符(URL)可指向的任何动作作为程序的输入。结合re模块使用将发挥强大威力!

    一个简单的例子:

    req = urllib2.Request(
    	url=url,
    	data=postdata,
    	headers=headers
    )
    result = urllib2.urlopen(req)
    

    模块urlliburllib2的功能差不多,简单来说urllib2urllib的增强——urllib2更好一些,但是urllib中有urllib2中所没有的函数。对于简单的下载, urllib绰绰有余。 如果需要实现HTTP身份验证Cookie亦或编写扩展来处理自己的协议,urllib2可能是更好的选择。在Python2.x中主要为urlliburllib2,这两个标准库是不可相互替代的。但是在Python3.x中将urllib2合并到了urllib,这一点值得注意。

    • urllib支持设置编码的函数urllib.urlencode,在模拟登陆的时候经常需要传递经过post编码之后的参数,如果不想使用第三方库完成模拟登录,就必须使用到标准库中的urlliburllib提供一些比较原始基础的方法而urllib2并没有,比如urllib中的urlencode方法用来GET查询字符串的产生。

    • urllib2比较有优势的地方在于urllib2.openurl中可以接受一个Request类的实例来设置Request参数,来修改/设置Header头从而达到控制HTTP Request的header部分的目的,也可以修改用户代理,设置cookie等,但urllib仅可以接受URL。这就意味着,如果你访问一个网站想更改User Agent(可以伪装你的浏览器),你就需要使用urllib2urllib2模块没有加入urllib.urlretrieve函数以及urllib.quote等一系列quote和unquote功能,这个时候就需要urllib的辅助。

    因此Python2.x中,urlliburllib2两者搭配使用。

    1、打开远程文件

    几乎可以像打开本地文件一样打开远程文件,差别是只能使用读取模式,以及使用模块urllib.request中的函数urlopen,而不是open(或file)。

    from urllib.request import urlopen
    webpage = urlopen('http://www.python.org')
    

    如果连接到了网络,变量webpage将包含一个类似于文件的对象,这个对象与网页http://www.python.org相关联。

    注意:要在没有联网的情况下尝试使用模块urllib,可使用以file:打头的URL访问本地文件,如file:c:\text\somefile.txt(别忘了对反斜杠进行转义)。

    urlopen返回的类似于文件的对象支持方法:close、 read、readline和readlines,还支持迭代等。

    假设要提取刚才所打开网页中链接About的相对URL, 可使用正则表达式 。

    >>> import re
    >>> text = webpage.read()
    # 注意:如果这个网页发生了变化,你可能需要修改使用的正则表达式。
    >>> m = re.search(b'<a href="([^"]+)" .*?>about</a>', text, re.IGNORECASE)
    >>> m.group(1)
    'about'
    
    02、获取远程文件

    函数urlopen返回一个类似于文件的对象,可从中读取数据。如果要让urllib替你下载文件并将其副本存储在一个本地文件中,可使用urlretrieve。这个函数不返回一个类似于文件的对象,而返回一个格式为(filename, headers)的元组,其中filename是本地文件的名称(由urllib自动创建),而headers包含一些有关远程文件的信息(这里不会介绍headers, 如果你想更深入地了解它,请在有关urllib的标准库文档中查找urlretrieve)。如果要给下载的副本指定文件名,可通过第二个参数来提供。

    urlretrieve('http://www.python.org', 'C:\\python_webpage.html')
    

    这将获取Python官网的主页,并将其存储到文件C:\python_webpage.html中。如果你没有指定文件名,下载的副本将放在某个临时位置,可使用函数open来打开。但使用完毕后,你可能想将其删除以免占用磁盘空间。要清空这样的临时文件,可调用函数urlcleanup且不提供任何参数,它将负责替你完成清空工作。

    一些实用的函数

    除了通过URL读取和下载文件外,urllib还提供了一些用于操作URL的函数,如下所示(这里假设你对URL和CGI略知一二)。

    • quote(string[, safe]) 返回一个字符串,其中所有的特殊字符(在URL中有特殊意义的字符)都已替换为对URL友好的版本(如将~替换为%7E),如果要将包含特殊字符的字符串用作URL很有用。参数safe是一个字符串(默认为'/'),包含不应像这样对其进行编码的字符

    • quote_plus(string[, safe]) 类似于quote,但也将空格替换为加号。

    • unquote(string):与quote相反。

    • unquote_plus(string):与quote_plus相反。

    • urlencode(query[, doseq]) 将映射(如字典)或由包含两个元素的元组(形如(key, value))组成的序列转换为“使用URL编码的”字符串。这样的字符串可用于CGI查询中(详细信息请参阅Python文档)。


    一、urllib

    urllib作为Python的标准库,基本上涵盖了基础的网络请求功能。

    1。 urllib.request

    urllib中,request这个模块主要负责构造和发起网络请求,并在其中加入Headers、Proxy等。

    1. 发起GET请求

    主要使用urlopen()方法来发起请求:

    from urllib import request
    
    resp = request.urlopen('http://www.baidu.com')
    print(resp.read().decode())
    

    urlopen()方法中传入字符串格式的url地址,则此方法会访问目标网址,然后返回访问的结果。

    返回的结果会是一个http.client.HTTPResponse对象,使用此对象的read()方法可以获取访问网页获得的数据。但是要注意的是,获得的数据会是bytes的二进制格式,所以需要decode()一下,转换成字符串格式。

    使用带参数的GET方法取回URL:

    >>> import urllib
    >>> params = urllib.urlencode({'spam': 1, 'eggs': 2, 'bacon': 0})
    >>> f = urllib.urlopen("http://www.musi-cal.com/cgi-bin/query?%s" % params)
    >>> print f.read()
    
    2. 发起POST请求

    urlopen()默认的访问方式是GET,当在urlopen()方法中传入data参数时,则会发起POST请求。注意:传递的data数据需要为bytes格式。timeout参数还可以设置超时时间如果请求时间超出,那么就会抛出异常。

    from urllib import request
    
    resp = request.urlopen('http://httpbin.org/post', data=b'word=hello', timeout=10)
    print(resp.read().decode())
    

    使用带参数的POST方法:

    >>> import urllib
    >>> params = urllib.urlencode({'spam': 1, 'eggs': 2, 'bacon': 0})
    >>> f = urllib.urlopen("http://www.musi-cal.com/cgi-bin/query", params)
    >>> print f.read()
    
    3. 添加Headers

    通过urllib发起的请求会有默认的一个Headers:"User-Agent":"Python-urllib/3.6",指明请求是由urllib发送的。
    所以遇到一些验证User-Agent的网站时,我们需要自定义Headers,而这需要借助于urllib.request中的Request对象。

    from urllib import request
    
    url = 'http://httpbin.org/get'
    headers = {'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36'}
    
    # 需要使用url和headers生成一个Request对象,然后将其传入urlopen方法中
    req = request.Request(url, headers=headers)
    resp = request.urlopen(req)
    print(resp.read().decode())
    
    4. Request对象

    如上所示,urlopen()方法中不止可以传入字符串格式的url,也可以传入一个Request对象来扩展功能,Request对象如下所示。

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

    构造Request对象必须传入url参数,data数据和headers都是可选的。
    最后,Request方法可以使用method参数来自由选择请求的方法,如PUT,DELETE等等,默认为GET。

    5. 添加Cookie

    为了在请求时能带上Cookie信息,我们需要重新构造一个opener。
    使用request.build_opener方法来进行构造opener,将我们想要传递的cookie配置到opener中,然后使用这个opener的open方法来发起请求。

    from http import cookiejar
    from urllib import request
    
    url = 'https://www.baidu.com'
    
    # 创建一个cookiejar对象
    cookie = cookiejar.CookieJar()
    
    # 使用HTTPCookieProcessor创建cookie处理器
    cookies = request.HTTPCookieProcessor(cookie)
    
    # 并以它为参数创建Opener对象
    opener = request.build_opener(cookies)
    
    # 使用这个opener来发起请求
    resp = opener.open(url)
    
    # 查看之前的cookie对象,则可以看到访问百度获得的cookie
    for i in cookie:
        print(i)
    

    或者也可以把这个生成的opener使用install_opener方法来设置为全局的,之后使用urlopen方法发起请求时,都会带上这个cookie

    # 将这个opener设置为全局的opener
    request.install_opener(opener)
    resp = request.urlopen(url)
    
    6. 设置Proxy代理

    使用爬虫来爬取数据的时候,常常需要使用代理来隐藏我们的真实IP。

    from urllib import request
    
    url = 'http://httpbin.org/ip'
    proxy = {'http':'218.18.232.26:80','https':'218.18.232.26:80'}
    
    # 创建代理处理器
    proxies = request.ProxyHandler(proxy)
    # 创建opener对象
    opener = request.build_opener(proxies)
    
    resp = opener.open(url)
    print(resp.read().decode())
    

    urllib官方文档的例子:

    # 使用HTTP代理,自动跟踪重定向
    >>> import urllib
    >>> proxies = {'http': 'http://proxy.example.com:8080/'}
    >>> opener = urllib.FancyURLopener(proxies)
    >>> f = opener.open("http://www.python.org")
    >>> f.read()
    
    # 不使用代理
    >>> import urllib
    >>> opener = urllib.FancyURLopener({})
    >>> f = opener.open("http://www.python.org/")
    >>> f.read()
    
    7. 下载数据到本地

    在我们进行网络请求时常常需要保存图片或音频等数据到本地,一种方法是使用python的文件操作,将read()获取的数据保存到文件中。
    而urllib提供了一个urlretrieve()方法,可以简单的直接将请求获取的数据保存成文件。

    from urllib import request
    
    url = 'http://python.org/'
    # urlretrieve()方法传入的第二个参数为文件保存的位置,以及文件名。
    request.urlretrieve(url, 'python.html')
    

    urlretrieve()方法是Python2.x直接移植过来的方法,以后有可能在某个版本中弃用。

    2。urllib.response

    在使用urlopen()方法或者opener的open()方法发起请求后,获得的结果是一个response对象。这个对象有一些方法和属性,可以让我们对请求返回的结果进行一些处理。

    read():获取响应返回的数据,只能使用一次。

    getcode():获取服务器返回的状态码。

    getheaders():获取返回响应的响应报头。

    geturl():获取访问的url。

    3。urllib.parse

    urllib.parseurllib中用来解析各种数据格式的模块。

    1. urllib.parse.quote

    在url中,是只能使用ASCII中包含的字符的,也就是说,ASCII不包含的特殊字符,以及中文等字符都是不可以在url中使用的。而我们有时候又有将中文字符加入到url中的需求,例如百度的搜索地址:https://www.baidu.com/s?wd=南北?之后的wd参数,则是我们搜索的关键词。那么我们实现的方法就是将特殊字符进行url编码,转换成可以url可以传输的格式,urllib中可以使用quote()方法来实现这个功能。

    >>> from urllib import parse
    >>> keyword = '南北'
    >>> parse.quote(keyword)
    '%E5%8D%97%E5%8C%97'
    

    如果需要将编码后的数据转换回来,可以使用unquote()方法。

    >>> parse.unquote('%E5%8D%97%E5%8C%97')
    '南北'
    
    2. urllib.parse.urlencode

    在访问url时,我们常常需要传递很多的url参数,而如果用字符串的方法去拼接url的话,会比较麻烦,所以urllib中提供了urlencode这个方法来拼接url参数。

    >>> from urllib import parse
    >>> params = {'wd': '南北', 'code': '1', 'height': '188'}
    >>> parse.urlencode(params)
    'wd=%E5%8D%97%E5%8C%97&code=1&height=188'
    

    4。urllib.error

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

    HTTPError还包含了三个属性:

    • code:请求的状态码
    • reason:错误的原因
    • headers:响应的报头

    例子:

    In [1]: from urllib.error import HTTPError
    
    In [2]: try:
       ...:     request.urlopen('https://www.jianshu.com')
       ...: except HTTPError as e:
       ...:     print(e.code)
    
    403
    

    二、urllib2

    Python2.x的一个例子:

    import urllib2
     
    # 设置浏览器请求头
    ua_headers={
        "User-Agent":"Mozilla/5.0 (Windows NT 6.1; WOW64; rv:34.0) Gecko/20100101 Firefox/34.0"
    }
    
    #建立请求内容
    request=urllib2.Request("http://baidu.com/",headers=ua_headers)
    
    #获取响应
    response=urllib2.urlopen(request)
    
    #页面内容
    html=response.read()
    
    print html
    print response.getcode()	#返回响应码
    print response.geturl()		#返回实际url
    print response.info() 		#返回服务器响应的报头
    

    Python3.x(整合之后的urllib)的一个例子:

    from urllib import request
    
    url = r'https://www.baidu.com/'
    headers = {
        'User-Agent': r'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) '
                      r'Chrome/45.0.2454.85 Safari/537.36 115Browser/6.0.3',
        'Referer': r'http://www.lagou.com/zhaopin/Python/?labelWords=label',
        'Connection': 'keep-alive'
    }
    req = request.Request(url, headers=headers)
    html = request.urlopen(req).read()
    
    # 处理编码
    html = html.decode('utf-8')
    print(html)
    

    来自urllib2官方文档的几个例子:

    GET一个URL:
    >>> import urllib2
    >>> f = urllib2.urlopen('http://www.python.org/')
    >>> print f.read()
    
    使用基本的HTTP认证:
    import urllib2
    auth_handler = urllib2.HTTPBasicAuthHandler()
    auth_handler.add_password(realm='PDQ Application',
                              uri='https://mahler:8092/site-updates.py',
                              user='klem',
                              passwd='kadidd!ehopper')
    opener = urllib2.build_opener(auth_handler)
    urllib2.install_opener(opener)
    urllib2.urlopen('http://www.example.com/login.html')
    

    注:build_opener()默认提供很多处理程序,包括代理处理程序,代理默认会被设置为环境变量所提供的。

    一个使用代理的例子:
    proxy_handler = urllib2.ProxyHandler({'http': 'http://www.example.com:3128/'})
    proxy_auth_handler = urllib2.ProxyBasicAuthHandler()
    proxy_auth_handler.add_password('realm', 'host', 'username', 'password')
    
    opener = urllib2.build_opener(proxy_handler, proxy_auth_handler)
    opener.open('http://www.example.com/login.html')
    
    添加HTTP请求头部:
    import urllib2
    req = urllib2.Request('http://www.example.com/')
    req.add_header('Referer', 'http://www.python.org/')
    r = urllib2.urlopen(req)
    
    更改User-agent:
    import urllib2
    opener = urllib2.build_opener()
    opener.addheaders = [('User-agent', 'Mozilla/5.0')]
    opener.open('http://www.example.com/')
    

    注:httplibhttplib2httplib是http客户端协议的实现,通常不直接使用,urllib是以httplib为基础,httplib2是第三方库,比httplib有更多特性。httplib比较底层,一般使用的话用urlliburllib2即可。

    三、Python3.X中使用整合后的urllib

    Python2.x 有这些库名可用: urlliburllib2urllib3httplibhttplib2requests
    Python3.x 有这些库名可用: urlliburllib3httplib2requests


    若只使用Python3.x,记住有个urllib的库就行了。Pyhton2.x和Python3.x都有urllib3requests, 它们不是标准库。urllib3提供线程安全连接池和文件post等支持,与urlliburllib2的关系不大。requests 自称HTTP for Humans,使用更简洁方便。

    Python3.x中将urllib2合并到了urllib,之后此包分成了以下几个模块:

    • urllib.request 用于打开和读取URL

    • urllib.error 用于处理前面request引起的异常

    • urllib.parse 用于解析URL

    • urllib.robotparser用于解析robots.txt文件

    Python3.x中,随着urllib2合入urllib,一些常用的方法也发生了变化:2

    1. 在Python2.x中使用import urlparse——在Python3.x中会使用import urllib.parse

    2. 在Python2.x中使用urllib2.urlopenurllib.urlopen(已弃用)——在Python3.x中会使用urllib.request.urlopen

    3. 在Python2.x中使用urllib2.Request——在Python3.x中会使用urllib.request.Request

    4. 在Python2.x中使用urllib.quote——在Python3.x中会使用urllib.request.quote

    5. 在Python2.x中使用urllib.urlencode——在Python3.x中会使用urllib.parse.urlencode

    6. 在Python2.x中使用cookielib.CookieJar——在Python3.x中会使用http.CookieJar

    7. 异常处理:在Python2.x中使用urllib2.URLError,urllib2.HTTPError——在Python3.x中会使用urllib.error.URLError,urllib.error.HTTPError

    :在Python3.3后urllib2已经不能再用,所有urllib2全部用urllib.request来代替。


    urlliburllib2在Python2.x以及Python3.x的区别:

    Python2.x中:
    import urllib
    import urllib2
    

    1、共同点:都可以直接用urlopen(‘url’)请求页面

    2、不同点:urlliburlencode(dict)unquote()进行编码和解码

    3、对于error:

    try:
    	response = urllib2.urlopen("http://pythonsite.com/111341.html")
    except urllib2.HTTPError as e:
    	print(e.reason)
    	print(e.code)
    	print(e.headers)
    except urllib2.URLError as e:
    	print(e.reason)
    
    else:
    	print("reqeust successfully")
    
    Python3.x中:

    1、请求页面:urllib.request.urlopen(‘url’)

    2、对于error:

    from urllib import request,error
    try:
    	response = request.urlopen("http://pythonsite.com/113211.html")
    except error.HTTPError as e:
    	print(e.reason)
    	print(e.code)
    	print(e.headers)
    except error.URLError as e:
    	print(e.reason)
    
    else:
    	print("reqeust successfully")
    

    几个官方例子:

    GET一个URL:
    >>> import urllib.request
    >>> with urllib.request.urlopen('http://www.python.org/') as f:
    ...     print(f.read(300))
    
    PUT一个请求:
    import urllib.request
    DATA=b'some data'
    req = urllib.request.Request(url='http://localhost:8080', data=DATA, method='PUT')
    with urllib.request.urlopen(req) as f:
        pass
    print(f.status)
    print(f.reason)
    
    基本的HTTP认证:
    import urllib.request
    auth_handler = urllib.request.HTTPBasicAuthHandler()
    auth_handler.add_password(realm='PDQ Application',
                              uri='https://mahler:8092/site-updates.py',
                              user='klem',
                              passwd='kadidd!ehopper')
    opener = urllib.request.build_opener(auth_handler)
    urllib.request.install_opener(opener)
    urllib.request.urlopen('http://www.example.com/login.html')
    
    使用proxy:
    proxy_handler = urllib.request.ProxyHandler({'http': 'http://www.example.com:3128/'})
    proxy_auth_handler = urllib.request.ProxyBasicAuthHandler()
    proxy_auth_handler.add_password('realm', 'host', 'username', 'password')
    
    opener = urllib.request.build_opener(proxy_handler, proxy_auth_handler)
    opener.open('http://www.example.com/login.html')
    
    添加头部:
    import urllib.request
    req = urllib.request.Request('http://www.example.com/')
    req.add_header('Referer', 'http://www.python.org/')
    r = urllib.request.urlopen(req)
    
    更改User-agent:
    import urllib.request
    opener = urllib.request.build_opener()
    opener.addheaders = [('User-agent', 'Mozilla/5.0')]
    opener.open('http://www.example.com/')
    
    使用GET时设置URL的参数:
    >>> import urllib.request
    >>> import urllib.parse
    >>> params = urllib.parse.urlencode({'spam': 1, 'eggs': 2, 'bacon': 0})
    >>> url = "http://www.musi-cal.com/cgi-bin/query?%s" % params
    >>> with urllib.request.urlopen(url) as f:
    ...     print(f.read().decode('utf-8'))
    ...
    
    使用POST时设置参数:
    >>> import urllib.request
    >>> import urllib.parse
    >>> data = urllib.parse.urlencode({'spam': 1, 'eggs': 2, 'bacon': 0})
    >>> data = data.encode('ascii')
    >>> with urllib.request.urlopen("http://requestb.in/xrbl82xr", data) as f:
    ...     print(f.read().decode('utf-8'))
    ...
    
    指定proxy:
    >>> import urllib.request
    >>> proxies = {'http': 'http://proxy.example.com:8080/'}
    >>> opener = urllib.request.FancyURLopener(proxies)
    >>> with opener.open("http://www.python.org") as f:
    ...     f.read().decode('utf-8')
    ...
    
    不使用proxy, 覆盖环境变量的proxy:
    >>> import urllib.request
    >>> opener = urllib.request.FancyURLopener({})
    >>> with opener.open("http://www.python.org/") as f:
    ...     f.read().decode('utf-8')
    ...
    

    注:Python2.X中的httplib被重命名为http.client

    使用2to3工具转换源码时, 会自动处理这几个库的导入.

    总的来说, 使用Python3.x, 记住只有urllib, 想要更简洁好用就用requests, 但不够通用。


    四、urllib33

    urllib3功能强大且易于使用,用于HTTP客户端的Python库。许多Python的原生系统已经开始使用urllib3

    urllib3提供了很多python标准库urllib里所没有的重要特性:

    • 线程安全
    • 连接池
    • 客户端SSL/TLS验证
    • 文件分部编码上传
    • 协助处理重复请求和HTTP重定位
    • 支持gzip和deflate压缩编码
    • 支持HTTP和SOCKS代理
    • 100%测试覆盖率

    1。安装

    urllib3是一个第三方库,pip安装:

    $ pip install urllib3
    

    或者,可以从GitHub获取最新的源代码:

    $ git clone git://github.com/shazow/urllib3.git
    $ python setup.py install
    

    2。使用

    urllib3主要使用连接池进行网络请求的访问,所以访问之前需要先创建一个连接池对象:

    # 导入urllib3模块:
    >>> import urllib3
    # 需要一个PoolManager实例来生成请求,由该实例对象处理与线程池的连接以及线程安全的所有细节,不需要任何人为操作:
    >>> http = urllib3.PoolManager()
    # 通过request()方法创建一个请求,该方法返回一个HTTPResponse对象:
    >>> r = http.request('GET', 'http://httpbin.org/robots.txt')
    >>> r.status
    200
    >>> r.data
    'User-agent: *\nDisallow: /deny\n'
    
    1.设置headers

    通过request()方法向请求(request)中添加一些其他信息:

    >>> r = http.request(
    ...     'POST',
    ...     'http://httpbin.org/post',
    ...     fields={'hello': 'world'})
    

    或者:在request()方法中,可以定义一个字典类型(dictionary),并作为headers参数传入:

    headers={'X-Something': 'value'}
    resp = http.request('GET', 'http://httpbin.org/headers', headers=headers)
    
    2.设置url参数

    对于GET等没有请求正文的请求方法,可以简单的通过设置fields参数来设置url参数。

    fields = {'arg': 'value'}
    resp = http.request('GET', 'http://httpbin.org/get', fields=fields)
    

    如果使用的是POST等方法,则会将fields作为请求的请求正文发送。
    所以,如果你的POST请求是需要url参数的话,那么需要自己对url进行拼接。

    fields = {'arg': 'value'}
    resp = http.request('POST', 'http://httpbin.org/get', fields=fields)
    
    3.设置代理
    >>> import urllib3
    >>> proxy = urllib3.ProxyManager('http://50.233.137.33:80', headers={'connection': 'keep-alive'})
    >>> resp = proxy.request('get', 'http://httpbin.org/ip')
    >>> resp.status
    200
    >>> resp.data
    b'{"origin":"50.233.136.254"}\n'
    

    urllib3中没有直接设置cookies的方法和参数,只能将cookies设置到headers中。

    4.官网的一些介绍

    请求(request)中的数据项(request data)可包括:

    Headers

    在request()方法中,可以定义一个字典类型(dictionary)并作为headers参数传入:

    >>> r = http.request(
    ...     'GET',
    ...     'http://httpbin.org/headers',
    ...     headers={
    ...         'X-Something': 'value'
    ...     })
    >>> json.loads(r.data.decode('utf-8'))['headers']
    {'X-Something': 'value', ...}
    
    Query parameters

    对于GET、HEAD和DELETE请求,可以简单的通过定义一个字典类型作为fields参数传入即可:

    >>> r = http.request(
    ...     'GET',
    ...     'http://httpbin.org/get',
    ...     fields={'arg': 'value'})
    >>> json.loads(r.data.decode('utf-8'))['args']
    {'arg': 'value'}
    

    对于POST和PUT请求(request),需要手动对传入数据进行编码,然后加在URL之后:

    >>> from urllib.parse import urlencode
    >>> encoded_args = urlencode({'arg': 'value'})
    >>> url = 'http://httpbin.org/post?' + encoded_args
    >>> r = http.request('POST', url)
    >>> json.loads(r.data.decode('utf-8'))['args']
    {'arg': 'value'}
    
    Form data

    对于PUT和POST请求(request),urllib3会自动将字典类型的field参数编码成表格类型.

    >>> r = http.request(
    ...     'POST',
    ...     'http://httpbin.org/post',
    ...     fields={'field': 'value'})
    >>> json.loads(r.data.decode('utf-8'))['form']
    {'field': 'value'}
    
    JSON

    在发起请求时,可以通过定义body参数并定义headers的Content-Type参数来发送一个已经过编译的JSON数据:

    >>> import json
    >>> data = {'attribute': 'value'}
    >>> encoded_data = json.dumps(data).encode('utf-8')
    >>> r = http.request(
    ...     'POST',
    ...     'http://httpbin.org/post',
    ...     body=encoded_data,
    ...     headers={'Content-Type': 'application/json'})
    >>> json.loads(r.data.decode('utf-8'))['json']
    {'attribute': 'value'}
    
    Files & binary data

    使用multipart/form-data编码方式上传文件,可以使用和传入Form data数据一样的方法进行,并将文件定义为一个元组的形式(file_name,file_data):

    >>> with open('example.txt') as fp:
    ...     file_data = fp.read()
    >>> r = http.request(
    ...     'POST',
    ...     'http://httpbin.org/post',
    ...     fields={
    ...         'filefield': ('example.txt', file_data),
    ...     })
    >>> json.loads(r.data.decode('utf-8'))['files']
    {'filefield': '...'}
    

    文件名(filename)的定义不是严格要求的,但是推荐使用,以使得表现得更像浏览器。同时,还可以向元组中再增加一个数据来定义文件的MIME类型:

    >>> r = http.request(
    ...     'POST',
    ...     'http://httpbin.org/post',
    ...     fields={
    ...         'filefield': ('example.txt', file_data, 'text/plain'),
    ...     })
    

    如果是发送原始二进制数据,只要将其定义为body参数即可。同时,建议对headerContent-Type参数进行设置:

    >>> with open('example.jpg', 'rb') as fp:
    ...     binary_data = fp.read()
    >>> r = http.request(
    ...     'POST',
    ...     'http://httpbin.org/post',
    ...     body=binary_data,
    ...     headers={'Content-Type': 'image/jpeg'})
    >>> json.loads(r.data.decode('utf-8'))['data']
    b'...'
    

    Response content

    The HTTPResponse object provides status, data, and header attributes:

    >>> r = http.request('GET', 'http://httpbin.org/ip')
    >>> r.status
    200
    >>> r.data
    b'{\n  "origin": "104.232.115.37"\n}\n'
    >>> r.headers
    HTTPHeaderDict({'Content-Length': '33', ...})
    
    JSON content

    JSON content can be loaded by decoding and deserializing the data attribute of the request:

    >>> import json
    >>> r = http.request('GET', 'http://httpbin.org/ip')
    >>> json.loads(r.data.decode('utf-8'))
    {'origin': '127.0.0.1'}
    
    Binary content

    The data attribute of the response is always set to a byte string representing the response content:

    >>> r = http.request('GET', 'http://httpbin.org/bytes/8')
    >>> r.data
    b'\xaa\xa5H?\x95\xe9\x9b\x11'
    

    Note: For larger responses, it’s sometimes better to stream the response.

    Using timeouts

    使用timeout,可以控制请求的运行时间。在一些简单的应用中,可以将timeout参数设置为一个浮点数:

    >>> http.request(
    ...     'GET', 'http://httpbin.org/delay/3', timeout=4.0)
    <urllib3.response.HTTPResponse>
    >>> http.request(
    ...     'GET', 'http://httpbin.org/delay/3', timeout=2.5)
    MaxRetryError caused by ReadTimeoutError
    

    要进行更精细的控制,可以使用Timeout实例,将连接的timeout和读的timeout分开设置:

    >>> http.request(
    ...     'GET',
    ...     'http://httpbin.org/delay/3',
    ...     timeout=urllib3.Timeout(connect=1.0))
    <urllib3.response.HTTPResponse>
    >>> http.request(
    ...     'GET',
    ...     'http://httpbin.org/delay/3',
    ...     timeout=urllib3.Timeout(connect=1.0, read=2.0))
    MaxRetryError caused by ReadTimeoutError
    

    如果想让所有的request都遵循一个timeout,可以将timeout参数定义在PoolManager中:

    >>> http = urllib3.PoolManager(timeout=3.0)
    # 或者这样
    >>> http = urllib3.PoolManager(
    ...     timeout=urllib3.Timeout(connect=1.0, read=2.0))
    

    当在具体的request中再次定义timeout时,会覆盖PoolManager层面上的timeout。

    请求重试(Retrying requests):

    urllib3可以自动重试幂等请求,原理和handles redirect一样。可以通过设置retries参数对重试进行控制。Urllib3默认进行3次请求重试,并进行3次方向改变。

    给retries参数定义一个整型来改变请求重试的次数:

    >>> http.requests('GET', 'http://httpbin.org/ip', retries=10)
    

    关闭请求重试(retrying request)及重定向(redirect)只要将retries定义为False即可:

    >>> http.request(
    ...     'GET', 'http://nxdomain.example.com', retries=False)
    NewConnectionError
    >>> r = http.request(
    ...     'GET', 'http://httpbin.org/redirect/1', retries=False)
    >>> r.status
    302
    

    关闭重定向(redirect)但保持重试(retrying request),将redirect参数定义为False即可:

    >>> r = http.request(
    ...     'GET', 'http://httpbin.org/redirect/1', redirect=False)
    >>> r.status
    302
    

    要进行更精细的控制,可以使用retry实例,通过该实例可以对请求的重试进行更精细的控制。

    例如,进行3次请求重试,但是只进行2次重定向:

    >>> http.request(
    ...     'GET',
    ...     'http://httpbin.org/redirect/3',
    ...     retries=urllib3.Retry(3, redirect=2))
    MaxRetryError
    

    You can also disable exceptions for too many redirects and just return the 302 response:

    >>> r = http.request(
    ...     'GET',
    ...     'http://httpbin.org/redirect/3',
    ...     retries=urllib3.Retry(
    ...         redirect=2, raise_on_redirect=False))
    >>> r.status
    302
    

    如果想让所有请求都遵循一个retry策略,可以在PoolManager中定义retry参数:

    >>> http = urllib3.PoolManager(retries=False)
    # 或者这样:
    >>> http = urllib3.PoolManager(
    ...     retries=urllib3.Retry(5, redirect=2))
    

    当在具体的request中再次定义retry时,会覆盖 PoolManager层面上的retry。

    Errors & Exceptions

    urllib3 wraps lower-level exceptions, for example:

    >>> try:
    ...     http.request('GET', 'nx.example.com', retries=False)
    >>> except urllib3.exceptions.NewConnectionError:
    ...     print('Connection failed.')
    

    See exceptions for the full list of all exceptions.

    Logging

    If you are using the standard library logging module urllib3 will emit several logs. In some cases this can be undesirable. You can use the standard logger interface to change the log level for urllib3’s logger:

    >>> logging.getLogger("urllib3").setLevel(logging.WARNING)
    

    五、requests

    requests使用的是urllib3,它继承了urllib2的所有特性。requests有很大功能特性:

    • 支持HTTP连接保持和连接池;
    • 支持使用cookie保持会话;
    • 支持文件上传;
    • 支持自动确定响应内容的编码;
    • 支持国际化的URL和POST数据自动编码。

    requests是第三方类库,需要另外安装。

    简单使用:
    import requests
     
    r = requests.get(url='http://www.baidu.com')    # 最基本的GET请求
    print(r.status_code)    # 获取返回状态
    
    #带参数的GET请求,http://dict.baidu.com/s?wd=python
    r = requests.get(url='http://dict.baidu.com/s', params={'wd':'python'})   
    print(r.url)
    print(r.text)   #打印解码后的返回数据
    

    关于requests更详细的介绍,请参阅 https://blog.csdn.net/jiduochou963/article/details/87564359


    参考:
    python中urllib, urllib2,urllib3, httplib,httplib2, request的区别 https://blog.csdn.net/permike/article/details/52437492
    Python网络请求urllib和urllib3详解 https://www.jianshu.com/p/f05d33475c78
    Python–urllib3库详解1 https://www.cnblogs.com/KGoing/p/6146999.html
    urllib2库.官方文档翻译 https://blog.csdn.net/u014343243/article/details/49308043


    1. 部分内容参考Python基础教程 ↩︎

    2. 进一步了解urllib2,参见中文版翻译文档:http://blog.csdn.net/u014343243/article/details/49308043 ↩︎

    3. urllib3官方文档: https://urllib3.readthedocs.io/en/latest/
      urllib3其他参考文档: https://pypi.org/project/urllib3/ ↩︎

    展开全文
  • Python urllib urllib模块

    2017-02-25 20:53:36
    Python urllib urllib2 urllib模块
  • Python urllib urllib2 urllib模块安装说明
  • python3网络爬虫一《使用urllib.request发送请求》

    万次阅读 多人点赞 2017-07-25 16:16:05
    python 爱好者交流群:810306356 这里有很多像你一样的伙伴,共同分享学习python的经验!...而在Python3中,已经不存在urllib2这个库了,统一为urllib。Python3 urllib库官方链接 https://docs.pytho...

     

    使用urllib

    顺便提一下

    如果有任何问题,你可以在这里找到我 ,软件测试交流qq群,209092584

     

    在Python2版本中,有urllib和urlib2两个库可以用来实现request的发送。而在Python3中,已经不存在urllib2这个库了,统一为urllib。Python3 urllib库官方链接       

    https://docs.python.org/3/library/urllib.html

     

     

    urllib中包括了四个模块,包括

     

    urllib.request,urllib.error,urllib.parse,urllib.robotparser

     

     

    urllib.request可以用来发送request和获取request的结果
    urllib.error包含了urllib.request产生的异常
    urllib.parse用来解析和处理URL

     

    urllib.robotparse用来解析页面的robots.txt文件

     

     

    可见其中模拟请求使用的最主要的库便是urllib.request,异常处理用urllib.error库。

     

    下面会对它们一一进行详细的介绍。

    使用urllib.request发送请求

     

    urllib.request.urlopen()基本使用
    urllib.request 模块提供了最基本的构造 HTTP 请求的方法,利用它可以模拟浏览器的一个请求发起过程,同时它还带有处理 authenticaton (授权验证), redirections (重定向), cookies (浏览器Cookies)以及其它内容。好,那么首先我们来感受一下它的强大之处,我们百度为例,我们来把这个网页抓下来。

     

    import urllib.request
    
    response = urllib.request.urlopen("https://www.baidu.com")
    print(response.read().decode("utf-8"))

     

     

     

     

    真正的代码只有两行,我们便完成了百度的抓取,输出了网页的源代码,得到了源代码之后呢?你想要的链接、图片地址、文本信息不就都可以提取出来了吗?接下来我们看下它返回的到底是什么,利用 type 函数输出 response 的类型。

     

     

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

     

     

     

    通过输出结果可以发现它是一个 HTTPResposne 类型的对象,它主要包含的方法有 read() 、 readinto() 、getheader(name) 、 getheaders() 、 fileno() 等函数和 msg 、 version 、 status 、 reason 、 debuglevel 、 closed 等属性。 得到这个对象之后,赋值为 response ,然后就可以用 response 调用这些方法和属性,得到返回结果的一系列信息。例如 response.read() 就可以得到返回的网页内容, response.status 就可以得到返回结果的状态码,如200代表请求成功,404代表网页未找到等。

     

    下面再来一个实例感受一下:

    >>> import urllib.request
    >>> response = urllib.request.urlopen("https://www.baidu.com")
    >>> print(response.status)
    200
    >>> print(response.getheaders())
    [('Accept-Ranges', 'bytes'), ('Cache-Control', 'no-cache'), ('Content-Length', '227'), ('Content-Type', 'text/html'), ('Date', 'Tue, 25 Jul 2017 06:36:40 GMT'), ('Last-Modified', 'Wed, 28 Jun 2017 02:16:00 GMT'), ('P3p', 'CP=" OTI DSP COR IVA OUR IND COM "'), ('Pragma', 'no-cache'), ('Server', 'BWS/1.1'), ('Set-Cookie', 'BD_NOT_HTTPS=1; path=/; Max-Age=300'), ('Set-Cookie', 'BIDUPSID=BEF13521D9F33BE4108EA36C07303743; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.com'), ('Set-Cookie', 'PSTM=1500964600; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.com'), ('Strict-Transport-Security', 'max-age=0'), ('X-Ua-Compatible', 'IE=Edge,chrome=1'), ('Connection', 'close')]
    >>> print(response.getheader("Server"))
    BWS/1.1


    可见,三个输出分别输出了响应的状态码,响应的头信息,以及通过传递一个参数获取了 Server 的类型。

     

     

     

    urllib.request.urlopen()详解

     

    利用以上最基本的 urlopen() 方法,我们可以完成最基本的简单网页的 GET 请求抓取。
    如果我们想给链接传递一些参数该怎么实现呢?我们首先看一下 urlopen() 函数的API。

    urllib.request.urlopen(url, data=None, [timeout, ]*, cafile=None, capath=None, cadefault=False, context=None)


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

    data 参数是可选的,如果要添加 data ,它要是字节流编码格式的内容,即 bytes 类型,通过 bytes() 函数可以进行转化,另外如果你传递了这个 data 参数,它的请求方式就不再是 GET 方式请求,而是 POST 。

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

     

    在这里我们传递了一个参数 word ,值是 hello 。它需要被转码成 bytes (字节流)类型。其中转字节流采用了 bytes() 方法,第一个参数需要是 str (字符串)类型,需要用 urllib.parse.urlencode() 方法来将参数字典转化为字符串。第二个参数指定编码格式,在这里指定为 utf8 。
    提交的网址是 httpbin.org ,它可以提供 HTTP 请求测试。 http://httpbin.org/post 这个地址可以用来测试 POST 请求,它可以输出请求和响应信息,其中就包含我们传递的 data 参数。
    运行结果如下:

     

    {
    "args": {},
    "data": "",
    "files": {},
    "form": {
    "word": "hello"
    },
    "headers": {
    "Accept-Encoding": "identity",
    "Content-Length": "10",
    "Content-Type": "application/x-www-form-urlencoded",
    "Host": "httpbin.org",
    "User-Agent": "Python-urllib/3.5"
    },
    "json": null,
    "origin": "123.124.23.253",
    "url": "http://httpbin.org/post"
    }

     


    我们传递的参数出现在了 form 中,这表明是模拟了表单提交的方式,以 POST 方式传输数据。

     

     

    timeout参数

    timeout 参数可以设置超时时间,单位为秒,意思就是如果请求超出了设置的这个时间还没有得到响应,就会抛出异常,如果不指定,就会使用全局默认时间。它支持 HTTP 、 HTTPS 、 FTP 请求。
    下面来用一个实例感受一下:

     

    >>> import urllib.request
    >>> response = urllib.request.urlopen("http://httpbin.org/get",timeout=1)
    >>> print(response.read())


    结果如下:

     

    During handling of the above exception, another exception occurr
    ed:
    Traceback (most recent call last): File "/var/py/python/urllibte
    st.py", line 4, in <module> response = urllib.request.urlopen('h
    ttp://httpbin.org/get', timeout=1)
    ...
    urllib.error.URLError: <urlopen error timed out>

     


    在这里我们设置了超时时间是1秒,程序1秒过后服务器依然没有响应,于是抛出了 urllib.error.URLError 异常,错误原因是 timed out 。

     

     

    因此我们可以通过设置这个超时时间来控制一个网页如果长时间未响应就跳过它的抓取,利用 try,except 语句就可以实现这样的操作。

     

     

    import urllib.request
    import  socket
    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!")

     


    在这里我们请求了 http://httpbin.org/get 这个测试链接,设置了超时时间是0.1秒,然后捕获了 urllib.error.URLError 这个异常,然后判断异常原因是超时异常,就得出它确实是因为超时而报错,打印输出了 TIME OUT ,当然你也可以在这里做其他的处理。

     

     

    运行结果如下:

     

    Time out!

    常理来说,0.1秒内基本不可能得到服务器响应,因此输出了 TIME OUT 的提示。这样,我们可以通过设置 timeout 这个参数来实现超时处理,有时还是很有用的。

     

     

     

    其他参数

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

    cadefault 参数现在已经弃用了,默认为 False 。

    以上讲解了 url.request.urlopen() 方法的用法,通过这个最基本的函数可以完成简单的请求和网页抓取,如需详细了解,可以参见官方文档。
    https://docs.python.org/3/library/urllib.request.html

     

    urllib.request.Request的使用

    由上我们知道利用 urlopen() 方法可以实现最基本的请求发起,但这几个简单的参数并不足以构建一个完整的请求,如果请求中需要加入 headers 等信息,我们就可以利用更强大的 Request 类来构建一个请求。

    首先我们用一个实例来感受一下 Request 的用法:

     

    import urllib.request
    
    request =urllib.request.Request("https://www.baidu.com")
    response = urllib.request.urlopen(request)
    print(response.read().decode("utf-8"))

     


    可以发现,我们依然是用 urlopen() 方法来发送这个请求,只不过这次 urlopen() 方法的参数不再是一个URL,而是一个 Request ,通过构造这个这个数据结构,一方面我们可以将请求独立成一个对象,另一方面可配置参数更加
    丰富和灵活。
    下面我们看一下 Request 都可以通过怎样的参数来构造,它的构造方法如下。

     

     

     

     

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


    第一个参数是请求链接,这个是必传参数,其他的都是可选参数。

     

    data 参数如果要传必须传 bytes (字节流)类型的,如果是一个字典,可以先用 urllib.parse.urlencode() 编码。

     

    headers 参数是一个字典,你可以在构造 Request 时通过 headers 参数传递,也可以通过调用 Request 对象的 add_header() 方法来添加请求头。请求头最常用的用法就是通过修改 User-Agent 来伪装浏览器,默认的 User-
    Agent 是 Python-urllib ,你可以通过修改它来伪装浏览器,比如要伪装火狐浏览器,你可以把它设置为 Mozilla/5.0 (X11; U; Linux i686)Gecko/20071127 Firefox/2.0.0.11

     

    origin_req_host 指的是请求方的 host 名称或者 IP 地址。

     

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

    method 是一个字符串,它用来指示请求使用的方法,比如 GET , POST , PUT 等等。
    下面我们传入多个参数构建一个 Request 来感受一下:

     

    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"))

     


    在这里我们通过四个参数构造了一个 Request , url 即请求链接,在 headers 中指定了 User-Agent 和 Host ,传递的参数 data 用了 urlencode() 和 bytes() 方法来转成字节流,另外指定了请求方式为 POST 。

     

     

    运行结果如下:
     

     

    {
      "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": "1.85.221.5", 
      "url": "http://httpbin.org/post"
    }

     


    通过观察结果可以发现,我们成功设置了 data , headers 以及 method 。

     

     

    另外 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.request高级特性

     

    大家有没有发现,在上面的过程中,我们虽然可以构造 Request ,但是一些更高级的操作,比如 Cookies 处理,代理该怎样来设置?
    接下来就需要更强大的工具 Handler 登场了。

     

    简而言之你可以把它理解为各种处理器,有专门处理登录验证的,有处理 Cookies 的,有处理代理设置的,利用它们我们几乎可以做到任何 HTTP 请求中所有的事情。

     

    首先介绍下 urllib.request.BaseHandler ,它是所有其他 Handler 的父类,它提供了最基本的 Handler 的方法,例
    如 default_open() 、 protocol_request() 等。
    接下来就有各种 Handler 类继承这个 BaseHandler ,列举如下:

    • HTTPDefaultErrorHandler 用于处理HTTP响应错误,错误都会抛出 HTTPError 类型的异常。
    • HTTPRedirectHandler 用于处理重定向。
    • HTTPCookieProcessor 用于处理 Cookie 。
    • ProxyHandler 用于设置代理,默认代理为空。
    • HTTPPasswordMgr 用于管理密码,它维护了用户名密码的表。
    • HTTPBasicAuthHandler 用于管理认证,如果一个链接打开时需要认证,那么可以用它来解决认证问题。 另外还有其他的 Handler ,可以参考官方文档。

    https://docs.python.org/3/library/urllib.request.html#urllib.request.BaseHandler

     

    它们怎么来使用,不用着急,下面会有实例为你演示。
    另外一个比较重要的就是 OpenerDirector ,我们可以称之为 Opener ,我们之前用过 urllib.request.urlopen() 这个方法,实际上它就是一个 Opener 。
    那么为什么要引入 Opener 呢?因为我们需要实现更高级的功能,之前我们使用的 Request 、 urlopen() 相当于类库为你封装好了极其常用的请求方法,利用它们两个我们就可以完成基本的请求,但是现在不一样了,我们需要实现更高级的功能,所以我们需要深入一层,使用更上层的实例来完成我们的操作。所以,在这里我们就用到了比调用 urlopen() 的对象的更普遍的对象,也就是 Opener 。

    Opener 可以使用 open() 方法,返回的类型和 urlopen() 如出一辙。那么它和 Handler 有什么关系?简而言之,就是利用 Handler 来构建 Opener 。
    认证
    我们先用一个实例来感受一下:

     

     

    import urllib.request
    auth_handler = urllib.request.HTTPBasicAuthHandler()
    auth_handler.add_password(realm='PDQ Application',
                              uri='https://mahler:8092/site-updates.py',
                              user='klem',
                              passwd='kadidd!ehopper')
    opener = urllib.request.build_opener(auth_handler)
    urllib.request.install_opener(opener)
    urllib.request.urlopen('http://www.example.com/login.html')

     


    此处代码为实例代码,用于说明 Handler 和 Opener 的使用方法。在这里,首先实例化了一个 HTTPBasicAuthHandler 对象,然后利用 add_password() 添加进去用户名和密码,相当于建立了一个处理认证的处理器。
    接下来利用 urllib.request.build_opener() 方法来利用这个处理器构建一个 Opener ,那么这个 Opener 在发送请求的时候就具备了认证功能了。接下来利用 Opener 的 open() 方法打开链接,就可以完成认证了。
    代理

     

    如果添加代理,可以这样做:

     

    import urllib.request
    proxy_handler = urllib.request.ProxyHandler({
    'http': 'http://218.202.111.10:80',
    'https': 'https://180.250.163.34:8888'
    })
    opener = urllib.request.build_opener(proxy_handler)
    response = opener.open('https://www.baidu.com')
    print(response.read())

     


    此处代码为实例代码,用于说明代理的设置方法,代理可能已经失效。

     

     

     

     

    在这里使用了 ProxyHandler , ProxyHandler 的参数是一个字典,key是协议类型,比如 http 还是 https 等,value是代理链接,可以添加多个代理。
    然后利用 build_opener() 方法利用这个 Handler 构造一个 Opener ,然后发送请求即可。

     

    Cookie设置

    我们先用一个实例来感受一下怎样将网站的 Cookie 获取下来。

    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)

    首先我们必须声明一个 CookieJar 对象,接下来我们就需要利用 HTTPCookieProcessor 来构建一个 handler ,最后利用 build_opener 方法构建出 opener ,执行 open() 即可。

    运行结果如下:

    BAIDUID=2E65A683F8A8BA3DF521469DF8EFF1E1:FG=1
    BIDUPSID=2E65A683F8A8BA3DF521469DF8EFF1E1
    H_PS_PSSID=20987_1421_18282_17949_21122_17001_21227_21189_21161_20927
    PSTM=1474900615
    BDSVRTM=0
    BD_HOME=0

     

    可以看到输出了每一条 Cookie 的名称还有值。
    不过既然能输出,那可不可以输出成文件格式呢?我们知道很多 Cookie 实际也是以文本形式保存的。
    答案当然是肯定的,我们用下面的实例来感受一下:

     

    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)

     

    这时的 CookieJar 就需要换成 MozillaCookieJar ,生成文件时需要用到它,它是 CookieJar 的子类,可以用来处理 Cookie 和文件相关的事件,读取和保存 Cookie ,它可以将 Cookie 保存成 Mozilla 型的格式。
    运行之后可以发现生成了一个 cookie.txt 文件。

     

    内容如下:

    # Netscape HTTP Cookie File
    # http://curl.haxx.se/rfc/cookie_spec.html
    # This is a generated file! Do not edit.
    .baidu.com TRUE / FALSE 3622386254 BAIDUID 05A
    E39B5F56C1DEC474325CDA522D44F:FG=1
    .baidu.com TRUE / FALSE 3622386254 BIDUPSID 05
    AE39B5F56C1DEC474325CDA522D44F
    .baidu.com TRUE / FALSE H_PS_PSSID 19638_1453
    _17710_18240_21091_18560_17001_21191_21161
    .baidu.com TRUE / FALSE 3622386254 PSTM 147490
    2606
    www.baidu.com FALSE / FALSE BDSVRTM 0
    www.baidu.com FALSE / FALSE BD_HOME 0


    另外还有一个 LWPCookieJar ,同样可以读取和保存 Cookie ,但是保存的格式和 MozillaCookieJar 的不一样,它会保存成与libwww-perl的Set-Cookie3文件格式的 Cookie 。
    那么在声明时就改为

     

    cookie = http.cookiejar.LWPCookieJar(filename)

     

     

    #LWP-Cookies-2.0
    Set-Cookie3: BAIDUID="0CE9C56F598E69DB375B7C294AE5C591:FG=1"; path="/"; domain=".baidu.com"; path_spec; domain_dot; expires="208
    4-10-14 18:25:19Z"; version=0
    Set-Cookie3: BIDUPSID=0CE9C56F598E69DB375B7C294AE5C591; path="/"; domain=".baidu.com"; path_spec; domain_dot; expires="2084-10-1
    4 18:25:19Z"; version=0
    Set-Cookie3: H_PS_PSSID=20048_1448_18240_17944_21089_21192_21161_20929; path="/"; domain=".baidu.com"; path_spec; domain_dot; di
    scard; version=0
    Set-Cookie3: PSTM=1474902671; path="/"; domain=".baidu.com"; path_spec; domain_dot; expires="2084-10-14 18:25:19Z"; version=0
    Set-Cookie3: BDSVRTM=0; path="/"; domain="www.baidu.com"; path_spec; discard; version=0
    Set-Cookie3: BD_HOME=0; path="/"; domain="www.baidu.com"; path_spec; discard; version=0
    
    
    

     


    生成的内容如下:由此看来生成的格式还是有比较大的差异的。
    那么生成了 Cookie 文件,怎样从文件读取并利用呢?
    下面我们以 LWPCookieJar 格式为例来感受一下:

     

     

     

     

    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'))

     

     

    前提是我们首先利用上面的方式生成了 LWPCookieJar 格式的 Cookie ,然后利用 load() 方法,传入文件名称,后面同样的方法构建 handler 和 opener 即可。
    运行结果正常输出百度网页的源代码。

     

     

     

    好,通过如上用法,我们可以实现绝大多数请求功能的设置了。
    发出请求之后,如果遇到异常怎么办?在下一节,我们会讲解一下有关异常处理的
    流程。

     

     

    展开全文
  • Python标准库—urlliburllib3

    万次阅读 2019-06-04 21:04:54
    urllib是Python中请求url连接的官方标准库,在Python2中主要为urlliburllib2,在Python3中整合成了urlliburllib中一共有四个模块,分别如下: request:主要负责构造和发起网络请求,定义了适用于在各种复杂情况...

    一、urllib

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

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

    1. urllib.request模块

    模块中最常用的函数为urllib.request.urlopen(),参数如下:

    urllib.request.urlopen(url, data=None, [timeout, ]*, cafile=None, capath=None, cadefault=False, context=None)
    •  url:  请求的网址
    •  data:要发送到服务器的数据
    •  timeout:设置网站的访问超时时间

    urlopen返回对象提供方法:

    • read() , readline() ,readlines() , fileno() , close() :对HTTPResponse类型数据进行操作
    • info():返回HTTPMessage对象,表示远程服务器返回的头信息
    • getcode():返回Http状态码。如果是http请求,200请求成功完成 ; 404网址未找到
    • geturl():返回请求的url

    (1)发送简单的GET请求:

    from urllib import request
    
    response = request.urlopen('https://www.baidu.com')
    print(response.read().decode())

    在urlopen()方法中,直接写入要访问的url地址字符串,该方法就会主动的访问目标网址,然后返回访问结果,返回的访问结果是一个    http.client.HTTPResponse对象,使用该对象的read()方法即可获取访问网页获取的数据,这个数据是二进制格式的,所以我们还需要使用decode()方法来将获取的二进制数据进行解码,转换成我们可以看的懂得字符串。

    (2)发送简单的POST请求:

    from urllib import reuqest
    
    response = request.urlopen('http://httpbin.org/post', data=b'word=hello')
    
    print(response.read().decode())   #decode()解码

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

    (3)复杂的请求——请求头

    当我们需要模拟一些其他的参数的时候,简单的urlopen() 方法已经无法满足我们的需求了,这个时候我们就需要使用urllib.request中的Request对象来帮助我们实现一些其它参数的模拟,比如请求头。

    Request对象如下所示:

    # Request对象实例化
    req  = urllib.request.Request(url, data=None, headers={},origin_req_host=None,unverifiable=False, method=None)

    举例如下: 

      from urllib import request
      
      url = 'http://httpbin.org/get'
      headers = {'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_5) \
    AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36'}
      
      # 需要使用url和headers生成一个Request对象,然后将其传入urlopen方法中
      req = request.Request(url, headers=headers)
      resp = request.urlopen(req)
      print(resp.read().decode())

     

    (4)复杂的请求—代理IP

    使用爬虫来爬取数据的时候,如果过于频繁的访问,而且网站还设有限制的话,很有可能会禁封我们的ip地址,这个时候就需要设置代理,来隐藏我们的真实IP。

    代理IP的原理:以本机先访问代理IP,再通过代理IP地址访问服务器,这样服务器接受到的访问IP就是代理IP地址。

    urllib提供了urllib.request.ProxyHandler()方法可动态的设置代理IP池。将代理IP以字典形式传入该方法,然后通过urllib.reques.build_opener()创建opener对象,用该对象的open()方法向服务器发送请求。

     from urllib import request
      
      url = 'http://httpbin.org/ip'
      proxy = {'http': '218.18.232.26:80', 'https': '218.18.232.26:80'}
      proxies = request.ProxyHandler(proxy)  # 创建代理处理器
      opener = request.build_opener(proxies)  # 创建opener对象
      
      resp = opener.open(url)
      print(resp.read().decode())
    

    在上述的方法中我们还用到了一个新的东西,即request.build_opener()方法,其实urlopen()就是通过构造好了的opener对象发送请求,在这里我们使用request.build_opener()方法重构了一个opener()对象,我们可以通过这个对象实现urlopen()实现的任何东西。

    (5)复杂的请求—cookies

    有时候当我们访问一些网站的时候需要进行翻页或者跳转等其它操作,为了防止无法访问我们想要的数据,需要让网站识别我们是同一个用户。这个时候我们就需要带上cookie进行访问。

    在设置cookie的时候由于urllib并没有很好的处理cookie的对象,所以在这里我们需要用到一个别的库,即http库,并使用里面的cookiejar来进行cookie的管理:

    from http import cookiejar
    from urllib import request
      
    url = 'https://www.baidu.com'
    # 创建一个cookiejar对象
    cookie = cookiejar.CookieJar()
    # 使用HTTPCookieProcessor创建cookie处理器
    cookies = request.HTTPCookieProcessor(cookie)
    # 并以它为参数创建Opener对象
    opener = request.build_opener(cookies)
    # 使用这个opener来发起请求
    resp = opener.open(url)
      
    # 查看之前的cookie对象,则可以看到访问百度获得的cookie
    for i in cookie:
        print(i)
    

      当然,如果把上面这个生成的opener对象使用install_opener方法来设置为全局的,opener对象之后的每次访问都会带上这个cookie。设置全局后既可以用urlopen()方法, 也可以用opener.open() ,不安装的话只能用opener.open()方法

    # 将这个opener设置为全局的opener,之后所有的,不管是opener.open()还是urlopen() 发送请求,都将使用自定义
    request.install_opener(opener)
    resp = request.urlopen(url)

    (6)复杂的请求—证书验证

    CA(Certificate Authority)是数字证书认证中心的简称,是指发放、管理、废除数字证书的受信任的第三方机构。

    CA的作用是检查证书持有者身份的合法性,并签发证书,以防证书被伪造或篡改,以及对证书和密钥进行管理。现实生活中可以用身份证来证明身份, 那么在网络世界里,数字证书就是身份证。和现实生活不同的是,并不是每个上网的用户都有数字证书的,往往只有当一个人需要证明自己的身份的时候才需要用到数字证书。普通用户一般是不需要,因为网站并不关心是谁访问了网站,现在的网站只关心流量。但是反过来,网站就需要证明自己的身份了。比如说现在钓鱼网站很多的,比如你想访问的是www.baidu.com,但其实你访问的是www.daibu.com”,所以在提交自己的隐私信息之前需要验证一下网站的身份,要求网站出示数字证书。一般正常的网站都会主动出示自己的数字证书,来确保客户端和网站服务器之间的通信数据是加密安全的。

    最简单的方法就是通过添加忽略ssl证书验证关闭证书验证,由于urllib并没有很好的处理ssl的对象,所以在这里我们需要用到一个别的库,即ssl库,如下:

    import ssl
    from urllib import request
    
    context = ssl._create_unverified_context()
    res = urllib.request.urlopen(request, context=context)

    2. urllib.error 模块

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

    HTTPError还包含了三个属性:

    • code:请求的状态码
    • reason:错误的原因
    • headers:响应的报头
    from urllib.error import HTTPError
    
    try:
        request.urlopen('https://www.jianshu.com')
    except HTTPError as e:
        print(e.code)
    
    

    3.urllib.parse 模块

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

    urllib.parse.quote(url):(URL编码处理)主要对URL中的非ASCII码编码处理

    urllib.parse.unquote(url):(URL解码处理)URL上的特殊字符还原

    urllib.parse.urlencode:对请求数据data进行格式转换

     

    二、urllib3

    来自官方网站的解释:

    urllib3是一个功能强大,对SAP 健全的 HTTP客户端。许多Python生态系统已经使用了urllib3,你也应该这样做。                    

    通过urllib3访问一个网页,那么必须首先构造一个PoolManager对象,然后通过PoolMagent中的request方法或者 urlopen()方法来访问一个网页,两者几乎没有任何区别。

    class urllib3.poolmanager.PoolManager(num_pools = 10,headers = None,** connection_pool_kw )

    生成一个PoolManager所需要的参数:

    • num_pools 代表了缓存的池的个数,如果访问的个数大于num_pools,将按顺序丢弃最初始的缓存,将缓存的个数维持在池的大小。
    • headers 代表了请求头的信息,如果在初始化PoolManager的时候制定了headers,那么之后每次使用PoolManager来进行访问的时候,都将使用该headers来进行访问。
    • ** connection_pool_kw 是基于connection_pool 来生成的其它设置

    当访问网页完成之后,将会返回一个HTTPResponse对象,可以通过如下的方法来读取获取GET请求的响应内容:

    import urllib3
    
    http = urllib3.PoolManager(num_pools=5, headers={'User-Agent': 'ABCDE'})
    
    resp1 = http.request('GET', 'http://www.baidu.com', body=data)
    # resp2 = http.urlopen('GET', 'http://www.baidu.com', body=data)
    
    print(resp2.data.decode())
    

    除了普通的 GET 请求之外,你还可以使用request()或者urlopen()进行 POST 请求:

    import urllib3
    import json
    
    data = json.dumps({'abc': '123'})
    http = urllib3.PoolManager(num_pools=5, headers={'User-Agent': 'ABCDE'})
    
    resp1 = http.request('POST', 'http://www.httpbin.org/post', body=data,timeout=5,retries=5)
    #resp2 = http.urlopen('POST', 'http://www.httpbin.org/post', body=data,timeout=5,retries=5)
    
    print(resp1.data.decode())
    

    注意事项

    • urllib3 并没有办法单独设置cookie,所以如果你想使用cookie的话,可以将cookie放入到headers中

     

    request()和urlopen()方法:

    request(self, method, url, fields=None, headers=None, **urlopen_kw)
    
    urlopen(self, method, url, redirect=True, **kw):

    差距还是很明显的,urlopen()比request()有三个参数是不一样的,你会发现request()具有fields,headers两个参数。而且相比之下 reuqest() 方法还是比较符合人们的使用方式的,所以更多的也就使用 request() 方法了。

    推荐使用request()来进行访问的,因为使用request()来进行访问有两点好处,

    • 可以直接进行post请求,不需要将 data参数转换成JSON格式
    • 直接进行GET请求,不需要自己拼接url参数
    import urllib3
    import json
    
    data = {'abc': '123'}
    http = urllib3.PoolManager(num_pools=5, headers={'User-Agent': 'ABCDE'})
    
    resp1 = http.request('POST', 'http://www.httpbin.org/post', fields=data)
    # resp1 = http.request('GET', 'http://www.httpbin.org/post', fields=data)  
    
    print(resp1.data.decode())
    

     

    虽然urlopen()没有fields,但这并不代表它不能进行POST访问,相反,两个方法都有一个body属性,这个属性就是我们平时POST请求时所熟知的data参数,只不过你需要将data字典先转换成JSON格式再进行传输。

    不过特别要声明的一点是 fielder 和 body 中只能存在一个。

    2.2 urllib3 ProxyManager

    如果你需要使用代理来访问某个网站的话, 那么你可以使用 ProxyManager 对象来进行设置

    def __init__(self, proxy_url, num_pools=10, headers=None,proxy_headers=None, **connection_pool_kw):
    

    ProxyManager和PoolManager的方法基本完全相同,这里举个简单的小例子,就不再赘述了:

    import urllib3
    import json
    
    data = {'abc': '123'}
    proxy = urllib3.ProxyManager('http://50.233.137.33:80', headers={'connection': 'keep-alive'})
    resp1 = proxy.request('POST', 'http://www.httpbin.org/post', fields=data)
    print(resp1.data.decode())

     

    展开全文
  • 在安装第三方库的时候,Python报错pip._vendor.urllib3.exceptions.ReadTimeoutError: HTTPSConnectionPool(host='files.pythonhosted.org', port=443): Read timed out. 解决方法如下: pip --default-timeout...
  • 相关链接: 《Python urlliburllib2、urllib3用法及区别》 《urllib2库.官方文档翻译》 《urllib3官方文档》 《urllib3的基本用法》 《详解 python3 urllib
  • python3中也有urlliburllib3两个库,其中urllib几乎是python2.7中urlliburllib2两个模块的集合,所以我们最常用的urllib模块,而urllib3则作为一个拓展模块使用。 python2.7中的urllib2 = python3中的urllib....
  • urlliburllib2

    2019-03-30 16:40:22
    文章目录一urllib库与urllib2库二 urllib三 区别 一urllib库与urllib2库 urllib库与urllib2库是python中内置的HTTP请求库,urllib模块提供的上层接口,是访问的www和ftp上的数据就像是访问本地文件一样 二 urllib 有...
  • urllib还是urllib2?

    2018-04-16 15:53:22
    urllib还是urllib2?结论: urllib2 与 urllib 有些不同。 原因: 在 Python 3.x 里,urllib2 改名为 urllib,被分成一些子模块: 1:urllib.request 2:urllib.parse 3:urllib.error。 说明: 1:函数...
  • Py之urllib2:Python库之urlliburllib2、urllib3系列简介、安装、使用方法之详细攻略 目录 urllib2简介 urllib2安装 urllib2使用方法 urllib2简介 urlliburllib2之间PK 1、在python中,urllib和...
  • python3对urlliburllib2进行了重构,拆分成了urllib.request,urllib.response, urllib.parse, urllib.error等几个子模块,这样的架构从逻辑和结构上说更加合理。urllib库无需安装,python3自带。python 3.x中将...
  • urlliburllib2

    2017-12-06 20:20:55
    urlliburllib2是python中两个单独存在的模块,虽然两者都是接受URL请求的相关模块,但是提供了不同的功能,两者并不是可以相互代替的。 urllib2可以接受一个Request类的实例来设置URL请求的headers,urllib仅可以...
  • 目录 Python2.x中 urlliburllib2 常用方法和类 Python3.x中 urllib ...urlliburllib2 ...urlliburllib2 是 python2.x 自带的模块...urlliburllib2 都是接受URL请求的相关模块,但是urllib2可以接受一个Re...
  • urlliburllib的区别

    2019-10-02 12:03:18
    urlliburllib2都是接受URL请求的相关模块,但是提供了不同的功能.两个最显著的不同如下  urllib2 can accept a Request object to set the headers for a URL request,urllib accepts only a URL. That means, ...
  • urllib2在python3后已经合并在urllib中了,具体为urllib.response,urllib.request urllib2.URLError 改为了urllib.error.URLError 文章目录URLError与HTTPError下载网页(requests库也可以) URLError与HTTPError ...
  • python3中把urlliburllib合并为一个库了,urllib对应urllib.request 1.) python 中最早内置拥有的网络请求模块就是 urllib,我们可以看一下 urllib 中的所有方法: 2.) urllib2模块中的所有方法更侧重于...
  • urllib3 库

    2019-07-29 10:49:45
    Urllib3是一个功能强大,条理清晰,用于HTTP客户端的Python库。许多Python的原生系统已经开始使用urllib3。Urllib3提供了很多python标准库urllib里所没有的重要特性
  • requests库优于urllib,其基于urlliburllib个人基本掌握。 1 #urllib.request 2 r=urllib.request.urlopen('http://www.cnblogs.com/realmonkeykingsun/') 3 print(r.read().decode('utf-8)) 4 5 #...
  • urllib & urllib2

    2016-01-03 16:19:53
    之前看python, 知道有urlliburllib2两个模块,但是一直没有去深入学习, 也并不清楚为什么有了urllib2还要保留urllib,最近接触一点爬虫的知识,用到了urlliburllib2, 在此做一点记录,记录这两个模块的区别以便日后...
  • urlliburllib2区别

    千次阅读 2018-06-13 17:42:53
    urlliburllib2区别 urlliburllib2区别: Python的urlliburllib2模块都做与请求URL相关的操作,但他们提供不同的功能。他们两个最显着的差异如下: 总结1:urllib2可以接受一个Request对象,并以此可以来...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 52,682
精华内容 21,072
关键字:

urllib