• urllib的使用


    urllib的使用

    urllib是python内置的HTTP请求库,包含如下四个模块:

    request:它是最基本HTTP请求模块,可以用来模拟发送请求,就像在浏览器里输入网址然后按回车一样,只需要传入URL以及额外的参数,就可以模拟实现这个过程了。

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

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

    robotparse:主要用来识别网站的robots.txt文件,然后判断哪些往回走哪可以爬,哪些网站不可以爬。

     

    1.request模块

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

    # 导入模块
    from urllib import request
    # 调用urlopen()方法发送请求
    response = request.urlopen('https://www.python.org')
    print(response.read().decode('utf-8'))

    通过简单的两行代码就可以将python官网的源代码抓取下来了,上面得到的response是一个HTTPResponse 类型的对象,通过该对象调用read()、readinto()、getheader(name)、getheaders()、fileno()等方法,以及msg、version、status、reason、debuglevel、closed等属性。下面来详细分析urlopen()函数的API:

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

    除了url参数以外,其余的参数都是可选的。

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

    import ulllib.parse
    import urllib.request
    
    data = bytes(urllib.parse.urlencode({'name':'jonas'}),encoding='utf-8')
    response = urllib.request.urlopen('http://httpbin.org/post',data=data)
    print(response.read())

    这里传递了一个参数name,值是jonas。它需要被转码成bytes类型,其中转转字节流采用了bytes()方法,该方法的第一个参数需要时str类型,需要用urllib.parse模块的urlencode()方法来将dict转化为str类型;第二个参数指定编码方式。

     

    timeout参数:用于设置超时时间,单位为秒。如果超出设置的时间还没有得到响应,就会抛出URLError异常。

    import urllib.request
    
    response = urllib.request.urlopen('http://httpbin.org/get',timeout=1)

    如果超过了1秒没有得到响应,程序就会抛出URLError异常,该异常属于urllib.error模块,错误原因是超时。

     

    上面通过urlopen()方法可以实现最基本的请求发起,但这几个简答的参数并不足以构建一个完整的请求,如果请求中需要加入Headers信息,就可以利用更强大的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对象。

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

    第一个参数 url 是必须必须的,用于请求的URL。

    第二个参数data如果要传,则必须传bytes()类型,跟上面的一样,如果是字典,可以通过urllib.parse.urlencode()来编码。

    第三个参数headers是一个字典,它就是请求头,可以在构造请求时通过headers参数直接构造,也可以通过调用请求实例的add_header()方法添加。请求头最常用的用法就是通过修改User-Agent来伪装浏览器,默认的User-Agent是Python-urllib,如果不修改该值,则很有可能会被识别为爬虫。

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

    第五个参数unverifiable表示这个请求是否是无法验证的,默认是False,意思就是说用户没有足够权限来选择接受这个请求的结果。

    第六个参数method是一个字符串,用来指示请求使用的方法。

    下面传入多个参数来构建你请求:

    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'           
    }
    my_dict = {'name':'jonas'}
    data = bytes(parse.urlencode(my_dict),encoding='utf-8')
    req = request.Request(url=url,data=data,headers=headers,method='POST')
    print(response.read().decode('utf-8'))

      在上面构建了请求,成功的伪装成浏览器去发请求拿数据,但是反爬虫的技术不仅仅是检查请求头的User-Agent,还有很多方式,比如,服务器会检测某个IP在单位时间内的请求次数,如果超过了某个值,那么服务器会拒绝服务,返回一些错误信息。所以在时候就需要用到代理技术了(详细在后面介绍)。

    在urllib.request模块里有一个BaseHandler类,它是所有其他Handler的父类,它提供了最基本的方法,除此以外还有很多基于这个类的子类:

    HTTPDefaultErrorHandler:用于处理HTTP响应错误,错误会怕抛出HTTPError异常。

    HTTPRedirectHandler:用于处理重定向

    HTTPCookieProcessor:用于处理Cookies

    ProxyHandler:用于设置代理,默认代理为空

    HTTPPasswordMgr:用于管理密码,它维护了用户名和密码的表

    HTTPBasicAuthHandler:用于管理认证,如果一个链接打开时需要认证,那么可以使用它来解决认证问题

      除了这些以外,还有一个比较重要的类就是OpernerDirector,称为Opener,上面使用的urlopen()方法的返回值其实就是一个Opener对象,有些网站在打开时就会弹出提示框,直接提示你输入用户名和密码,验证成功后才能查看页面,如果需要请求这样的页面,就可以通过HTTPBasicAuthHandler来完成了。

    from urllib.request import HTTPPasswordMgrWithDefaultRealm,HTTPBasicAuthHandler,build_opener
    from urllib.error import URLError
    
    username = 'jonas'
    password = 123456
    url = 'localhost:3000'
    
    p = HTTPPasswordMgrWithDefaultRealm()
    p.add_password(None,url,username,password)
    auth_handler = HTTPBasicAuthHandler(p)
    opener = build_opener(auth_handler)
    
    try:
        result = opener.open(url)
        html = result.read().decode('utf-8')
    except URLError as e:
        print(e.reason)  

    这里首先实例化 HTTPBasicAuthHandler 对象,其参数是 HTTPPasswordMgrWithDefaultRealm 对象,它利用add_password()添加进去用户名和密码,这样就建立了一个处理验证的Handler,接下来就可以利用这个Handler并使用build_opener()方法构建一个Opener,这个Opener在发送请求时就相当于验证成功了,然后利用Opener的open()方法打开链接,就完成验证了,这里获取到的结果就是验证后的页面源码内容。

     

    除了上面的验证以外,在爬虫的时候免不了使用的就是代理技术。

    from urllib.error import URLError
    from urllib.request import ProxyHandler,build_opener
    
    proxy_handler = ProxyHandler({
       'http':'http://127.0.0.1:5000',
       'https':'https://127.0.0.1:5000'  
    })
    opener = build_opener(proxy_handler)
    try:
        response = opener.open('https://www.baidu.com')
        print(response.read().decode('utf-8'))
    except URLError as e:
        print(e.reason)

    这里使用了ProxyHandler,其参数是一个字典,键名是协议类型,然后利用这个Handler及build_opener()方法构造一个Opener

     

    2.error模块

    2.1 URLError

    URLError类来自urllib库的error模块,它继承自OSError,是error异常模块的基类,由request模块产生的异常都可以通过捕获这个类类处理。它有一个reason属性,用于返回错误的原因。

    from urllib import request,error
    
    try:
        response = request.urlopen('https://www.baidu123.com')
    except error.URLError as e:
        print(e.reason)

    上面请求了一个不存在的URL,就可以捕获到这个异常。

     

    2.2 HTTPError

    它是URLError的子类,专门用于处理HTTP请求错误,它有如下3个属性:

    code:返回HTTP状态码

    reason:返回错误的原因

    headers:返回请求头

     

    3.parse模块

    parse模块定义了处理URL的标准接口,例如实现URL各部分的抽取、合并以及连接转换。

    3.1 urlparse()

    该方法可以实现URL的识别和分段

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

     该方法返回的结果是一个ParseResult对象,它包含6个部分,分别是scheme代表协议、netloc代表域名、path代表访问路径、params代表参数、query代表查询条件和fragment代表锚点

    一个标准的连接格式:scheme://netloc/path;params?query#fragment

    除了这种最基本的解析方式,该方法还卡伊传其他参数:

    urllib.parse.urlparse(urlstring,scheme='',allow_fragments=True)

    urlstring:待解析的URL,必须参数

    scheme:默认的协议

    allow_fragments:是否忽略fragment

     

    3.2 urlunparse()

    该方法可以接受一个可迭代对象,但是长度必须是6,如果不足或者过多都会报错。

    from urllib import parse
    
    data = ['http','www.baidu.com','index.html','user','a=6','comment']
    print(parse.urlunparse(data))

    这样就实现了URL的构造了

     

    3.3 urlsplit()

    该方法和urlparse()非常相似,不同的就是它不再单独解析params这一部分。

     

    3.3 urlunsplit()

    与urlunparse()类似,它也是将连接各部分组合成完整连接的方法,传入的参数也是一个可迭代对象,唯一有区别的就是长度必须是5

     

    3.4 urlencode()

     该方法常用于构造GET请求的参数,具体用法在上面已经有示例。

     

    3.5 parse_qs()

    如果需要处理一串GET请求参数,可以利用该方法进行反序列化。

     

    3.6 quote()

    该方法可以将内容转化为URL编码的格式。URL中带有中文参数时,有时可能会导致乱码问题,此时用这个方法可以将中文字符转化为URL编码

    from urllib.parse import quote
    
    keyword = '壁纸'
    url = 'https://www.baidu.com/s?wd=' + quote(keyword)
    print(url)

    对应的,还有unquote()方法,用于URL解码

    from urllib.parse import unquote
    
    url = 'https://www.baidu.com/s?wd=%E5%A3%81%E7%BA%BB'
    print(unquote(url))
  • 相关阅读:
    Linux驱动之Framebuffer子系统基础知识
    C/C++语言常见面试题汇总
    转载-Linux驱动面试题汇总
    nginx服务在html中嵌入php代码无法显示问题
    关于strsep函数以及联想
    system替代函数
    system问题总结记录
    C语言-判断文件是否存在
    vue常见表单信息收集
    sublime 设置格式化快捷键
  • 原文地址:https://www.cnblogs.com/jonas-von/p/9172847.html
Copyright © 2020-2023  润新知