zoukankan      html  css  js  c++  java
  • 2.爬虫 urlib库讲解 异常处理、URL解析、分析Robots协议

    1.异常处理

    URLError类来自urllib库的error模块,它继承自OSError类,是error异常模块的基类,由request模块产生的异常都可以通过这个类来处理

    from urllib import request, error
    
    try:
        response = request.urlopen('http://cuiqingcai.com/index.htm')
    except error.HTTPError as e:
        print(e.reason, e.code, e.headers, sep='
    ')
    except error.URLError as e:
        print(e.reason)
    else:
        print('Request Successfully')

    输出结果如下:

    Not Found
    404
    Server: nginx/1.10.3 (Ubuntu)
    Date: Tue, 09 Apr 2019 07:25:19 GMT
    Content-Type: text/html; charset=UTF-8
    Transfer-Encoding: chunked
    Connection: close
    Vary: Cookie
    Expires: Wed, 11 Jan 1984 05:00:00 GMT
    Cache-Control: no-cache, must-revalidate, max-age=0
    Link: <https://cuiqingcai.com/wp-json/>; rel="https://api.w.org/"
    

    * 这样来理解:URLError 和 HTTPError ==> URLError其子类是HTTPError。

    *URLError拥有属性reason;HTTPError拥有属性reason(原因)、headers(请求头)、code(状态码).

    import socket
    import urllib.request
    import urllib.error
    
    try:
        response = urllib.request.urlopen('https://www.baidu.com', timeout=0.01)
    except urllib.error.URLError as e:
        print(type(e.reason))
        if isinstance(e.reason, socket.timeout):
            print('TIME OUT')

    2.解析链接

    urllib库中的parse模块,它定义了处理URL的标准接口,例如实现URL各部分的抽取、合并以及链接转换.

    !!! scheme协议://netloc域名/path访问路径;params参数?query查询条件#fragment瞄点

    • urlencode() !!! 这个函数前面提到过,很重要,用于构造get请求参数
    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
    • urllib.parse.urlparse(urlstring, scheme='', allow_fragments=True):

    *该方法可以实现URL的识别和分段 urlstring必填项,即代解析的URL地址;scheme默认的协议(eg:http、https);allow_fragments是否忽略fragment

    实例0

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

    实例1

    from urllib.parse import urlparse
    
    result = urlparse('www.baidu.com/index.html;user?id=5#comment', scheme='https')
    print(result)
    
    """
    输出结果:
    ParseResult(scheme='https', netloc='', path='www.baidu.com/index.html', params='user', query='id=5', fragment='comment')
    """

    实例2

    from urllib.parse import urlparse
    
    result = urlparse('http://www.baidu.com/index.html;user?id=5#comment', scheme='https')
    print(result)
    
    """
    输出结果:
    ParseResult(scheme='http', netloc='www.baidu.com', path='/index.html', params='user', query='id=5', fragment='comment')
    """

    实例3

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

    实例4

    from urllib.parse import urlparse
    
    result = urlparse('http://www.baidu.com/index.html#comment', allow_fragments=False)
    print(result)
    
    """
    输出结果:
    ParseResult(scheme='http', netloc='www.baidu.com', path='/index.html#comment', params='', query='', fragment='')
    """
    • urlunparse(data) :实现URL的构造。长度必须为6、类型:列表、元组或特定的数据结构
    from urllib.parse import urlunparse
    
    data = ['http', 'www.baidu.com', 'index.html', 'user', 'a=6', 'comment']
    print(urlunparse(data))
    
    """
    结果如下:
    http://www.baidu.com/index.html;user?a=6#comment
    """
    • urljoin():实现链接的解析合并和生成
    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'))

    输出结果如下:

    http://www.baidu.com/FAQ.html
    https://cuiqingcai.com/FAQ.html
    https://cuiqingcai.com/FAQ.html
    https://cuiqingcai.com/FAQ.html?question=2
    https://cuiqingcai.com/index.php
    http://www.baidu.com?category=2#comment
    www.baidu.com?category=2#comment
    www.baidu.com?category=2
    

    *有点晕?没关系.是有一定规律的,简单来说,有两个参数,以后面的那个为准,没有的补充,有的后者覆盖前者。

    *值得注意的是:第一个参数path访问路径后面的(即params、query、fragment)是不起作用的。(看最后的那个打印就明白了)

    • urlsplit():类似与urlparse。区别:urlsplit()会将params合并到path中,返回5个结果,其返回的结果是一个元组类型,即可以用属性获取值,也可以用索引来索取。
    from urllib.parse import urlsplit
    
    result = urlsplit('http://www.baidu.com/index.html;user?id=5#comment')
    print(type(result), result)
    print(result.scheme,result[0])
    
    """
    <class 'urllib.parse.SplitResult'> SplitResult(scheme='http', netloc='www.baidu.com', path='/index.html;user', query='id=5', fragment='comment')
    http http
    """
    
    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')
    """
    • urlunsplit():类似与urlunparse。唯一的区别是:传入的参数长度必须为5.
    from urllib.parse import urlunsplit
    
    data = ['http', 'www.baidu.com', 'index.html', 'a=6', 'comment']
    print(urlunsplit(data))
    
    """
    http://www.baidu.com/index.html?a=6#comment
    """
    
    from urllib.parse import urlunparse
    
    data = ['http', 'www.baidu.com', 'index.html', 'user', 'a=6', 'comment']
    print(urlunparse(data))
    
    """
    http://www.baidu.com/index.html;user?a=6#comment
    """
    • parse_qs():反序列化,将一串Get请求数据转回字典。
    from urllib.parse import parse_qs
    
    query = 'name=germey&age=22'
    print(parse_qs(query))
    
    """
    {'name': ['germey'], 'age': ['22']}
    """
    • parse_qsl():将参数转换为元组组成的列表。
    from urllib.parse import parse_qsl
    
    query = 'name=germey&age=22'
    print(parse_qsl(query))
    
    """
    [('name', 'germey'), ('age', '22')]
    """
    • quote()与unquote():URL编码和解码
    from urllib.parse import quote
    
    keyword = "我爱你"
    url = 'https://www.baidu.com/s?wd=' + quote(keyword)
    print(url)
    
    """
    https://www.baidu.com/s?wd=%E6%88%91%E7%88%B1%E4%BD%A0
    """
    
    
    from urllib.parse import unquote
    
    url = 'https://www.baidu.com/s?wd=%E6%88%91%E7%88%B1%E4%BD%A0'
    print(unquote(url))
    
    """
    https://www.baidu.com/s?wd=我爱你
    """

    3.分析Robots协议(爬虫协议、机器人协议)

    *告知爬虫和搜索引擎哪些页面可以爬取,哪些页面不可爬取。它通常是一个叫作robots.txt的文本文件。

    举例:robots.txt

      User-agent:* (*指代所有爬虫)

      Disallow: /  (禁止爬取'/'所有目录)

      Allow:/public/ (允许爬取的目录)

    *利用urllib的robotparser模块,我们可以实现网站的Robots协议的分析。

    ==>常用的几个方法:(只例举出3个,其实还有parse()、mtime()、modified(),用到的时候再说)

    set_url:设置robots.txt文件的链接。

    read():读取robots.txt文件并进行分析.必须调用!!!

    can_fetch():参数1 User-agent,参数2 URL.返回结果True.False表明是否可以爬取.

    from urllib.robotparser import RobotFileParser
    rp = RobotFileParser()
    rp.set_url('http://www.jianshu.com/robots.txt')
    rp.read()
    print(rp.can_fetch('*','http://www.jianshu.com/p/b67554025d7d'))
    print(rp.can_fetch('*','http://www.jianshu.com/search?q=python&page=1&type=collections'))
    
    """
    结果如下:
    False
    False
    """
    # 也可以使用parse()方法执行读取和分析.那个相对复杂,我选择简单的,够用就行.
  • 相关阅读:
    leetcode刷题 650~
    leetcode刷题 633~
    发送udp报文
    SIP (Session Initiation Protocol) 协议
    你所不知道的replace
    uni-app(六)生成海报图片路径问题
    uni-app(五)小程序的一些注意事项,踩坑
    uni-app(四)小程序里的vuex
    uni-app(三)组件、插件使用,引入字体
    uni-app(二)接口请求封装,全局输出api
  • 原文地址:https://www.cnblogs.com/DC0307/p/10677021.html
Copyright © 2011-2022 走看看