zoukankan      html  css  js  c++  java
  • (转)Python3 模块3之 Urllib之 urllib.parse、urllib.robotparser

    原文:https://blog.csdn.net/qq_36148847/article/details/79153738

    https://blog.csdn.net/zly412934578/article/details/77776659

    https://blog.csdn.net/shangulidexiao/article/details/70174318

    紧接上一篇:Python3 模块2之 Urllib之 urllib.error

    urllib.parse
    urllib.parse 模块定义了一个标准接口,在组件(addressing scheme、网址以及路径等)中打破了统一资源定位器(URL)字符串,并将相对 URL(relative URL)转换为给定的 基 URL(base URL) 的绝对 URL(absolute URL)。
    urllib.parse 被设计成在相对统一资源定位器(Relative Uniform Resource Locators)上与互联网 RFC 相匹配。它支持如下的 URL schemes (URL 协议): file、 ftp、gopher、hdl、http、 https、imap、 mailto、 mms、news、nntp、 prospero、rsync、rtsp、 rtspu、 sftp、 shttp、 sip、 sips、 snews、svn、svn+ssh、 telnet、 wais、 ws、wss。

    urllib.parse 分为 URL parsing (网址解析)和URL quoting(地址引用) 。

    一. 网址解析(URL Parsing)
    URL 解析函数专注于将 URL 字符串拆分为其组件,或将 URL 组件组合到 URL 字符串中。

    下面简要分析使用对应解析函数
    1.urlparse

    定义:urllib.parse.urlparse(urlstring, scheme=”, allow_fragments=True)

    作用特点:将 URL 拆分成 6 大组件

    通常一个基本点 URL 应该为:scheme://netloc/path;parameters?query#fragment ,每个元素组都为 String 字符串类型,或者为空。例如,http://www.cwi.nl:80/%7Eguido/Python.html

    除这六大组件外,该类具有以下附加的只读便利属性(可看下表):

    属性 索引 值 值为 None
    scheme 0 URL 协议 scheme 参数
    netloc 1 网络端口 空字符串
    path 2 分层路径 空字符串
    params 3 最后一个路径元素参数 空字符串
    query 4 Query 组件 空字符串
    fragment 5 片段标志符 空字符串
    username 用户名 None
    password Password None
    hostname 主机名 (小写) None
    port 如果存在,端口值为整数 None
    下面是一个实例:

    #! /usr/bin/evn python3

    #"测试urlparse"
    #导入parse模块
    from urllib import parse

    urp = parse.urlparse('https://docs.python.org/3/search.html?q=parse&check_keywords=yes&area=default')
    print(urp)
    #result:ParseResult(scheme='http', netloc='www.baidu.com:80', path='/doc', params='', query='age=5', fragment='ff')
    print(urp.scheme)
    #result:http
    print(urp.netloc)
    #result:www.baidu.com:80
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    输出:

    ParseResult(scheme='https', netloc='docs.python.org', path='/3/search.html', params='', query='q=parse&check_keywords=yes&area=default', fragment='')
    https
    docs.python.org
    1
    2
    3
    4
    urllib.parse.parse_qsl(qs, keep_blank_values=False, strict_parsing=False, encoding=’utf-8’, errors=’replace’)

    2.urlunparse

    定义:urllib.parse.urlunparse(parts)

    从urlparse() 返回的元组元素构造一个URL 。该部分参数可以是任何六个组件的迭代。如果最初解析的 URL 有不必要的分隔符(例如 ?;带有空查询; RFC 声明它们是等同的),则这可能会导致稍微不同但等效的URL 。

    下面是一个实例:

    #! /usr/bin/evn python
    #测试urlunparse
    #导入parse模块
    from urllib import parse
    parsed=parse.urlparse('http://user:pass@NetLoc:80/path;parameters?query=argument#fragment')
    print(parsed)
    url=parse.urlunparse(parsed)
    print(url)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    输出:

    ParseResult(scheme='http', netloc='user:pass@NetLoc:80', path='/path', params='parameters', query='query=argument', fragment='fragment')
    http://user:pass@NetLoc:80/path;parameters?query=argument#fragment
    1
    2
    3
    三.parse_qs

    定义:urllib.parse.parse_qs(qs, keep_blank_values=False, strict_parsing=False, encoding=’utf-8’, errors=’replace’)

    解析一个作为字符串参数给定的查询字符串(类型application/x-www-form-urlencoded 类型的数据)。数据作为字典返回。字典键是唯一的查询变量名且值是每个名称的值列表。

    可选参数 keep_blank_values 是指示分空值编码的查询应处理为空字符串标志。一个真值表示空值应保留为空字符串。参数 keep_blank_values 的默认值为 false 表示空值将被忽略,并被视为不包括在内。

    可选参数 strict_parsing 是一个标志,表示如何处理解析错误。如果值为 FALSE(默认),错误将被忽略。如果是 `TRUE 1的,误差使 ValueError 异常增加。

    四.parse_qsl

    定义:urllib.parse.parse_qsl(qs, keep_blank_values=False, strict_parsing=False, encoding=’utf-8’, errors=’replace’)

    基本用法与 parse_qs 一致,只是urllib.parse.parse_qs 返回字典,urllib.parse.parse_qsl 返回列表。

    下面是一个针对 三、四的实例:

    from urllib import parse
    url = r'https://docs.python.org/3.5/search.html?q=parse&check_keywords=yes&area=default'
    parseResult = parse.urlparse(url)
    #print(parseResult)
    # parseResult 数据格式满足 parse.parse_qs、parse.parse_qsl 传入的数据格式要求
    param_dict = parse.parse_qs(parseResult.query)
    param_list = parse.parse_qsl(parseResult.query)
    print("返回字典:",param_dict)
    print("返回列表:",param_list)

    #注意:加号会被解码,可能有时并不是我们想要的
    pps = parse.parse_qs('proxy=183.222.102.178:8080&task=XXXXX|5-3+2')
    print(pps)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    输出:

    返回字典: {'q': ['parse'], 'check_keywords': ['yes'], 'area': ['default']}
    返回列表: [('q', 'parse'), ('check_keywords', 'yes'), ('area', 'default')]
    {'proxy': ['183.222.102.178:8080'], 'task': ['XXXXX|5-3 2']}
    1
    2
    3
    4
    五.urlsplit

    定义:urllib.parse.urlsplit(urlstring, scheme=”, allow_fragments=True)
    返回:(scheme, netloc, path, query, fragment) 比 urlparse 少个params 参数

    这与 urlparse()URL 相似,但不会将参数分开。通常应该使用这种方法,而不是使用 urlparse() 允许将参数应用到 URL 的路径部分的每个段的更新的 URL(请参阅RFC2396 )。分段函数分隔路径段和参数。这个函数返回一个5元组:(寻址方案(addressing scheme),网络地址(network location),路径(path),查询( query),片段标识符(fragment identifier))。

    返回值实际上是一个子类的实例tuple。该类具有以下附加的只读便利属性:

    属性 索引 值 值为空
    scheme 0 URL 协议 scheme 参数
    netloc 1 网络端口 空字符串
    path 2 分层路径 空字符串
    params 3 最后一个路径元素参数 空字符串
    query 4 Query 组件 空字符串
    fragment 5 片段标志符 空字符串
    username 用户名 None
    password Password None
    hostname 主机名 (小写) None
    port 如果存在,端口值为整数 None
    下面是一个实例:

    #! /usr/bin/evn python
    #测试 urlsplit
    #导入 parse 模块
    from urllib import parse
    print (parse.urlsplit('http://www.jb51.net:80/faq.cgi?src=fie'))
    #result:SplitResult(scheme='http', netloc='www.jb51.net:80', path='/faq.cgi', query='src=fie', fragment='')
    1
    2
    3
    4
    5
    6
    7
    输出:

    SplitResult(scheme='http', netloc='www.jb51.net:80', path='/faq.cgi', query='src=fie', fragment='')
    1
    六.urlunsplit

    urllib.parse.urlunsplit(parts)

    结合一个 urlsplit() 返回的元组元素形成一个完整的 URL 字符串。参数的部分参数可以是可迭代的 five-item。如果被解析的 URL 含有本不必要的分隔符(比如 ? 、查询为空、RFC 明这些是等价的),有这可能会导致一个稍有不同但等效的 URL。

    下面是一个实例:

    #! /usr/bin/evn python
    #测试urlunparse
    #导入parse模块
    from urllib import parse
    sr = parse.SplitResult(scheme='http', netloc='www.baidu.com:80', path='/doc', query='age=5', fragment='ff')
    print(parse.urlunsplit(sr))
    #result:http://www.baidu.com:80/doc?age=5#ff
    1
    2
    3
    4
    5
    6
    7
    8
    输出:

    http://www.baidu.com:80/doc?age=5#ff
    1
    七.urljoin

    urllib.parse.urljoin(base, url, allow_fragments=True)

    通过将基URL(base )与另一个 URL(url) 组合起来构建完整的(绝对)的URL。

    下面是一个例子:

    #!/usr/bin/evn python3
    #测试urljoin
    #导入parse模块
    from urllib import parse
    uj1 = parse.urljoin("http://www.asite.com/folder1/currentpage.html","anotherpage.html")
    uj2 = parse.urljoin("http://www.asite.com/folder1/currentpage.html","folder2/anotherpage.html")
    uj3 = parse.urljoin("http://www.asite.com/folder1/currentpage.html","/folder3/anotnerpage.html")
    uj4 = parse.urljoin("http://www.asite.com/folder1/currentpage.html","../finalpage.html")
    print(uj1)
    print(uj2)
    print(uj3)
    print(uj4)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    输出:

    http://www.asite.com/folder1/anotherpage.html
    http://www.asite.com/folder1/folder2/anotherpage.html
    http://www.asite.com/folder3/anotnerpage.html
    http://www.asite.com/finalpage.html
    1
    2
    3
    4
    5
    Note:如果 url 是一个绝对 URL(即以// 或 scheme:// 开头的 url ),url 的主机名或 scheme 将会替代 base 。

    下面是一个实例:

    #!/usr/bin/evn python3
    #测试urljoin
    #导入parse模块
    from urllib import parse
    uj1 = parse.urljoin("http://www.asite.com/folder/currentpage.html","https://www.python.org/folder2")
    uj2 = parse.urljoin("http://www.asite.com/folder/currentpage.html","//www.python.org/folder1")
    uj3 = parse.urljoin("http://www.asite.com/folder/currentpage.html","www.python.org/folder2")

    print(uj1)
    print(uj2)
    print(uj3)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    输出:

    https://www.python.org/folder2
    http://www.python.org/folder1
    http://www.asite.com/folder/www.python.org/folder2
    1
    2
    3
    4
    八.urldefrag

    urllib.parse.urldefrag(url)

    如果 url 包含片段标志符(即 url 尾部的 #+锚点标签 内容),则返回一个不含片段标志符的 url 且片段标志符分成独立的字符串序列。如何 url 不包含片段标志符则返回未修改的 url 和一个空字符串。

    返回值实际上是元组( tuple) 的一个子类的实例。这个类具有以下附加的只读的,便利的属性:

    属性 索引 值 值为空
    url 0 不具有标志符的 url 空字符串
    fragment 1 片段标志符 空字符串
    下面是一个实例:

    #! /usr/bin/evn python
    #测试 urlunparse
    #导入parse模块
    from urllib import parse
    ud = parse.urldefrag('http://music.163.com/#/my/')
    print(ud)
    #result:DefragResult(url='http://music.163.com/', fragment='/my/')
    1
    2
    3
    4
    5
    6
    7
    8
    输出:

    DefragResult(url='http://music.163.com/', fragment='/my/')
    1
    二.地址引用(URL Quoting)
    URL引用函数侧重于获取程序数据,并通过引用特殊字符和适当地编码非ASCII文本来使其作为URL组件安全使用。它们还支持逆转这些操作,以使URL组件的内容重新创建原始数据,如果上述URL解析函数未覆盖该任务的话。

    一.quote |quote_from_bytes

    定义:urllib.parse.quote(string, safe=’/’, encoding=None, errors=None)
    定义:urllib.parse.quote_from_bytes(bytes, safe=’/’)
    功能:对字符进行转码,特殊字符(保留字符),如“;” | “/” | “?” | “:” | “@” | “&” | “=” | “+” |”$” | “,” 不转码。

    下面是一个实例:

    #! /usr/bin/evn python
    #测试 parse.quote
    #导入parse模块
    from urllib import parse
    quoted = parse.quote('https://www.baidu.com/s?ie=utf-8&f=8&rsv_bp=1&tn=baidu&wd=%E6%95%B0%E5%AD%A6&oq=%25E9%25AB%2598%25E7%25AD%2589%25E6%2595%25B0%25E5%25AD%25A6&rsv_pq=bc3192bd00006199&rsv_t=9874L5kHfiTTvwbjdnArv85fD%2B4yAJXywKFWw1HfLoGCNsctPGieUGbvTcY')
    print(quoted)
    1
    2
    3
    4
    5
    6
    7
    输出:

    https%3A//www.baidu.com/s%3Fie%3Dutf-8%26f%3D8%26rsv_bp%3D1%26tn%3Dbaidu%26wd%3D%25E6%2595%25B0%25E5%25AD%25A6%26oq%3D%2525E9%2525AB%252598%2525E7%2525AD%252589%2525E6%252595%2525B0%2525E5%2525AD%2525A6%26rsv_pq%3Dbc3192bd00006199%26rsv_t%3D9874L5kHfiTTvwbjdnArv85fD%252B4yAJXywKFWw1HfLoGCNsctPGieUGbvTcY
    1
    2
    二.quote_plus

    定义:urllib.parse.quote_plus(string, safe=”, encoding=None, errors=None)

    与 quote 相似,由 quote_plus 编码 /, quote 不编码 /
    下面是个实例:

    #! /usr/bin/evn python
    #测试 parse.quote 、parse.quote_plus
    #导入parse模块
    from urllib import parse
    p=parse.quote('a&b/c') #未编码斜线
    print('quote:',p)
    plus=parse.quote_plus('a&b/c') #编码了斜线
    print('plus:',plus)
    1
    2
    3
    4
    5
    6
    7
    8
    输出

    quote: a%26b/c
    plus: a%26b%2Fc
    1
    2
    3
    三.unquote|unquote_to_bytes

    定义:urllib.parse.unquote(string, encoding=’utf-8’, errors=’replace’)
    定义:urllib.parse.unquote_to_bytes(string)
    功能:quote 的逆过程

    下面是一个实例:

    #!/usr/bin/evn python
    #测试 unquote、unquote_to_bytes
    #导入parse模块
    from urllib import parse
    print(parse.unquote('http%3A//www.baidu.com/doc/sub.html%3Fname%3Dhan%20jian%26age%3D45%40%3B+$'))
    print(parse.unquote_to_bytes('http%3A//www.baidu.com/doc/sub.html%3Fname%3Dhan%20jian%26age%3D45%40%3B+$'))
    1
    2
    3
    4
    5
    6
    7
    输出:

    http://www.baidu.com/doc/sub.html?name=han jian&age=45@;+$
    b'http://www.baidu.com/doc/sub.html?name=han jian&age=45@;+$'
    1
    2
    四.unquote_plus

    定义:urllib.parse.unquote_plus(string, encoding=’utf-8’, errors=’replace’)
    功能:quote_plus的逆过程

    下面是个实例:

    #! /usr/bin/evn python
    #测试 parse.unquote 、parse.unquote_plus
    #导入parse模块
    from urllib import parse
    uq=parse.unquote('1+2') #不解码加号
    print('unquote:',uq)
    uqp=parse.unquote_plus('1+2') #把加号解码为空格
    print('unquote_plus:',uqp)
    1
    2
    3
    4
    5
    6
    7
    8
    输出:

    unquote: 1+2
    unquote_plus: 1 2
    1
    2
    五.urlencode

    定义:urllib.parse.urlencode(query, doseq=False, safe=”, encoding=None, errors=None, quote_via=quote_plus)
    功能:将字典形式的数据转化成查询字符串
    参数的含义:
    query:需要转化的字典数据
    doseq:如果字典的某个值是序列的话是否解析,deseq值为False不解析doseq的值为True的时候解析,稍后在例子中给出
    safe:那些字符串不需要编码
    encoding:要转化成的字符串的编码
    quote_via:使用quote编码还是qutoe_plus编码,默认quote_plus也就是空格被转化成+号

    下面是一个实例:

    #!/usr/bin/env python3
    #urlencode 测试
    from urllib import parse
    #定义要转化的字典数据
    qdict = {'age':34,'grils':('lili','tingting'),'name':'han p$'}
    print(parse.urlencode(qdict))
    #result:
    #age=34&grils=%28%27lili%27%2C+%27tingting%27%29&name=han+p%24

    #怎么让两个女朋友分开呢
    print(parse.urlencode(qdict,True))

    #result
    #age=34&grils=lili&grils=tingting&name=han+p%24

    #怎么让name里边的$不要编码呢
    print(parse.urlencode(qdict,True,'$'))

    #result
    #age=34&grils=lili&grils=tingting&name=han+p$

    #怎么让空格不编码成+而编译成%20呢
    print(parse.urlencode(qdict,True,'$',quote_via=parse.quote))
    #由于前面还有两个位置参数所以使用关键字参数
    #result age=34&grils=lili&grils=tingting&name=han%20p$
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    输出:

    age=34&grils=%28%27lili%27%2C+%27tingting%27%29&name=han+p%24
    age=34&grils=lili&grils=tingting&name=han+p%24
    age=34&grils=lili&grils=tingting&name=han+p$
    age=34&grils=lili&grils=tingting&name=han%20p$
    1
    2
    3
    4
    5
    三.urllib.robotparse
    一. 了解网站文件 robots.txt

    每个网站都会定义 robots.txt 文件,这个文件可以告诉网络爬虫爬取该网站时存在哪些限制。作为良好网民以及其他人利益,一般上遵从这些限制。

    如何查看这个文件?可以通过在目标网站站点或域名后面加上 robots.txt 进行访问。

    例如 目标网站站点 https://www.douban.com 的 robots.txt 文件就是 https://www.douban.com/robots.txt。
    下面即为这个文件内容:

    User-agent: *
    Disallow: /subject_search
    Disallow: /amazon_search
    Disallow: /search
    Disallow: /group/search
    Disallow: /event/search
    Disallow: /celebrities/search
    Disallow: /location/drama/search
    Disallow: /forum/
    Disallow: /new_subject
    Disallow: /service/iframe
    Disallow: /j/
    Disallow: /link2/
    Disallow: /recommend/
    Disallow: /trailer/
    Disallow: /doubanapp/card

    # section 1
    Sitemap: https://www.douban.com/sitemap_index.xml
    Sitemap: https://www.douban.com/sitemap_updated_index.xml

    # section 2
    # Crawl-delay: 5

    # section 3
    User-agent: Wandoujia Spider
    Disallow: /
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    关于这个 robots.txt 文件内容:

    section 1:

    定义了 ` Sitemap` 文件,即所谓的网站地图。
    1
    section 2:

    这被注释掉的部分,如果没有被注释且指明了跳转链接,那么,表明每个用户两次爬虫之间的时间间隔不能小于 5s 否则所访问的网站网页会自动跳转到指定的链接页面。此时,相当于网站服务器禁封了 IP ,禁封时间依据各网站的情况。
    1
    section 3:

    这部分表示,`robots.txt` 文件禁止那些代理为 ` Wandoujia Spider` 的爬虫访问网站。理解过来,就是禁止豌豆荚爬虫代理访问网站。
    1
    二. 检查网站地图(Sitemap)

    打开 robots.txt 文件里面的 Sitemap 地址,例如上面的 Sitemap 有, https://www.douban.com/sitemap_index.xml 和 Sitemap: https://www.douban.com/sitemap_updated_index.xml 。

    网站提供的 Sitemap 文件(即 网站地图)提供了该网站站点里面所有页面的链接,这些链接组成了这个 Sitemap 文件,所以叫做地图并不过分。 这样,便无须爬取某个网站站点里面的每一个网页因为网站提供的 Sitemap 文件 帮助了网络爬虫定为网站最新的内容(如下图)。

    Note:虽然 Sitemap 文件提供了一种爬取网站的有效方式,但是我们仍需要对其谨慎处理,因为该文件经常存在缺失、过期或者不完整的问题。(观点以及学习视角引用自:Python 网络爬虫 010 (高级功能) 解析 robots.txt 文件

    三. robots.txt 文件的使用测试

    还是那个豆瓣的 robots.txt 文件 https://www.douban.com/robots.txt。

    如下为文件内容:

    User-agent: *
    Disallow: /subject_search
    Disallow: /amazon_search
    Disallow: /search
    Disallow: /group/search
    Disallow: /event/search
    Disallow: /celebrities/search
    Disallow: /location/drama/search
    Disallow: /forum/
    Disallow: /new_subject
    Disallow: /service/iframe
    Disallow: /j/
    Disallow: /link2/
    Disallow: /recommend/
    Disallow: /trailer/
    Disallow: /doubanapp/card
    Sitemap: https://www.douban.com/sitemap_index.xml
    Sitemap: https://www.douban.com/sitemap_updated_index.xml
    # Crawl-delay: 5

    User-agent: Wandoujia Spider
    Disallow: /
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    对于这个 robots.txt 文件来说, Wandoujia Spider 的代理用户是禁止预览该站点的。

    可以使用Python 自带的 robotparser 模块测试一下:

    import urllib.robotparser
    rp = robotparser.RobotFileParser()
    rp.set_url('https://www.douban.com/robots.txt')
    rp.read()
    url = 'https://www.douban.com'
    user_agent = 'Wandoujia Spider'
    wsp_info = rp.can_fetch(user_agent, url)
    print("Wandoujia Spider 代理用户访问情况:",wsp_info)
    user_agent = 'Other Spider'
    osp_info = rp.can_fetch(user_agent, url)
    print("Other Spider 代理用户访问情况:",osp_info)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    输出:

    Wandoujia Spider 代理用户访问情况: False
    Other Spider 代理用户访问情况: True
    1
    2
    3
    学习资料:python doc 、Python 网络爬虫 010 (高级功能) 解析 robots.txt 文件 、Python 网络爬虫 010 (高级功能) 解析 robots.txt 文件、urllib的parse模块。

  • 相关阅读:
    JSONP的学习(收集整理)
    10个必备的移动UI设计资源站(转)
    iscroll4框架解析[webapp开发](转)
    IE9中Media queries在iframe无效的解决方法
    mustache模板技术
    企业级的响应式设计(Responsive design at enterprise level)译
    在JSP中使用jQuery的冲突解决(收集整理)
    Java开发 Eclipse使用技巧(转)
    Front End中Javascript兼容问题收集(转)
    vector it->和*it
  • 原文地址:https://www.cnblogs.com/liujiacai/p/9989321.html
Copyright © 2011-2022 走看看