小白学Python---bs4操作

下面的一段HTML代码将作为例子

html_doc = """
<html><head><title>The Dormouse's story</title></head>
<body>
<p class="title"><b>The Dormouse's story</b></p>

<p class="story">Once upon a time there were three little sisters; and their names were
<a href="http://example.com/elsie" class="sister" id="link1">Elsie</a>,
<a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> and
<a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>;
and they lived at the bottom of a well.</p>

<p class="story">...</p>
"""
  1. prettify() 将一个bs对象按照标准格式进行格式化输出
from bs4 import BeautifulSoup
soup = BeautifulSoup(html_doc)
print(soup.prettify())
  1. 几个简单的浏览结构化的方法

    • soup.标签:找出第一个该类标签
    print(soup.title)
    # <title>The Dormouse's story</title>
    
    • soup.标签.name:获取tag的name属性值
    	print(soup.title.name)
    	# title
    
    • soup.title.text 和 soup.title.string 的区别:
    print(soup.title.text)
    print(type(soup.title.text))
    print(soup.title.string)
    print(type(soup.title.string))
    # The Dormouse's story
    # <class 'str'>
    # The Dormouse's story
    # <class 'bs4.element.NavigableString'>
    
    • find_all() 和 find():前者返回符合条件的标签列表,后者返回一个bs4的tag对象
    • soup.get_text() 获取文档中的所有的文字内容
  2. tag标签属性值的操作

    • 获取属性值:获取文档中第一个p标签的所有class属性,返回list,转换的文档是XML格式,那么tag中不包含多值属性
    print(soup.p.get('class'))
    print(soup.p.attrs['class'])
    print(soup.p['class'])
    #['title']
    #['title']
    #['title']
    
    • 添加、修改属性、删除属性:
    soup.b['class'] = 'content'
    print(soup.b)
    #<b class="content">The Dormouse's story</b>
    soup.b['class'] = 'text'
    print(soup.b)
    #<b class="text">The Dormouse's story</b>
    del soup.b['class']
    print(soup.b)
    #<b>The Dormouse's story</b>
    
  3. 子节点

    • .contents 属性可以将tag的直接子节点以列表的方式输出
    print(soup.head.contents)
    # [<title>The Dormouse's story</title>]
    
    • .children 生成器,可以对tag的直接子节点进行循环
    for j in soup.head.children:
        print(j)
    #<title>The Dormouse's story</title>
    for i in soup.title.children:
        print(i)
    #The Dormouse's story
    
    • .descendants 属性可以对所有tag的子孙节点进行递归循环
    for k in soup.head.descendants:
    	print(k)
    # <title>The Dormouse's story</title>
    # The Dormouse's story
    
    • .string 和 .strings stripped_strings:tag只有一个 NavigableString 类型子节点,那么这个tag可以使用 .string 得到子节点;tag中包含多个字符串 [2] ,可以使用 .strings 来循环获取;输出的字符串中可能包含了很多空格或空行,使用 .stripped_strings 可以去除多余空白内容;
  4. 父节点

    • .parent:
    <head>标签是<title>标签的父节点;
    文档title的字符串也有父节点:<title>标签;
    文档的顶层节点比如<html>的父节点是 BeautifulSoup 对象;
    BeautifulSoup 对象的 .parent 是None;
    
    • .parents:通过元素的 .parents 属性可以递归得到元素的所有父辈节点,下面的例子使用了 .parents 方法遍历了<a>标签到根节点的所有节点.
    for parent in soup.a.parents:
    	print(parent.name)
    #p
    #body
    #html
    #[document]
    
  5. 兄弟节点

    • .next_sibling 和 .previous_sibling:<>标签有 .next_sibling 属性,但是没有 .previous_sibling 属性,因为<>标签在同级节点中是第一个.同理,<c>标签有 .previous_sibling 属性,却没有 .next_sibling 属性:
    sibling_soup = BeautifulSoup('<a><b>text1</b><c>text2</c></b></a>')
    
    • 在html_doc文档中,第一个<a>标签的.next_sibling结果不是第二个标签,而是','
    • 通过 .next_siblings 和 .previous_siblings 属性可以对当前节点的兄弟节点迭代输出;
  6. 搜索文档树

    • 过滤器
      -- 字符串
    soup.find_all('b') 找出所有的<b>标签
    

    -- 正则表达式

    soup.find_all(re.compile("^b")) 找出所有以b开头的标签,例子中<body>和<b>都能被找到
    soup.find_all(re.comile("t")) 找出所有标签中包含't'的标签
    

    -- 列表

    soup.find_all(["a", "b"]) 找到文档中所有<a>标签和<b>标签
    

    -- True

    soup.find_all(True) True:可以匹配任何值,下面代码查找到所有的tag,但是不会返回字符串节点
    

    -- 方法

    以下方法找出包含 class 属性却不包含 id 属性的标签:

    def has_class_but_no_id(tag):
    	return tag.has_attr('class') and not tag.has_attr('id')
    print(soup.find_all(has_class_but_no_id))
    # [<p class="title content"><b>The Dormouse's story</b></p>, <p class="story">Once upon a # time there were three little sisters; and their names were
    # <a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>,
    # <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a> and
    # <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>;
    # and they lived at the bottom of a well.</p>, <p class="story">...</p>]
    
    • find_all
    -- find_all( name , attrs , recursive , text , **kwargs )
    soup.find_all("p", "title")
    # [<p class="title"><b>The Dormouse's story</b></p>]
    soup.find_all(href=re.compile("elsie"), id='link1')
    # [<a class="sister" href="http://example.com/elsie" id="link1">three</a>]
    

    -- 特殊属性的搜索

    data_soup = BeautifulSoup('<div data-foo="value">foo!</div>')
    data_soup.find_all(data-foo="value")
    # SyntaxError: keyword can't be an expression
    data_soup.find_all(attrs={"data-foo": "value"})
    # [<div data-foo="value">foo!</div>]
    

    -- 按CSS搜索
    class 在Python中是保留字,使用 class 做参数会导致语法错误.从Beautiful Soup的4.1.1版本开始,可以通过 class_ 参数搜索有指定CSS类名的tag:

    print(soup.find_all("a", class_="sister"))
    # [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>,
    #  <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>,
    #  <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]
    

    -- text参数
    class 在Python中是保留字,使用 class 做参数会导致语法错误.从Beautiful Soup的4.1.1版本开始,可以通过 class_ 参数搜索有指定CSS类名的tag:

    print(soup.find_all(text="Elsie"))
    # ['Elsie']
    

    -- limit参数

    soup.find_all("a", limit=2)
    # [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>,
    #  <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>]
    

    -- recursive 参数
    调用tag的 find_all() 方法时,Beautiful Soup会检索当前tag的所有子孙节点,如果只想搜索tag的直接子节点,可以使用参数 recursive=False :

    soup.html.find_all("title")
    # [<title>The Dormouse's story</title>]
    soup.html.find_all("title", recursive=False)
    # []
    
    • Beautiful Soup中还有10个用于搜索的API.它们中的五个用的是与 find_all() 相同的搜索参数,另外5个与 find() 方法的搜索参数类似.区别仅是它们搜索文档的不同部分.记住: find_all() 和 find() 只搜索当前节点的所有子节点,孙子节点等. find_parents() 和 find_parent() 用来搜索当前节点的父辈节点,搜索方法与普通tag的搜索方法相同,搜索文档搜索文档包含的内容. 我们从一个文档中的一个叶子节点开始.

    • CSS选择器
      Beautiful Soup支持大部分的CSS选择器,在 Tag 或 BeautifulSoup 对象的 .select() 方法中传入字符串参数,即可使用CSS选择器的语法找到tag:

      -- 通过tag标签逐层查找:

    soup.select("html head title")
    # [<title>The Dormouse's story</title>]
    

    -- 找到某个tag标签下的直接子标签:

    soup.select("head > title")
    # [<title>The Dormouse's story</title>]
    
    soup.select("p > a")
    # [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>,
    #  <a class="sister" href="http://example.com/lacie"  id="link2">Lacie</a>,
    #  <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]
    
    soup.select("p > a:nth-of-type(2)")
    # [<a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>]
    
    soup.select("p > #link1")
    # [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>]
    soup.select("body > a")
    # []
    

    -- 找到兄弟节点标签:(所有兄弟和直系兄弟)

    soup.select("#link1 ~ .sister")
    	# [<a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>,
    	#  <a class="sister" href="http://example.com/tillie"  id="link3">Tillie</a>]
    soup.select("#link1 + .sister")
    	# [<a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>]
    

    -- 通过CSS的类名查找:

    soup.select(".sister")
    	# [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>,
    	#  <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>,
    	#  <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]
    soup.select("[class~=sister]")
    	# [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>,
    	#  <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>,
    	#  <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]
    

    -- 通过tag的id查找:

    soup.select("#link1")
    	# [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>]
    soup.select("a#link2")
    	# [<a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>]
    

    -- 通过是否存在某个属性来查找:

    soup.select('a[href]')
    	# [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>,
    	#  <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>,
    	#  <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]
    

    -- 通过属性的值来查找:

    soup.select('a[href="http://example.com/elsie"]')
    	# [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>]
    soup.select('a[href^="http://example.com/"]')
    	# [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>,
    	#  <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>,
    	#  <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]
    soup.select('a[href$="tillie"]')
    	# [<a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]
    soup.select('a[href*=".com/el"]')
    	# [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>]
    
原文地址:https://www.cnblogs.com/bbszc520/p/9154087.html