zoukankan      html  css  js  c++  java
  • 【网络爬虫学习】第一个Python爬虫程序 & 编码与解码详解 & Pythonの实现

    本节编写一个最简单的爬虫程序,作为学习 Python 爬虫前的开胃小菜。

    下面使用 Python 内置的 urllib 库获取网页的 html 信息。注意,urllib 库属于 Python 的标准库模块,无须单独安装,它是 Python 爬虫的常用模块。

    获取网页html信息

    1) 获取响应对象

    向百度(http://www.baidu.com/)发起请求,获取百度首页的 HTML 信息,代码如下:

    # 导包,发起请求使用urllib库的request请求模块
    import urllib.request
    
    # urlopen()向URL发请求,返回响应对象,注意url必须完整
    responese = urllib.request.urlopen('https://www.baidu.com/')
    print(responese)
    
    

    上述代码会返回百度首页的响应对象, 其中 urlopen() 表示打开一个网页地址。

    注意:请求的 url 必须带有 http 或者 https 传输协议。

    输出结果,如下所示:

    <http.client.HTTPResponse object at 0x032F0F90>
    

    上述代码也有另外一种导包方式,也就是使用 from,代码如下所示:

    # 发起请求使用urllib库的request请求模块
    from urllib import request
    
    responese = request.urlopen('https://www.baidu.com/')
    print(responese)
    
    

    2) 输出HTML信息

    在上述代码的基础上继续编写如下代码:

    # 提取响应内容
    html = responese.read().decode('utf-8')
    # 打印响应内容
    print(html)
    

    输出结果如下,由于篇幅过长,此处只做了简单显示:

    <http.client.HTTPResponse object at 0x03678E68>
    <html>
    <head>
            <script>
                    location.replace(location.href.replace("https://","http://"));
            </script>
    </head>
    <body>
            <noscript><meta http-equiv="refresh" content="0;url=http://www.baidu.com/"></noscript>   
    </body>
    </html>
    

    通过调用 response 响应对象的 read() 方法提取 HTML 信息,该方法返回的结果是字节串类型(bytes),因此需要使用 decode() 转换为字符串。程序完整的代码程序如下:

    # 发起请求使用urllib库的request请求模块
    from urllib import request
    
    responese = request.urlopen('https://www.baidu.com/')
    print(responese)
    
    # 提取响应内容
    html = responese.read().decode('utf-8')
    # 打印响应内容
    print(html)
    

    通过上述代码获取了百度首页的 html 信息,这是最简单、最初级的爬虫程序。后续我们还学习如何分析网页结构、解析网页数据,以及存储数据等。

    常用方法

    在本节您认识了第一个爬虫库 urllib,下面关于 urllib 做简单总结。

    1) urlopen()

    表示向网站发起请求并获取响应对象,如下所示:

    urllib.request.urlopen(url,timeout)
    

    urlopen() 有两个参数,说明如下:

    • url:表示要爬取数据的 url 地址。
    • timeout:设置等待超时时间,指定时间内未得到响应则抛出超时异常。

    2) Request()

    该方法用于创建请求对象、包装请求头,比如重构 User-Agent(即用户代理,指用户使用的浏览器)使程序更像人类的请求,而非机器。重构 User-Agent 是爬虫和反爬虫斗争的第一步。在下一节会做详细介绍。

    urllib.request.Request(url, headers)
    

    参数说明如下:

    • url:请求的URL地址。
    • headers:重构请求头。

    3) html响应对象方法

    bytes = response.read() # read()返回结果为 bytes 数据类型
    string = response.read().decode() # decode()将字节串转换为 string 类型
    url = response.geturl() # 返回响应对象的URL地址
    code = response.getcode() # 返回请求时的HTTP响应码
    

    4) 编码解码操作

    #字符串转换为字节码
    string.encode("utf-8") 
    #字节码转换为字符串
    bytes.decode("utf-8") 
    

    [QAQ ]


    既然这里提到了解码以及编码就稍微进阶一下...

    请注意,本部分来自 阮一峰的网络日志 & C语言中文网的URL编码/解码详解

    URL就是网址,只要上网,就一定会用到。

    一般来说,URL只能使用英文字母、阿拉伯数字和某些标点符号,不能使用其他文字和符号。比如,世界上有英文字母的网址"http://www.abc.com",但是没有希腊字母的网址"http://www.aβγ.com"(读作阿尔法-贝塔-伽玛.com)。这是因为网络标准RFC 1738做了硬性规定:

    "...Only alphanumerics [0-9a-zA-Z], the special characters "$-_.+!*'()," [not including the quotes - ed], and reserved characters used for their reserved purposes may be used unencoded within a URL."
    
    "只有字母和数字[0-9a-zA-Z]、一些特殊符号"$-_.+!*'(),"[不包括双引号]、以及某些保留字,才可以不经过编码直接用于URL。"
    

    关于汉字部分的详解请移步自:Here 进行学习,这里不多介绍了。

    当 URL 路径或者查询参数中,带有中文或者特殊字符的时候,就需要对 URL 进行编码(采用十六进制编码格式)。URL 编码的原则是使用安全字符去表示那些不安全的字符。

    PS:安全字符,指的是没有特殊用途或者特殊意义的字符。

    URL基本组成

    URL 是由一些简单的组件构成,比如协议、域名、端口号、路径和查询字符串等,示例如下:

    https://www.cnblogs.com/RioTian/index?param=10
    

    路径和查询字符串之间使用问号?隔开。上述示例的域名为 www.cnblogs.com/RioTian/,路径为 index,查询字符串为 param=10。

    URL 中规定了一些具有特殊意义的字符,常被用来分隔两个不同的 URL 组件,这些字符被称为保留字符。例如:

    • 冒号:用于分隔协议和主机组件,斜杠用于分隔主机和路径
    • ?:用于分隔路径和查询参数等。
    • =用于表示查询参数中的键值对。
    • &符号用于分隔查询多个键值对。
    其余常用的保留字符有:/ . ... # @ $ + ; %
    

    哪些字符需要编码

    URL 之所以需要编码,是因为 URL 中的某些字符会引起歧义,比如 URL 查询参数中包含了”&”或者”%”就会造成服务器解析错误;再比如,URL 的编码格式采用的是 ASCII 码而非 Unicode 格式,这表明 URL 中不允许包含任何非 ASCII 字符(比如中文),否则就会造成 URL 解析错误。

    URL 编码协议规定(RFC3986 协议):URL 中只允许使用 ASCII 字符集可以显示的字符,比如英文字母、数字、和- _ . ~ ! *这 6 个特殊字符。当在 URL 中使用不属于 ASCII 字符集的字符时,就要使用特殊的符号对该字符进行编码,比如空格需要用%20来表示。

    除了无法显示的字符需要编码外,还需要对 URL 中的部分保留字符不安全字符进行编码。下面列举了部分不安全字符:

    [ ] < > " "  { } |  ^ * · ‘ ’ 等
    

    下面示例,查询字符串中包含一些特殊字符,这些特殊字符不需要编码:

    http://www.biancheng.net/index?param=10!*&param1=20!-~_
    

    下表对 URL 中部分保留字符和不安全字符进行了说明:

    字符 (URL特殊字符编码) 含义 十六进制值编码
    + URL 中 + 号表示空格 %2B
    空格 URL中的空格可以编码为 + 号或者 %20 %20
    / 分隔目录和子目录 %2F
    ? 分隔实际的 URL 和参数 %3F
    % 指定特殊字符 %25
    # 表示书签 %23
    & URL 中指定的参数间的分隔符 %26
    = URL 中指定参数的值 %3D

    下面简单总结一下,哪些字符需要编码,分为以下三种情况:

    • ASCII 表中没有对应的可显示字符,例如,汉字。
    • 不安全字符,包括:# ”% <> [] {} | ^ ` 。
    • 部分保留字符,即 & / : ; = ? @ 。

    Python实现编码与解码

    Python 的标准库urllib.parse模块中提供了用来编码和解码的方法,分别是 urlencode() 与 unquote() 方法。

    方法 说明
    urlencode() 该方法实现了对 url 地址的编码操作
    unquote() 该方法将编码后的 url 地址进行还原,被称为解码

    1) 编码urlencode()

    下面以百度搜索为例进行讲解。首先打开百度首页,在搜索框中输入“爬虫”,然后点击“百度一下”。当搜索结果显示后,此时地址栏的 URL 信息,如下所示:

    https://www.baidu.com/s?wd=爬虫&rsv_spt=1&rsv_iqid=0xa3ca348c0001a2ab&issp=1&f=8&rsv_bp=1&rsv_idx=2&ie=utf-8&tn=baiduhome_pg&rsv_enter=1&rsv_dl=ib&rsv_sug3=8&rsv_sug1=7&rsv_sug7=101
    

    可以看出 URL 中有很多的查询字符串,而第一个查询字符串就是“wd=爬虫”,其中 wd 表示查询字符串的键,而“爬虫”则代表您输入的值。

    在网页地址栏中删除多余的查询字符串,最后显示的 URL 如下所示:

    https://www.baidu.com/s?wd=爬虫
    

    使用搜索修改后的 URL 进行搜索,依然会得到相同页面。因此可知“wd”参数是百度搜索的关键查询参数。下面编写爬虫程序对 “wd=爬虫”进行编码,如下所示:

    from urllib import request
    from urllib import parse
    
    # 构建查询字符串字典
    query_string = {'wd': '爬虫'}
    # 调用parse模块的urlencode()进行编码
    result = parse.urlencode(query_string)
    # 使用format函数格式化字符串,拼接url地址
    url = 'http://www.baidu.com/s?{}'.format(result)
    print(url)
    

    输出结果,如下所示:

    wd=%E7%88%AC%E8%99%AB
    http://www.baidu.com/s?wd=%E7%88%AC%E8%99%AB
    

    编码后的 URL 地址依然可以通过地网页址栏实现搜索功能。

    除了使用 urlencode() 方法之外,也可以使用 quote(string) 方法实现编码,代码如下:

    from urllib import parse
    
    # 注意url的书写格式,和 urlencode存在不同
    url = 'http://www.baidu.com/s?wd={}'
    word = input('请输入要搜索的内容: ')
    # quote() 只能对字符串编码
    query_string = parse.quote(word)
    print(url.format(query_string))
    

    输出结果如下:

    输入:请输入要搜索的内容:RioTian博客园
    输出:http://www.baidu.com/s?wd=RioTian%E5%8D%9A%E5%AE%A2%E5%9B%AD
    

    编码后的 URL 地址依然可以通过地网页址栏实现搜索功能。

    除了使用 urlencode() 方法之外,也可以使用 quote(string) 方法实现编码,代码如下:

    from urllib import parse
    
    # 注意url的书写格式,和 urlencode存在不同
    url = 'http://www.baidu.com/s?wd={}'
    word = input('请输入要搜索的内容: ')
    # quote() 只能对字符串编码
    query_string = parse.quote(word)
    print(url.format(query_string))
    

    输出结果如下:

    请输入要搜索的内容: RioTian
    http://www.baidu.com/s?wd=RioTian
    

    注意:quote() 只能对字符串编码,而 urlencode() 可以直接对查询字符串字典进行编码。因此在定义 URL 时,需要注意两者之间的差异。方法如下:

    # urllib.parse
    urllib.parse.urlencode({'key':'value'}) #字典
    urllib.parse.quote(string) #字符串
    

    2) 解码unquote(string)

    解码是对编码后的 URL 进行还原的一种操作,示例代码如下:

    from urllib import parse
    
    string = '%E7%88%AC%E8%99%AB'
    print(parse.unquote(string))
    

    输出结果:

    爬虫
    

    3) URL地址拼接方式

    最后,给大家介绍三种拼接 URL 地址的方法。除了使用 format() 函数外,还可以使用字符串相加,以及字符串占位符,总结如下:

    似乎以前也写过(雾QAQ)

    # 1、字符串相加
    baseurl = 'http://www.baidu.com/s?'
    params = 'wd=%E7%88%AC%E8%99%AB'
    url = baseurl + params
    
    # 2、字符串格式化(占位符)
    params = 'wd=%E7%88%AC%E8%99%AB'
    url = 'http://www.baidu.com/s?%s' % params
    
    # 3、format()方法
    url = 'http://www.baidu.com/s?{}'
    params = 'wd=%E7%88%AC%E8%99%AB'
    url = url.format(params)
    

    The desire of his soul is the prophecy of his fate
    你灵魂的欲望,是你命运的先知。

  • 相关阅读:
    入门菜鸟
    FZU 1202
    XMU 1246
    Codeforces 294E Shaass the Great 树形dp
    Codeforces 773D Perishable Roads 最短路 (看题解)
    Codeforces 814E An unavoidable detour for home dp
    Codeforces 567E President and Roads 最短路 + tarjan求桥
    Codeforces 567F Mausoleum dp
    Codeforces 908G New Year and Original Order 数位dp
    Codeforces 813D Two Melodies dp
  • 原文地址:https://www.cnblogs.com/RioTian/p/15230874.html
Copyright © 2011-2022 走看看