zoukankan      html  css  js  c++  java
  • 《Python网络爬虫权威指南》读书笔记1(第1章:初见爬虫)

    前言

    这本书的所有代码示例都在GitHub网站上(https://github.com/REMitchell/python-scraping),可以查看和下载。

    如果想要更全面地学习Python,Bill Lubanovic写的《Python语言及其应用》是一本非常好的教材。(笔者还没有看,笔者选用的入门教材是《Python编程:从入门到实践》)

    补充材料(代码示例、练习等)可以从https://github.com/REMitchell/python-scraping下载。

    第1章 初见网络爬虫

    1.1 网络连接

    from urllib.request import urlopen
    
    html = urlopen('http://pythonscraping.com/pages/page1.html')
    print(html.read())

    把上面这段代码保存为scrapetest.py,然后再终端运行如下指令:

     python scrapetest.py

    这会输出http://pythonscraping.com/pages/page1.html 这个网页的全部HTML代码。更准确地说,这会输出在域名为http://pythonscraping.com 的服务器上<网络应用根地址>/pages 文件夹里的HTML文件pages.html 的源代码。

    b'<html>
    <head>
    <title>A Useful Page</title>
    </head>
    <body>
    <h1>An Interesting Title</h1>
    <div>
    Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
    </div>
    </body>
    </html>
    '

    urllib是Python的标准库,建议读读这个库的Python文档

    1.2 BeautifulSoup

    1.2.1 安装BeautifulSoup

    在Windows系统上安装:

    1、从下载页面下载最新的BeautifulSoup(网址为:http://www.crummy.com/software/BeautifulSoup/

    2、解压到python文件夹下,并切换到...python/beautifulsoup4-4.1.3/目录下

    3、执行:python setup.py install

    4、在python终端里导入测试

    笔者出现了“ cannot import name 'HTMLParseError'”错误

    经过搜索,解决方法如下:

    先卸载掉之前安装的bs4,再用pip命令重新安装。

    PS D:Program Filespython-3.7.4-amd64> pip3 uninstall beautifulsoup4
    Uninstalling beautifulsoup4-4.8.0:
      Would remove:
        d:program filespython-3.7.4-amd64libsite-packageseautifulsoup4-4.8.0-py3.7.egg
    Proceed (y/n)? y
      Successfully uninstalled beautifulsoup4-4.8.0
    PS D:Program Filespython-3.7.4-amd64> pip install beautifulsoup4
    Collecting beautifulsoup4
      Downloading https://files.pythonhosted.org/packages/1a/b7/34eec2fe5a49718944e215fde81288eec1fa04638aa3fb57c1c6cd0f98c3/beautifulsoup4-4.8.0-py3-none-any.whl (97kB)
        100% |████████████████████████████████| 102kB 137kB/s
    Requirement already satisfied: soupsieve>=1.2 in d:program filespython-3.7.4-amd64libsite-packagessoupsieve-1.9.2-py3.7.egg (from beautifulsoup4) (1.9.2)
    Installing collected packages: beautifulsoup4
    Successfully installed beautifulsoup4-4.8.0

    然后,就成功啦。

     1.2.2 运行BeautifulSoup

    把本章开头的例子重新再运行看看:

    from urllib.request import urlopen
    from bs4 import BeautifulSoup
    
    html = urlopen('http://pythonscraping.com/pages/page1.html')
    bs = BeautifulSoup(html.read(),'html.parser')
    print(bs.h1)

    输出结果是:

    <h1>An Interesting Title</h1>

    html.read()获取网页的HTML内容。除了文本字符串,BeautifulSoup还可以使用urlopen直接返回的文件对象,而不需要先调用.read()函数:bs = BeautifulSoup(html.read(),'html.parser')

    下面的所有函数调用都可以产生相同的结果:

    bs.html.body.h1

    bs.body.h1

    bs.html.h1

    当你创建一个BeautifulSoup对象时,需要传入两个参数:第一个参数是该对象所基于的HTML文本,第二个参数指定了你希望BeautifulSoup用来创建该对象的解析器。

    html.parser是python3中的一个解析器,不需要单独安装。

    另一个常用的解析器是lxml,可以通过pip命令安装:pip install lxml

    BeautifulSoup使用lxml解析器时,只需要改变解析器参数:bs = BeautifulSoup(html.read(),'lxml')

    和html.parser相比,lxml的优点在于解析“杂乱”或者包含错误语法的HTML代码的性能更优一些。lxml的一个缺点是它必须单独安装,并且依赖于第三方C语言库。相对于html.parser来说,这可能会导致可移植性和易用性问题。

    另一个常用的HTML解析器是html5lib。和lxml一样,html5lib也是一个具有容错性的解析器。它也以来于外部依赖,并且比lxml和html.parser都慢。

    1.2.3 可靠的网络连接以及异常处理

    html = urlopen('http://pythonscraping.com/pages/page1.html')

    这行代码主要会发生两种异常:

    • 网页在服务器上不存在(或者获取页面的时候出现错误)
    • 服务器不存在

    发生第一种异常时,程序会返回HTTP错误。urlopen函数会抛出HTTPError异常。用下面的方式处理这种异常:

    from urllib.error import HTTPError
    from urllib.request import urlopen
    from bs4 import BeautifulSoup
    
    try:
        html = urlopen('http://pythonscraping.com/pages1/page1.html')
    except HTTPError as e:
        print(e)
        # 返回空值,中断程序,或者执行另一个方案
    else:
        # 程序继续。注意:如果你已经在上面异常捕捉那一段代码里返回或者终端(break),
        # 那么就不需要使用else语句了,这段代码也不会执行
        bs = BeautifulSoup(html.read(),'html.parser')
        print(bs.h1)

    笔者故意将网址写错了,得到下面的结果:

    HTTP Error 404: Not Found

    如果服务器不存在,urlopen会抛出一个URLError异常。这就意味着获取不到服务器,并且由远程服务器负责返回HTTP状态码,所以不能抛出HTTPError异常,而且还应该捕获到更严重的URLError异常。增加以下检查代码:

    from urllib.error import HTTPError
    from urllib.request import urlopen
    from urllib.error import URLError
    from bs4 import BeautifulSoup
    
    try:
        html = urlopen('http://pythonscrapingthisurldoesnotfound.com/pages1/page1.html')
    except HTTPError as e:
        print(e)
    except URLError as e:
        print('The server could not be found!')
    else:
        bs = BeautifulSoup(html.read(),'html.parser')
        print(bs.h1)
    The server could not be found!

    当你调用BeautifulSoup对象里的一个标签时,增加一个检查条件以保证标签确实存在。如果你想调用的标签不存在,BeautifulSoup就会返回None对象。不过,如果调用这个None对象下面的子标签,就会发生AttributerError错误。

    下面这行代码(nonExistenTag是虚拟标签,BeautifulSoup对象里实际没有)

    print(bs.nonExistenTag)

    会返回一个None对象。

    None
    UserWarning: .nonExistenTag is deprecated, use .find("nonExisten") instead. If you really were looking for a tag called nonExistenTag, use .find("nonExistenTag")
      name=tag_name

    处理这个对象是十分必要的。如果你不检查,直接调用这个None对象的子标签,就会很麻烦,如下所示。

     print(bs.nonExistenTag.someTag)

    这时就会返回一个异常:

    AttributeError: 'NoneType' object has no attribute 'someTag'

    为了避免这两种情况,最简单的方式就是对两种情形进行检查:

     try:
            badContent = bs.nonExistingTag.anotherTag
        except AttributeError as e:
            print('Tag was not found')
        else:
            if badContent == None:
                print('Tag was not found')
            else:
                print(badContent)

    重新组织一下代码,让它不那么难写难读:

    from urllib.error import HTTPError
    from urllib.request import urlopen
    from urllib.error import URLError
    from bs4 import BeautifulSoup
    
    def getTitle(url):
        try:
            html = urlopen(url)
        except HTTPError as e:
            return None
        except URLError as e:
            return None
        try:
            bs = BeautifulSoup(html.read(),'html.parser')
            title = bs.body.h1
        except AttributeError as e:
            return None
        return title
    title = getTitle('http://pythonscraping.com/pages/page1.html')
    if title == None:
        print('Title could not found')
    else:
        print(title)

    创建了一个getTitle函数,它可以返回网页的标题,如果获取网页的时候遇到问题就会返回一个None对象。在getTitle函数里面,我们像前面那样检查了HTTPError,黄色标记的是我觉得书上漏掉的,检查URLError错误。然后把两行BeautifulSoup代码封装在一个try语句里。这两行有任意一行有问题都会抛出AttributeError。

  • 相关阅读:
    [ZJOI 2012]数列
    [JSOI 2011]柠檬
    sonar错误及修改方案
    mysql 查询该字段不包含中文
    service 事务
    mysql 不等于和null
    java文件编译为class文件
    主,副时间排序
    MySQL 按首字母排序
    excle导入
  • 原文地址:https://www.cnblogs.com/cathycheng/p/11362528.html
Copyright © 2011-2022 走看看