初识urllib

发布时间:2018-08-27 19:55:09编辑:Run阅读(8646)

    使用urllib

    request:  是最基本的 HTTP 请求模块,可以用来模拟发送请求,只需要给库方法传入URL以及额外的参数,就可以模拟实现这个过程了。

    error:  异常处理模块,如果出现请求错误, 可以捕获这些异常,然后进行重试或其它操作以保证程序不会意外终止。

    parse:  工具模块,提供了许多 URL 处理方法,比如拆分、解析,合并等。

    robotparser:  主要是用来识别网站的robots.txt 文件,然后判断哪些网站可以爬,哪些网站不可以爬,用得较少。


    发送请求

    使用urllib的request模块,可以实现请求的发送并得到响应

    具体用法:

    urlopen()

    urllib.request 模块提供了最基本的构造 HTTP请求的方法, 利用它可以模拟浏览器的一个请求发起过程, 同时它还带有处理授权验证( authenticaton )、重定向( redirection 、浏览器 Cookies 及其他内容

    以百度为例,把网页抓下来

    #!/usr/bin/env python
    # coding: utf-8
    import urllib.request
    
    response = urllib.request.urlopen("http://www.baidu.com")
    print(response.read().decode('utf8'))

    运行结果如下:

    blob.png

    这里只用了两行代码,便完成了百度首页的抓取,显示了网页的源代码,得到了源代码之后呢?想要的链接,图片地址,文本信息就可以从中提取出来。


    利用type()函数查看response的数据类型

    import urllib.request
    
    response = urllib.request.urlopen("http://www.baidu.com")
    print(type(response))

    输出结果如下:

    <class 'http.client.HTTPResponse'>

    它是一个HTTPResponse类型的对象,主要包含read(),readinto(),getheader(name),getheaders(name),fileno()等方法以及msg,version,status,reason,debuglevel,closed等属性


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

    实例如下:

    #!/usr/bin/env python
    # coding: utf-8
    import urllib.request
    
    response = urllib.request.urlopen("http://www.baidu.com")
    print(response.status)
    print(response.getheaders())
    print(response.getheader('Server'))

    运行结果如下:

    blob.png


    利用最基本的urlopen()方法,可以完成最基本的简单网页GET请求抓取。还可以传递一些参数,源码如下:

    blob.png

    除了第一个参数可以传递URL之外,还可以传递其它内容,data(附加数据),timeout(超时时间)等....


    参数详情介绍

    data参数

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

    实例:

    #!/usr/bin/env python
    # coding: utf-8
    import urllib.request
    import urllib.parse
    
    data = bytes(urllib.parse.urlencode({'test': 'hello world'}), encoding='utf8')
    response = urllib.request.urlopen("http://httpbin.org/post", data=data)
    print(response.read().decode('utf8'))

    运行结果如下

    blob.png

    注释:上面传递了一个字典,键为test,值为hello wrod,传递过程中需要被转码为bytes(字节流)类型,类型转换用到了bytes()方法,该方法的第一个参数需是str(字符串)类型,而上面传的是一个字典类型,这个时候需要用urllib.parse模块里的urlencode()方法将字典转化成字符串;第二个参数指定编码格式为utf8。

    http://httpbin.org/post,这个链接可以用来测试POST请求,传递的参数出现在form字段中,表示模拟了表单提交的方式,以POST方式传递数据。


    timeout参数

    timeout参数用于设置超时时间,单位为秒,意思就是超过设定的时间,还没有得到响应,就会抛出异常,不指定,使用全局默认时间,支持http,https,ftp请求。

    实例:

    #!/usr/bin/env python
    # coding: utf-8
    import urllib.request
    
    response = urllib.request.urlopen("http://httpbin.org/get", timeout=1)
    print(response.read().decode('utf8'))

    运行结果如下:

    blob.png

    注释:这里设置超时时间为1秒,1秒后没有响应,就会抛出异常,异常属于urllib.error模块

    因此,可以通过设置这个超时时间来控制一个网页如果长时间未响应,就跳过它抓取,可以利用try except语句来实现,代码如下:

    #!/usr/bin/env python
    # coding: utf-8
    import urllib.request
    import urllib.error
    import socket
    
    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")

    运行结果如下:

    Time out

    注释:这里请求了http://httpbin.org/post测试连接,设置了超时时间为0.1秒,然后捕获了URLError异常,接着判断异常是socket.timeout类型(超时异常),得出确实是超时报错,最后打印Time out, 按照常理0.1秒内不可能得到服务器响应,所有超时,通过设置timeout这个参数来实现超时处理,还是很有用的


    其它参数

    除了 data 参数和 timeout 参数外,还有 context 参数,它必须是 ssl.SSLContext 类型,用来指定SSL设置, 此外,cafile和capath 这两个参数分别指定 CA 证书和它的路径,这个在请求 HTTPS 链接时会有用,若需要更加详细的文档信息,可以找到python的安装目录,找到Doc目录,下面会有一个pythons354.chrm文档,如下:

    blob.png


    Request

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

    Request用法实例:

    #!/usr/bin/env python
    # coding: utf-8
    import urllib.request
    
    request = urllib.request.Request('http://www.baidu.com')
    response = urllib.request.urlopen(request)
    print(response.read().decode('utf8'))

    注释:依旧是用urlopen()方法来发送这个请求,不过这次该方法的参数不再是URL,而是一个Request类型的对象。通过构造这个数据结构,一方面我们可以将请求独立成一个对象,另一方面可更加丰富和灵活地配置参数。


    Request构造源码如下:

    blob.png

    第一个参数url用于请求URL,这是比传参数,其它都是可选

    第二个参数data,如果需要传,必须传bytes(字节流)类型的。如果是字典,先用urllib.parse模块里的urlencode()编码

    第三个参数 headers 是一个字典,它就是请求头, 在构造请求时通过 headers 参数直接构造,也可以通过调用请求实例的 add_header()方法添加。添加请求头最常用的用法就是通过修改 User-Agent 来伪装浏览器,默认的 User-Agent是Python-urllib,可以通过修改它来伪装成浏览器。

    第四个参数 origin_req_host 指的是请求方的 host 名称或者 IP 地址。

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

    第六个参数method是一个字符串 ,用来指示请求使用的方法,比如 GET, POST, PUT等


    实例,传入多个参数构建请求:

    #!/usr/bin/env python
    # coding: utf-8
    from urllib import request,parse
    
    url = 'http://httpbin.org/post'
    headers = {
        'User-Agent': 'Mozilla/4.0 (compatible; MSIE S. S; Windows NT)',
        'Host': 'httpbin.org',
    }
    dict = {
        'name': 'zhangsan'
    }
    
    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('utf8'))

    运行结果如下;

    blob.png

    注释:通过4个参数构造了一个请求,其中url即请求URL,headers中指定了User-Agent和Host,参数data用urloncode()和bytes()方法转成字节流,还指定了请求的方式为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 )')

    这样更加方便地构造请求,实现请求的转发


关键字