美文网首页
BeautifulSoup的使用姿势

BeautifulSoup的使用姿势

作者: 红烧排骨饭 | 来源:发表于2018-03-05 16:26 被阅读0次

    BeautifulSoup 是什么

    BeautifulSoup库是解析、遍历、维护“标签树”的功能库

    安装

    pip3 install beautifulsoup4
    

    注意:

    在 PyPi 中还有一个名字是 BeautifulSoup 的包,但那可能不是你想要的,那是 Beautiful Soup3 的发布版本,因为很多项目还在使用 BS3, 所以 BeautifulSoup 包依然有效.但是如果你在编写新项目,那么你应该安装的 beautifulsoup4

    HelloWorld

    首先导入包

    from bs4 import BeautifulSoup
    

    BeautifulSoup 可以直接打开文件,并分析文件内容

    soup = BeautifulSoup(open('index.html'), 'html.parser')
    

    也可以直接分析文件内容

    soup = BeautifulSoup('<html>data</html>', 'html.parser')
    

    上面的 html.parser 部分是指定解析器,用来解析文件内容用的。BeautifulSoup 目前有以下几种解析器

    • html.parser
    • lxml
    • xml
    • html5lib

    来演示一个例子。从 https://python123.io/ws/demo.html 上获取网页的 HTML 内容,然后使用 BeautifulSoup 解析

    import requests
    from bs4 import BeautifulSoup
    
    r = requests.get('https://python123.io/ws/demo.html')
    html_text =r.text
    soup = BeautifulSoup(html_text, 'html.parser')
    

    得到 HTML 内容如下

    <html><head><title>This is a python demo page</title></head>
    <body>
    <p class="title"><b>The demo python introduces several python courses.</b></p>
    <p class="course">Python is a wonderful general-purpose programming language. You can learn Python from novice to professional by tracking the following courses:
    <a href="http://www.icourse163.org/course/BIT-268001" class="py1" id="link1">Basic Python</a> and <a href="http://www.icourse163.org/course/BIT-1001870001" class="py2" id="link2">Advanced Python</a>.</p>
    </body></html>
    

    可以使用 prettify() 打印格式化后的 HTML 内容

    print(soup.prettify())
    

    得到

    <html>
     <head>
      <title>
       This is a python demo page
      </title>
     </head>
     <body>
      <p class="title">
       <b>
        The demo python introduces several python courses.
       </b>
      </p>
      <p class="course">
       Python is a wonderful general-purpose programming language. You can learn Python from novice to professional by tracking the following courses:
       <a class="py1" href="http://www.icourse163.org/course/BIT-268001" id="link1">
        Basic Python
       </a>
       and
       <a class="py2" href="http://www.icourse163.org/course/BIT-1001870001" id="link2">
        Advanced Python
       </a>
       .
      </p>
     </body>
    </html>
    

    BeautifulSoup 类的基本元素

    基本元素 类型 说明
    Tag bs4.element.Tag 标签,最基本的信息组织单元,分别用 <> 和 </> 标明开头和结尾
    Name str 标签的名字,<p>...</p> 的名字是 'p',格式 <tag>.name
    Attributes dict 标签的属性,字典组织形式,格式 <tag>.attrs
    NavigableString bs4.element.NavigableString 标签内非属性字符串,<>...</> 中的字符串,格式 <tag>.string
    Comment bs4.element.Comment 标签内字符串的注释部分,一种特殊的 Comment 类型

    用一张图来说明就是

    接着以 https://python123.io/ws/demo.html 获取到的 HTML 内容来解释说明 BeautifulSoup 的基本元素

    Tag标签

    标签,最基本的信息组织单元,分别用 <> 和 </> 标明开头和结尾

    from bs4 import BeautifulSoup
    
    soup = BeautifulSoup(html_text, 'html.parser')
    print(type(soup.title)
    print(soup.title)
    print(soup.title.title)
    print(soup.a)
    

    输出

    <class 'bs4.element.Tag'>
    <title>This is a python demo page</title>
    None
    <a class="py1" href="http://www.icourse163.org/course/BIT-268001" id="link1">Basic Python</a>
    

    任何存在于 HTML 文档中的标签都可以用 soup.<tag> 访问获得
    还可以使用 soup.<tag1>.<tag2> 类似的形式,获取 <tag1> 标签下的 <tag2> 标签
    当 HTML 文档中存在多个相同 <tag> 对应内容时,soup.<tag> 返回第一个

    Tag的name

    标签的名字,<p>…</p> 的名字是'p',格式:<tag>.name

    查看 <a> 标签的名字

    from bs4 import BeautifulSoup
    
    soup = BeautifulSoup(html_text, 'html.parser')
    print(type(soup.a.name))
    print(soup.a.name)
    

    输出

    <class 'str'>
    a
    

    Tag的attrs

    标签的属性,字典形式组织,格式:<tag>.attrs

    from bs4 import BeautifulSoup
    
    soup = BeautifulSoup(html_text, 'html.parser')
    print(type(soup.p.attrs))
    print(soup.p.attrs)
    print(soup.a.attrs)
    

    输出

    <class 'dict'>
    {'class': ['title']}
    {'href': 'http://www.icourse163.org/course/BIT-268001', 'class': ['py1'], 'id': 'link1'}
    

    Tag的NavigableString

    标签内非属性字符串,<>…</> 中字符串,格式:<tag>.string

    from bs4 import BeautifulSoup
    
    soup = BeautifulSoup(html_text, 'html.parser')
    print(type(soup.p.string))
    print(soup.p.string)
    

    输出

    <class 'bs4.element.NavigableString'>
    The demo python introduces several python courses.
    

    Tag的Comment

    from bs4 import BeautifulSoup
    
    html_text = '''
    <b><!--This is a comment--></b>
    <p>This is not a comment</p>
    '''
    soup = BeautifulSoup(html_text, 'html.parser')
    print(soup.b.string)
    print(type(soup.b.string))
    print(soup.p.string)
    print(type(soup.p.string))
    

    输出

    This is a comment
    <class 'bs4.element.Comment'>
    This is not a comment
    <class 'bs4.element.NavigableString'>
    

    可以看到虽然都是调用 <tag>.string 方法获取注视和标签内容,但是两者的类型是不一样的:
    标签的 Comment 是特殊的 NavigableString 类型:bs4.element.Comment

    这个需要在将来的实际应用中特别注意,可以使用 if-else 语句来判断

    if isinstance(tag.string, bs4.element.Comment):
        pass
    else:
        pass
    

    使用BeautifulSoup分析HTML树

    https://python123.io/ws/demo.html 下载到的 HTML 文档内容如下

    <html><head><title>This is a python demo page</title></head>
    <body>
    <p class="title"><b>The demo python introduces several python courses.</b></p>
    <p class="course">Python is a wonderful general-purpose programming language. You can learn Python from novice to professional by tracking the following courses:
    <a href="http://www.icourse163.org/course/BIT-268001" class="py1" id="link1">Basic Python</a> and <a href="http://www.icourse163.org/course/BIT-1001870001" class="py2" id="link2">Advanced Python</a>.</p>
    </body></html>
    

    可以把它理解成一棵树,<html> 标签是根,其他标签接在根下面

    于是,遍历标签树就有这几种方式

    • 下行遍历
    • 上行遍历
    • 平行遍历

    下行遍历

    属性 说明
    .contents 子节点的列表,将 <tag> 所有儿子节点存入列表
    .children 子节点的迭代类型,与 .contents 类似,用于循环遍历儿子节点
    .descendants 子孙节点的迭代类型,包含所有子孙节点,用于循环遍历

    .contents

    查看 head 标签的子节点

    from bs4 import BeautifulSoup
    
    soup = BeautifulSoup(html_text, 'html.parser')
    print(soup.head.contents)
    

    输出

    [<title>This is a python demo page</title>]
    

    查看 body 标签的子节点

    print(soup.body.contents)
    

    输出

    ['\n', <p class="title"><b>
    The demo python introduces several python courses.</b></p>, '\n', <p class="course">Python is a wonderful general-purpose programming language. You can learn Python from novice to professional by tracking the following courses:
    <a class="py1" href="http://www.icourse163.org/course/BIT-268001" id="link1">Basic Python</a> and <a class="py2" href="http://www.icourse163.org/course/BIT-1001870001" id="link2">Advanced Python</a>.</p>, '\n']
    

    可以发现 \n 换行符也当作是一个节点输出了,这个很重要,在 BeautifulSoup 里换行符也当作一个节点看待。比如

    soup = BeautifulSoup('''
    ''', 'html.parser')
    print(soup.contents)
    for child in soup.contents:
        print(type(child))
    

    输出结果是

    ['\n']
    <class 'bs4.element.NavigableString'>
    

    .children

    用法和 .contents 一样,都是遍历节点下的子节点

    soup = BeautifulSoup(html_text, 'html.parser')
    for child in soup.head.children:
        print(child)
    

    输出

    <title>This is a python demo page</title>
    

    .descendants

    查看标签下的子孙节点

    soup = BeautifulSoup(html_text, 'html.parser')
    for child in soup.head.descendants:
        print(child)
    

    输出

    <title>This is a python demo page</title>
    This is a python demo page
    

    可以看到同样是 head 标签,调用 .children 和 调用 .descendants 差别很大。.children 是获取标签下的直接节点,而 .descendants 是获取标签下的子孙节点。同时在 BeautifulSoup 中,字符串也是当作节点看待,所以就输出了

    <title>This is a python demo page</title>
    This is a python demo page
    

    上行遍历

    属性 说明
    .parent 节点的父亲标签
    .parents 节点先辈标签的迭代类型,用于循环遍历先辈节点

    .parent

    print(soup.title.parent)
    print(soup.html.parent)
    print(soup.parent)
    

    分别输出

    <head><title>This is a python demo page</title></head>
    
    <html><head><title>This is a python demo page</title></head>
    <body>
    <p class="title"><b>The demo python introduces several python courses.</b></p>
    <p class="course">Python is a wonderful general-purpose programming language. You can learn Python from novice to professional by tracking the following courses:
    <a href="http://www.icourse163.org/course/BIT-268001" class="py1" id="link1">Basic Python</a> and <a href="http://www.icourse163.org/course/BIT-1001870001" class="py2" id="link2">Advanced Python</a>.</p>
    </body></html>
    
    None
    

    .parents

    for parent in soup.a.parents:
        print(type(parent), parent.name)
    

    输出

    <class 'bs4.element.Tag'> p
    <class 'bs4.element.Tag'> body
    <class 'bs4.element.Tag'> html
    <class 'bs4.BeautifulSoup'> [document]
    

    平行遍历

    属性 说明
    .next_sibling 返回按照HTML文本顺序的下一个平行节点标签
    .previous_sibling 返回按照HTML文本顺序的上一个平行节点标签
    .next_siblings 迭代类型,返回按照HTML文本顺序的后续所有平行节点标签
    .previous_siblings 迭代类型,返回按照HTML文本顺序的前续所有平行节点标签

    需要注意,平行遍历,是发生在同一个父节点下的各节点间

    遍历方式总结

    查找节点

    查找节点常用的方法有以下两个

    • find( name , attrs , recursive , text , **kwargs )
    • find_all( name , attrs , recursive , text , **kwargs )

    find:查找第一个符合要求的节点
    find_all:查找所有符合要求的节点

    下面几个常用的例子

    找到第一个 <a> 标签

    a = soup.find('a')
    print(a)
    

    输出

    <a class="py1" href="http://www.icourse163.org/course/BIT-268001" id="link1">Basic Python</a>
    

    找到所有 <a> 标签

    for a in soup.find_all('a'):
        print(a)
    

    输出

    <a class="py1" href="http://www.icourse163.org/course/BIT-268001" id="link1">Basic Python</a>
    <a class="py2" href="http://www.icourse163.org/course/BIT-1001870001" id="link2">Advanced Python</a>
    

    查找 class 属性值为 py1 的标签

    a = soup.find('a', {'class': 'py1'})
    print(a)
    

    输出

    <a class="py1" href="http://www.icourse163.org/course/BIT-268001" id="link1">Basic Python</a>
    

    查找所有以 p 字母开头的标签

    import re
    
    for tag in soup.find_all(re.compile(r'^p')):
        print(tag.name)
    

    输出

    p
    p
    

    查找所有 href 属性为 http://www.icourse163.org/course/ 开头的 a 标签

    import re
    
    for tag in soup.find_all('a', {'href': re.compile(r'^http://www.icourse163.org/course/.+')}):
        print(tag)
    

    输出

    <a class="py1" href="http://www.icourse163.org/course/BIT-268001" id="link1">Basic Python</a>
    <a class="py2" href="http://www.icourse163.org/course/BIT-1001870001" id="link2">Advanced Python</a>
    

    总结

    使用方法

    from bs4 import BeautifulSoup
    
    soup = BeautifulSoup(html_text, 'html.parser')
    

    基本元素

    • Tag
    • name
    • attrs
    • NavigableString
    • Comment

    遍历方式

    1. 下行遍历
    2. 上行遍历
    3. 平行遍历

    查找节点

    • find
    • find_all

    相关文章

      网友评论

          本文标题:BeautifulSoup的使用姿势

          本文链接:https://www.haomeiwen.com/subject/tmhhfftx.html