urllib库
    urllib库是Python中一个最基本的网络请求库。可以模拟浏览器的行为,向指定的服务器发送一个请求,并可以保存服务器返回的数据。
    在Python3的urllib库中,所有和网络请求相关的方法,都被集到urllib.request模块下了
    urlopen函数:
    urllib.request.urlopen(url, data=None, [timeout, ], cafile=None, capath=None, cadefault=False, context=None)
    返回值:返回值是一个http.client.HTTPResponse对象,这个对象是一个类文件句柄对象。有read(size)、readline、readlines以及getcode等方法。
    url:目标资源在网路中的位置。可以是一个表示URL的字符串;也可以是一个urllib.request对象
    data:data用来指明发往服务器请求中的额外的信息(如:在线翻译,在线答题等提交的内容)。HTTP是python中实现的众多网络通信http、https、ftp等协议中,唯一一个 使用data 参数的,也就是说只有打开的是http网址的时候,自定义data参数才会有作用。另外,官方API手册介绍指出:
    1. data必须是一个字节数据对象(Python的bytes object)
    2. data必须符合标准the standard application/x-www-form-urlencoded format,怎么得到这种标准结构的data呢?使用urllib.parse.urlencode()将自定义的data转换成标准格式,而这个函数所能接收的参数类型是pyhon中的mapping object(键/值对,如dict) or a sequence of two-element tuples(元素是tuple的列表)。
    3. data也可以是一个可迭代的对象,这种情况下就需要配置response对象中的Conten-length,指明data的大小。
    4. data默认是None,此时以GET方式发送请求;当用户给出data参数的时候,改为POST方式发送请求。
    cafile、capath、cadefault 参数:用于实现可信任的CA证书的HTTP请求。(基本上很少用)
    context参数:实现SSL加密传输。(基本上很少用)

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

    urlretrieve函数:
    这个函数可以方便的将网页上的一个文件保存到本地。以下代码可以非常方便的将百度的首页下载到本地:
    urlretrieve(url, filename=None, reporthook=None, data=None)
    url:外部或者本地url
    filename:指定了保存到本地的路径(如果未指定该参数,urllib会生成一个临时文件来保存数据);
    reporthook:是一个回调函数,当连接上服务器、以及相应的数据块传输完毕的时候会触发该回调。我们可以利用这个回调函数来显示当前的下载进度。
    data:指post到服务器的数据。该方法返回一个包含两个元素的元组(filename, headers),filename表示保存到本地的路径,header表示服务器的响应头。

    urlopen返回 一个类文件对象,它提供了如下方法:
    read() , readline() , readlines() , fileno() , close() :这些方法的使用方式与文件对象完全一样;
    info():返回一个httplib.HTTPMessage 对象,表示远程服务器返回的头信息
    getcode():返回Http状态码。如果是http请求,200表示请求成功完成;404表示网址未找到;
    geturl():返回请求的url;

    from urllib import request
    request.urlretrieve(‘http://www.baidu.com/','baidu.html‘)

    urlencode函数:
    用浏览器发送请求的时候,如果url中包含了中文或者其他特殊字符,那么浏览器会自动的给我们进行编码。而如果使用代码发送请求,那么就必须手动的进行编码,这时候就应该使用urlencode函数来实现。urlencode可以把字典数据转换为URL编码的数据。示例代码如下:

    from urllib import parse
    data = {‘name’:’爬虫基础’,’greet’:’hello world’,’age’:100}
    qs = parse.urlencode(data)
    print(qs)

    parse_qs函数:
    urllib.parse.parse_qs 返回字典
    urllib.parse.parse_qsl 返回列表

    可以将经过编码后的url参数进行解码。示例代码如下:

    from urllib import parse
    qs = “name=%E7%88%AC%E8%99%AB%E5%9F%BA%E7%A1%80&greet=hello+world&age=100”
    print(parse.parse_qs(qs))

    urlparse和urlsplit:
    有时候拿到一个url,想要对这个url中的各个组成部分进行分割,那么这时候就可以使用urlparse或者是urlsplit来进行分割。示例代码如下:

    from urllib import request,parse
    url = ‘http://www.baidu.com/s?username=zhiliao
    result = parse.urlsplit(url)
    # result = parse.urlparse(url)
    print(‘scheme:’,result.scheme)
    print(‘netloc:’,result.netloc)
    print(‘path:’,result.path)
    print(‘query:’,result.query)
    urlparse和urlsplit基本上是一模一样的。唯一不一样的地方是,urlparse里面多了一个params属性,而urlsplit没有这个params属性。比如有一个url为:url = ‘http://www.baidu.com/s;hello?wd=python&username=abc#1',
    那么urlparse可以获取到hello,而urlsplit不可以获取到。url中的params也用得比较少。

    *request.Request类:

    如果想要在请求的时候增加一些请求头,那么就必须使用request.Request类来实现。比如要增加一个User-Agent,示例代码如下:

    from urllib import request
    headers = {
    ‘User-Agent’: ‘Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36’
    }
    req = request.Request(“http://www.baidu.com/",headers=headers)
    resp = request.urlopen(req)
    print(resp.read())

    user-agent:
    将爬虫伪装成浏览器向服务器发送请求
    cookie:
    账户信息,用于登录

    都保存在请求头headers里面

    ProxyHandler处理器(代理设置)
    很多网站会检测某一段时间某个IP的访问次数(通过流量统计,系统日志等),如果访问次数多的不像正常人,它会禁止这个IP的访问。
    所以我们可以设置一些代理服务器,每隔一段时间换一个代理,就算IP被禁止,依然可以换个IP继续爬取。
    urllib中通过ProxyHandler来设置使用代理服务器,下面代码说明如何使用自定义opener来使用代理:

    from urllib import request
    # 这个是没有使用代理的
    # resp = request.urlopen(‘http://httpbin.org/get‘)
    # print(resp.read().decode(“utf-8”))

    # 这个是使用了代理的
    handler = request.ProxyHandler({“http”:”218.66.161.88:31769”})
    opener = request.build_opener(handler)
    req = request.Request(“http://httpbin.org/ip“)
    resp = opener.open(req)
    print(resp.read())