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
    你灵魂的欲望,是你命运的先知。

  • 相关阅读:
    ThinkPHP 实现数据库事务回滚示例代码
    Java数据结构和算法
    Java数据结构和算法
    Java数据结构和算法
    git push每次提交都要输入用户名的解决方案
    Java数据结构与算法
    Java数据结构和算法
    Java数据结构和算法
    类和接口
    git如何忽略文件
  • 原文地址:https://www.cnblogs.com/RioTian/p/15230874.html
Copyright © 2011-2022 走看看