• 第02章 BeautifulSoup 入门


     

    序言

    1. 内容介绍

    本章详细介绍了BeautifulSoup 的安装、 BeautifulSoup 对象创建、BeautifulSoup 对象相关节点选取等内容。

    2. 理论目标

    • 了解 BeautifulSoup 的安装
    • 了解 BeautifulSoup 对象创建
    • 了解 BeautifulSoup 对象相关节点选取

    3. 实践目标

    • 能掌握 BeautifulSoup 的安装及对象创建,完成网页关键信息选取

    4. 实践案例

    5. 内容目录

    • 1.BeautifulSoup 简介与安装

    • 2.BeautifulSoup 创建及对象种类

    • 3.BeautifulSoup 遍历文档树

    • 4.BeautifulSoup 搜索文档树

    • 5.BeautifulSoup CSS选择器


    第1节 BeautifulSoup 简介与安装

    1. BeautifulSoup 简介

    Beautiful Soup 是一个HTML/XML的解析器,主要的功能也是如何解析和提取 HTML/XML 数据。

    通过解析文档为用户提供需要抓取的数据,已成为和lxml、html6lib 一样出色的python 解释器,为用户灵活地提供不同的解析策略或强劲的速度。

    简单来说,就是把HTML/XML生成规范性文档,方便查找目标元素。

     

    2. BeautifulSoup 安装

    使用 BeautifulSoup,除了安装beautifulsoup4,最好也安装解析器 lxml

    • BeautifulSoup 安装:
    pip install beautifulsoup4
    

    51658daf7f93a500aafa37f23f4d21a3.png

    • 解析器 lxml 安装:
    pip install lxml
    

    c5111d548cf893675b581c9e87305527.png


    第2节 BeautifulSoup 创建及对象种类

    1. BeautifulSoup 创建

     

    ## 导入BeautifulSoup 库,Beautiful Soup 4 已经被移植到 BS4,因此导入时我们需要 import bs4 from bs4 import BeautifulSoup ## 导入html 文档 with open('example.html', 'rb') as f: html = f.read() print(type(html)) bs = BeautifulSoup(html, "lxml") #解析html 文档内容,创建对象 print(bs)

     

    百度一下,你就知道

    b0749bbcc451ce646fd48c45225a023b.png

    • Beautiful Soup 自动将输入文档转换为Unicode编码,输出文档转换为utf-8编码。

    exampe.html 内容

     

    百度一下,你就知道

    2. BeautifulSoup 对象种类

    BeautifulSoup4将复杂HTML文档转换成一个复杂的树形结构,每个节点都是Python对象,所有对象可以归纳为4种:

    1. BeautifulSoup
    2. Tag
    3. NavigableString
    4. Comment

    5c458162d9ba92df9e0baa97fbdbefad.png

    BeautifulSoup

    BeautifulSoup对象表示的是一个文档的内容,可以当作 Tag 对象。

     

    print(bs) print(bs.name) print(type(bs.name)) print(bs.attrs)

     

    百度一下,你就知道

    [document] {}

    Tag

    Tag通俗点讲就是HTML中的一个个标签。

    soup 加标签名轻松地获取这些标签的内容,查找的是在所有内容中的第一个符合要求的标签

     

    # 获取title标签的所有内容 print("这是一个title 标签:\n", bs.title) print("\n") # 获取head标签的所有内容 print("这是一个head 标签:\n", bs.head) print("\n") # 获取第一个a标签的所有内容 print("这是一个a 标签:\n", bs.a) print("\n") # 类型 print("这是一个a 标签的类型:\n", type(bs.a))

     

    这是一个title 标签: 百度一下,你就知道

     

    这是一个head 标签: 百度一下,你就知道

     

    这是一个a 标签:

     

    这是一个a 标签的类型:

    Tag 有两个重要的属性

    • name
    • attrs
     

    # bs 对象本身比较特殊,它的 name 即为 [document] print(bs.name) # 对于内部标签,输出的值便为标签本身的名称 print(bs.head.name) # 打印标签的所有属性,得到的类型是一个字典。 print(bs.a.attrs) # 获取属性内容 print(bs.a['class']) # 等价 bs.a.get('class') # 修改属性和内容,此处修改后就无法获取 bs.a['class'] = "newClass" print(bs.a) # 删除属性 del bs.a['class'] print(bs.a)

    1. [document]
    2. head
    3. {'class': ['mnav'], 'href': 'http://news.baidu.com', 'name': 'tj_trnews'}
    4. ['mnav']
    5. <a class="newClass" href="http://news.baidu.com" name="tj_trnews"><!-- 新闻 --></a>
    6. <a href="http://news.baidu.com" name="tj_trnews"><!-- 新闻 --></a>

    NavigableString

    即标签内部的内容、文字。

     

    ## 获取标签及相应内容 print(bs.title) print(bs.title.string) print("\n类型是:") print(type(bs.title.string))

    1. <title>百度一下,你就知道 </title>
    2. 百度一下,你就知道
    3. 类型是:
    4. <class 'bs4.element.NavigableString'>

    Comment

    Comment 对象是一个特殊类型的NavigableString 对象,其输出的内容不包括注释符号,但包括注释符号里面的内容。

    可以简单认为,如果标签内部的内容、文字是注释内容(文档说明内容),即为Comment,否则为NavigableString(网页内容)。

    如果不处理,可能会对我们的文本处理造成意想不到的麻烦。

     

    # print(bs.a) print(bs.a.string) # 新闻 print(type(bs.a.string)) # print(str(type(bs.a.string)) == "")

    1. <a class="mnav" href="http://news.baidu.com" name="tj_trnews"><!-- 新闻 --></a>
    2. 新闻
    3. <class 'bs4.element.Comment'>
    4. True

    第3节 BeautifulSoup 遍历文档树

    BeautifulSoup 主要提供以下属性遍历文档树

    序号属性作用说明
    1.contents获取Tag的所有子节点,返回一个list
    2.children获取Tag的所有子节点,返回一个生成器
    3.descendants获取Tag的所有子孙节点
    4.strings如果Tag包含多个字符串,即在子孙节点中有内容,可以用此获取,而后进行遍历
    5.stripped_strings与strings用法一致,只不过可以去除掉那些多余的空白内容
    6.parent获取Tag的父节点
    7.parents递归得到父辈元素的所有节点,返回一个生成器
    8.previous_sibling获取当前Tag的上一个节点,属性通常是字符串或空白,真实结果是当前标签与上一个标签之间的顿号和换行符
    10.previous_siblings获取当前Tag的上面所有的兄弟节点,返回一个生成器
    9.next_sibling获取当前Tag的下一个节点,属性通常是字符串或空白,真是结果是当前标签与下一个标签之间的顿号与换行符
    11.next_siblings获取当前Tag的下面所有的兄弟节点,返回一个生成器
    12.previous_element获取解析过程中上一个被解析的对象(字符串或tag),与previous_sibling不同,这里包括不同级的
    14.previous_elements返回一个生成器,可以向前访问文档的解析内容
    13.next_element获取解析过程中下一个被解析的对象(字符串或tag),与next_sibling不同,这里包括不同级的
    15.next_elements返回一个生成器,可以向后访问文档的解析内容
    16.has_attr判断Tag是否包含属性

    1. 子孙标签

     

    print(".contents:获取Tag的所有子节点,返回一个list(含换行符):\n") print(bs.head.contents) print("*"*50 + "此处为分隔符" + "*"*50 + "\n") print(".children:获取Tag的所有子节点,返回一个生成器(含换行符):\n") print(bs.head.children) print("\n遍历结果:") for i in bs.head.children: print(i) print("*"*50 + "此处为分隔符" + "*"*50 + "\n") print(".descendants:获取Tag的所有子孙节点,不同的是,.descendants对所有tag 的子孙节点进行递归循环:\n") print(bs.head.descendants) print("\n遍历结果:") for i in bs.head.descendants: print(i)

    1. .contents:获取Tag的所有子节点,返回一个list(含换行符):
    2. ['\n', <meta content="text/html;charset=utf-8" http-equiv="content-type"/>, '\n', <meta content="IE=Edge" http-equiv="X-UA-Compatible"/>, '\n', <meta content="always" name="referrer"/>, '\n', <link href="https://ss1.bdstatic.com/5eN1bjq8AAUYm2zgoY3K/r/www/cache/bdorz/baidu.min.css" rel="stylesheet" type="text/css"/>, '\n', <title>百度一下,你就知道 </title>, '\n']
    3. *********************************************此处为分隔符*****************************************
    4. .children:获取Tag的所有子节点,返回一个生成器(含换行符):
    5. <list_iterator object at 0x000002388A6CB940>
    6. 遍历结果:
    7. <meta content="text/html;charset=utf-8" http-equiv="content-type"/>
    8. <meta content="IE=Edge" http-equiv="X-UA-Compatible"/>
    9. <meta content="always" name="referrer"/>
    10. <link href="https://ss1.bdstatic.com/5eN1bjq8AAUYm2zgoY3K/r/www/cache/bdorz/baidu.min.css" rel="stylesheet" type="text/css"/>
    11. <title>百度一下,你就知道 </title>
    12. **************************************此处为分隔符*************************************
    13. .descendants:获取Tag的所有子孙节点,不同的是,.descendants对所有tag 的子孙节点进行递归循环:
    14. <generator object Tag.descendants at 0x000002388A6D2970>
    15. 遍历结果:
    16. <meta content="text/html;charset=utf-8" http-equiv="content-type"/>
    17. <meta content="IE=Edge" http-equiv="X-UA-Compatible"/>
    18. <meta content="always" name="referrer"/>
    19. <link href="https://ss1.bdstatic.com/5eN1bjq8AAUYm2zgoY3K/r/www/cache/bdorz/baidu.min.css" rel="stylesheet" type="text/css"/>
    20. <title>百度一下,你就知道 </title>
    21. 百度一下,你就知道

    2. 子孙标签内容(文本内容)

     

    print(".strings:如果Tag包含多个字符串,即在子孙节点中有内容,可以用此获取,而后进行遍历:\n") print(bs.head.strings) print("\n遍历结果:") for i in bs.head.strings: print(i) print("*"*50 + "此处为分隔符" + "*"*50 + "\n") print(".stripped_strings:与strings用法一致,只不过可以去除掉那些多余的空白内容:\n") print(bs.head.stripped_strings) print("\n遍历结果:") for i in bs.head.stripped_strings: print(i)

    1. .strings:如果Tag包含多个字符串,即在子孙节点中有内容,可以用此获取,而后进行遍历:
    2. <generator object Tag._all_strings at 0x000002388A6D2190>
    3. 遍历结果:
    4. 百度一下,你就知道
    5. ******************************************此处为分隔符*****************************************
    6. .stripped_strings:与strings用法一致,只不过可以去除掉那些多余的空白内容:
    7. <generator object Tag.stripped_strings at 0x000002388A6D2190>
    8. 遍历结果:
    9. 百度一下,你就知道

    3. 父标签

     

    print(bs.a) print(".parent:获取Tag的父节点:\n") print(bs.a.parent) print("\n" + "*"*50 + "此处为分隔符" + "*"*50 + "\n") print(".parents:递归得到父辈元素的所有节点,返回一个生成器:\n") print(bs.a.parents) print("\n遍历结果:") n = 1 for i in bs.a.parents: print("第{}个父标签\n".format(str(n))) print(i) n = n + 1

    1. <a class="mnav" href="http://news.baidu.com" name="tj_trnews"><!-- 新闻 --></a>
    2. .parent:获取Tag的父节点:
    3. <div id="u1">
    4. <a class="mnav" href="http://news.baidu.com" name="tj_trnews"><!-- 新闻 --></a>
    5. <a class="mnav" href="https://www.hao123.com" name="tj_trhao123">hao123 </a>
    6. <a class="mnav" href="http://map.baidu.com" name="tj_trmap">地图 </a>
    7. <a class="mnav" href="http://v.baidu.com" name="tj_trvideo">视频 </a>
    8. <a class="mnav" href="http://tieba.baidu.com" name="tj_trtieba">贴吧 </a>
    9. <a class="bri" href="//www.baidu.com/more/" name="tj_briicon" style="display: block;">更多产品 </a>
    10. </div>
    11. *******************************************此处为分隔符*******************************************
    12. .parents:递归得到父辈元素的所有节点,返回一个生成器:
    13. <generator object PageElement.parents at 0x000002388A79AF20>
    14. 遍历结果:
    15. 1个父标签
    16. <div id="u1">
    17. <a class="mnav" href="http://news.baidu.com" name="tj_trnews"><!-- 新闻 --></a>
    18. <a class="mnav" href="https://www.hao123.com" name="tj_trhao123">hao123 </a>
    19. <a class="mnav" href="http://map.baidu.com" name="tj_trmap">地图 </a>
    20. <a class="mnav" href="http://v.baidu.com" name="tj_trvideo">视频 </a>
    21. <a class="mnav" href="http://tieba.baidu.com" name="tj_trtieba">贴吧 </a>
    22. <a class="bri" href="//www.baidu.com/more/" name="tj_briicon" style="display: block;">更多产品 </a>
    23. </div>
    24. 2个父标签
    25. <div class="head_wrapper">
    26. <div id="u1">
    27. <a class="mnav" href="http://news.baidu.com" name="tj_trnews"><!-- 新闻 --></a>
    28. <a class="mnav" href="https://www.hao123.com" name="tj_trhao123">hao123 </a>
    29. <a class="mnav" href="http://map.baidu.com" name="tj_trmap">地图 </a>
    30. <a class="mnav" href="http://v.baidu.com" name="tj_trvideo">视频 </a>
    31. <a class="mnav" href="http://tieba.baidu.com" name="tj_trtieba">贴吧 </a>
    32. <a class="bri" href="//www.baidu.com/more/" name="tj_briicon" style="display: block;">更多产品 </a>
    33. </div>
    34. </div>
    35. ...

    4. 上一个节点

     

    print(".previous_sibling:获取当前Tag的上一个节点,属性通常是字符串或空白,真实结果是当前标签与上一个标签之间的顿号和换行符:\n") print(bs.body.previous_sibling) print("\n" + "*"*50 + "此处为分隔符" + "*"*50 + "\n") print(".previous_siblings:获取当前Tag的上面所有的兄弟节点,返回一个生成器:\n") print(bs.body.previous_siblings) print("\n遍历结果:") n = 1 for i in bs.body.previous_siblings: print("往上数,第{}个同级标签\n".format(str(n))) print(i) n = n + 1

    1. .previous_sibling:获取当前Tag的上一个节点,属性通常是字符串或空白,真实结果是当前标签与上一个标签之间的顿号和换行符:
    2. *********************************************此处为分隔符*********************************************
    3. .previous_siblings:获取当前Tag的上面所有的兄弟节点,返回一个生成器:
    4. <generator object PageElement.previous_siblings at 0x000002388A6D2040>
    5. 遍历结果:
    6. 往上数,第1个同级标签
    7. 往上数,第2个同级标签
    8. <head>
    9. <meta content="text/html;charset=utf-8" http-equiv="content-type"/>
    10. <meta content="IE=Edge" http-equiv="X-UA-Compatible"/>
    11. <meta content="always" name="referrer"/>
    12. <link href="https://ss1.bdstatic.com/5eN1bjq8AAUYm2zgoY3K/r/www/cache/bdorz/baidu.min.css" rel="stylesheet" type="text/css"/>
    13. <title>百度一下,你就知道 </title>
    14. </head>
    15. 往上数,第3个同级标签

    5. 下一个节点

     

    print(".next_sibling:获取当前Tag的下一个节点,属性通常是字符串或空白,真是结果是当前标签与下一个标签之间的顿号与换行符,同级节点:\n") print(bs.a.next_sibling) print("\n" + "*"*50 + "此处为分隔符" + "*"*50 + "\n") print(".next_siblings:获取当前Tag的下面所有的兄弟节点,返回一个生成器:\n") print(bs.a.next_siblings) print("\n遍历结果:") n = 1 for i in bs.a.next_siblings: print("往下数,第{}个同级标签\n".format(str(n))) print(i) n = n + 1

    1. .next_sibling:获取当前Tag的下一个节点,属性通常是字符串或空白,真是结果是当前标签与下一个标签之间的顿号与换行符,同级节点:
    2. **********************************************此处为分隔符**********************************************
    3. .next_siblings:获取当前Tag的下面所有的兄弟节点,返回一个生成器:
    4. <generator object PageElement.next_siblings at 0x000002388A6D2C10>
    5. 遍历结果:
    6. 往下数,第1个同级标签
    7. 往下数,第2个同级标签
    8. <a class="mnav" href="https://www.hao123.com" name="tj_trhao123">hao123 </a>
    9. 往下数,第3个同级标签
    10. 往下数,第4个同级标签
    11. <a class="mnav" href="http://map.baidu.com" name="tj_trmap">地图 </a>
    12. 往下数,第5个同级标签
    13. 往下数,第6个同级标签
    14. <a class="mnav" href="http://v.baidu.com" name="tj_trvideo">视频 </a>
    15. 往下数,第7个同级标签
    16. 往下数,第8个同级标签
    17. <a class="mnav" href="http://tieba.baidu.com" name="tj_trtieba">贴吧 </a>
    18. 往下数,第9个同级标签
    19. 往下数,第10个同级标签
    20. <a class="bri" href="//www.baidu.com/more/" name="tj_briicon" style="display: block;">更多产品 </a>
    21. 往下数,第11个同级标签

    6. 上一个元素

     

    print(".previous_element:获取解析过程中上一个被解析的对象(字符串或tag),与previous_sibling不同的,这里包括不同级的:\n") print(bs.a.previous_element) print("\n" + "*"*50 + "此处为分隔符" + "*"*50 + "\n") print(".previous_elements:返回一个生成器,可以向前访问文档的解析内容:\n") print(bs.a.previous_elements) print("\n遍历结果:") n = 1 for i in bs.a.previous_elements: print("往上数,第{}个元素\n".format(str(n))) print(i) n = n + 1

    1. .previous_element:获取解析过程中上一个被解析的对象(字符串或tag),与previous_sibling不同的,这里包括不同级的:
    2. **********************************************此处为分隔符**********************************************
    3. .previous_elements:返回一个生成器,可以向前访问文档的解析内容:
    4. <generator object PageElement.previous_elements at 0x000002388A6D30B0>
    5. 遍历结果:
    6. 往上数,第1个元素
    7. 往上数,第2个元素
    8. <div id="u1">
    9. <a href="http://news.baidu.com" name="tj_trnews"><!-- 新闻 --></a>
    10. <a class="mnav" href="https://www.hao123.com" name="tj_trhao123">hao123 </a>
    11. <a class="mnav" href="http://map.baidu.com" name="tj_trmap">地图 </a>
    12. <a class="mnav" href="http://v.baidu.com" name="tj_trvideo">视频 </a>
    13. <a class="mnav" href="http://tieba.baidu.com" name="tj_trtieba">贴吧 </a>
    14. <a class="bri" href="//www.baidu.com/more/" name="tj_briicon" style="display: block;">更多产品 </a>
    15. </div>
    16. 往上数,第3个元素
    17. 往上数,第4个元素
    18. ...
    19. 往上数,第27个元素
    20. html

    7. 下一个元素

     

    print(".next_element:获取解析过程中下一个被解析的对象(字符串或tag),可能与next_sibling不同,这里包括不同级的:\n") print(bs.meta.next_element) print("\n" + "*"*50 + "此处为分隔符" + "*"*50 + "\n") print(".next_elements:返回一个生成器,可以向后访问文档的解析内容:\n") print(bs.meta.next_elements) print("\n遍历结果:") n = 1 for i in bs.meta.next_elements: print("往下数,第{}个元素\n".format(str(n))) print(i) n = n + 1

    1. .next_element:获取解析过程中下一个被解析的对象(字符串或tag),可能与next_sibling不同,这里包括不同级的:
    2. **********************************************此处为分隔符**********************************************
    3. .next_elements:返回一个生成器,可以向后访问文档的解析内容:
    4. <generator object PageElement.next_elements at 0x000002388A6D2190>
    5. 遍历结果:
    6. 往下数,第1个元素
    7. 往下数,第2个元素
    8. <meta content="IE=Edge" http-equiv="X-UA-Compatible"/>
    9. 往下数,第3个元素
    10. ...

    8. 属性判断

     

    print(".has_attr:判断Tag是否包含属性:\n") print(bs.a.has_attr("href"))

    1. .has_attr:判断Tag是否包含属性:
    2. True

    第4节 BeautifulSoup 搜索文档树

    BeautifulSoup 通过find_all 和find 对文档树进行搜索。

    uploading.4e448015.gif正在上传…重新上传取消

    1. find_all的使用

    find_all () 方法搜索当前 tag 的所有 tag 子节点,并判断是否符合过滤器的条件。

    • 语法:find_all(name, attrs, recursive, text, **kwargs, limit)

    name 参数

    查找所有名字为 name 的 tag

    1. 字符串过滤:匹配标签名等于字符串的tag,返回tag列表。
     

    a_list = bs.find_all("a") print(a_list)

    [<a href="http://news.baidu.com" name="tj_trnews"><!-- 新闻 --></a>, <a class="mnav" href="https://www.hao123.com" name="tj_trhao123">hao123 </a>, <a class="mnav" href="http://map.baidu.com" name="tj_trmap">地图 </a>, <a class="mnav" href="http://v.baidu.com" name="tj_trvideo">视频 </a>, <a class="mnav" href="http://tieba.baidu.com" name="tj_trtieba">贴吧 </a>, <a class="bri" href="//www.baidu.com/more/" name="tj_briicon" style="display: block;">更多产品 </a>]
    
    1. 正则表达式过滤:匹配标签名符合正则表达式的tag,返回tag列表。
     

    import re pattern = re.compile("^b") a_list = bs.find_all(pattern) print(a_list)

     

    [

    ]

    1. 列表:匹配标签名符合列表中的任一元素的tag,返回tag列表。
     

    a_list = bs.find_all(["a", "meta"]) print(a_list)

     

    [, , , , hao123 , 地图 , 视频 , 贴吧 , 更多产品 ]

    1. 方法:传入一个方法,方法只接受一个元素参数, 如果这个方法返回 True 表示当前元素匹配并且被找到,如果不是则返 False。
     

    ## 校验当前元素,如果包含 class 属性却不包含 id 属性。 def has_class_but_no_id(tag): return tag.has_attr('class') and not tag.has_attr('id') a_list = bs.find_all(has_class_but_no_id) print(a_list)

     

    [

    , hao123 , 地图 , 视频 , 贴吧 , 更多产品 ]

    attrs 参数

    针对部分tag 属性在搜索不能使用,比如 HTML5 中的 data-* 属性。

     

    data_soup = BeautifulSoup('

    foo!
    ') data_list = data_soup.find_all(attrs={"data-foo": "value"}) print(data_list)

     

    [

    foo!
    ]

    recursive 参数

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

     

    a_list = bs.find_all(text="html", recursive=False) print(a_list)

    1. <!DOCTYPE html>
    2. <html>
    3. <head>
    4. <meta content="text/html;charset=utf-8" http-equiv="content-type"/>
    5. <meta content="IE=Edge" http-equiv="X-UA-Compatible"/>
    6. <meta content="always" name="referrer"/>
    7. <link href="https://ss1.bdstatic.com/5eN1bjq8AAUYm2zgoY3K/r/www/cache/bdorz/baidu.min.css" rel="stylesheet" type="text/css"/>
    8. <title>百度一下,你就知道 </title>
    9. </head>
    10. <body link="#0000cc">
    11. <div id="wrapper">
    12. <div id="head">
    13. <div class="head_wrapper">
    14. <div id="u1">
    15. <a class="mnav" href="http://news.baidu.com" name="tj_trnews"><!-- 新闻 --></a>
    16. <a class="mnav" href="https://www.hao123.com" name="tj_trhao123">hao123 </a>
    17. <a class="mnav" href="http://map.baidu.com" name="tj_trmap">地图 </a>
    18. <a class="mnav" href="http://v.baidu.com" name="tj_trvideo">视频 </a>
    19. <a class="mnav" href="http://tieba.baidu.com" name="tj_trtieba">贴吧 </a>
    20. <a class="bri" href="//www.baidu.com/more/" name="tj_briicon" style="display: block;">更多产品 </a>
    21. </div>
    22. </div>
    23. </div>
    24. </div>
    25. </body>
    26. </html>
    27. ['html']
     

    a_list = bs.find_all(text="地图 ", recursive=False) print(a_list)

    []
    

    text 参数

    通过 text 参数可以搜搜文档中的字符串内容

     

    a_list = bs.find_all(text="地图 ") print(a_list)

    ['地图 ']
    

    limit 参数

    find_all() 方法返回全部的搜索结构,使用limit 参数限制返回结果的数量。效果与 SQL 中的 limit 关键字类似。

     

    a_list = bs.find_all("a", limit=2) print(a_list)

    [<a href="http://news.baidu.com" name="tj_trnews"><!-- 新闻 --></a>, <a class="mnav" href="https://www.hao123.com" name="tj_trhao123">hao123 </a>]
    

    **kwargs 参数

    查找属性值符合要求的tag。class 是 python 的关键词,需加个下划线。

     

    ## 单条件 a_list = bs.find_all(id="wrapper") print(a_list)

    1. [<div id="wrapper">
    2. <div id="head">
    3. <div class="head_wrapper">
    4. <div id="u1">
    5. <a href="http://news.baidu.com" name="tj_trnews"><!-- 新闻 --></a>
    6. <a class="mnav" href="https://www.hao123.com" name="tj_trhao123">hao123 </a>
    7. <a class="mnav" href="http://map.baidu.com" name="tj_trmap">地图 </a>
    8. <a class="mnav" href="http://v.baidu.com" name="tj_trvideo">视频 </a>
    9. <a class="mnav" href="http://tieba.baidu.com" name="tj_trtieba">贴吧 </a>
    10. <a class="bri" href="//www.baidu.com/more/" name="tj_briicon" style="display: block;">更多产品 </a>
    11. </div>
    12. </div>
    13. </div>
    14. </div>]
     

    ## 正则表达式匹配 import re pattern = re.compile("baidu.com") a_list = bs.find_all(href=pattern) print(a_list)

    [<a href="http://news.baidu.com" name="tj_trnews"><!-- 新闻 --></a>, <a class="mnav" href="http://map.baidu.com" name="tj_trmap">地图 </a>, <a class="mnav" href="http://v.baidu.com" name="tj_trvideo">视频 </a>, <a class="mnav" href="http://tieba.baidu.com" name="tj_trtieba">贴吧 </a>, <a class="bri" href="//www.baidu.com/more/" name="tj_briicon" style="display: block;">更多产品 </a>]
    
     

    ## 多条件 a_list = bs.find_all(class_="mnav",href="http://news.baidu.com") print(a_list)

    []
    

    2. find的使用

    find() 与 find_all() 方法唯一的区别是 find_all() 方法的返回结果是值包含一个元素的列表,而 find() 方法直接返回去全部结果

    • 语法:find( name , attrs , recursive , text , **kwargs )

    从结果可以看出find_all(),尽管传入了limit=1,但是返回值仍然为一个列表,当我们只需要取一个值时,远不如find()方法方便。但是如果未搜索到值时,将返回一个None。


    第5节 BeautifulSoup CSS选择器

    BeautifulSoup支持发部分的CSS选择器,在Tag获取BeautifulSoup对象的.select()方法中传入字符串参数,即可使用CSS选择器的语法找到Tag,返回类型是 list

    1. 通过标签名查找:标签名
    2. 通过类名查找:.类名
    3. 通过id查找:#id值
    4. 组合查找:多个查找条件组合
    5. 属性查找:标签名[属性名 = ‘属性值’]
    6. 直接子标签查找:父标签名 > 子标签名
    7. 兄弟节点标签查找:标签名 ~ 标签名
    8. 获取内容:.get_text()

    1. 通过标签名查找

     

    a_list = bs.select("a") print(a_list)

    [<a href="http://news.baidu.com" name="tj_trnews"><!-- 新闻 --></a>, <a class="mnav" href="https://www.hao123.com" name="tj_trhao123">hao123 </a>, <a class="mnav" href="http://map.baidu.com" name="tj_trmap">地图 </a>, <a class="mnav" href="http://v.baidu.com" name="tj_trvideo">视频 </a>, <a class="mnav" href="http://tieba.baidu.com" name="tj_trtieba">贴吧 </a>, <a class="bri" href="//www.baidu.com/more/" name="tj_briicon" style="display: block;">更多产品 </a>]
    

    2. 通过类名查找

     

    a_list = bs.select('.mnav') print(a_list)

    [<a class="mnav" href="https://www.hao123.com" name="tj_trhao123">hao123 </a>, <a class="mnav" href="http://map.baidu.com" name="tj_trmap">地图 </a>, <a class="mnav" href="http://v.baidu.com" name="tj_trvideo">视频 </a>, <a class="mnav" href="http://tieba.baidu.com" name="tj_trtieba">贴吧 </a>]
    

    3. 通过id查找

     

    a_list = bs.select('#wrapper') print(a_list)

    1. [<div id="wrapper">
    2. <div id="head">
    3. <div class="head_wrapper">
    4. <div id="u1">
    5. <a href="http://news.baidu.com" name="tj_trnews"><!-- 新闻 --></a>
    6. <a class="mnav" href="https://www.hao123.com" name="tj_trhao123">hao123 </a>
    7. <a class="mnav" href="http://map.baidu.com" name="tj_trmap">地图 </a>
    8. <a class="mnav" href="http://v.baidu.com" name="tj_trvideo">视频 </a>
    9. <a class="mnav" href="http://tieba.baidu.com" name="tj_trtieba">贴吧 </a>
    10. <a class="bri" href="//www.baidu.com/more/" name="tj_briicon" style="display: block;">更多产品 </a>
    11. </div>
    12. </div>
    13. </div>
    14. </div>]

    4. 组合查找

     

    a_list = bs.select('div .mnav') print(a_list)

    [<a class="mnav" href="https://www.hao123.com" name="tj_trhao123">hao123 </a>, <a class="mnav" href="http://map.baidu.com" name="tj_trmap">地图 </a>, <a class="mnav" href="http://v.baidu.com" name="tj_trvideo">视频 </a>, <a class="mnav" href="http://tieba.baidu.com" name="tj_trtieba">贴吧 </a>]
    

    5. 属性查找

     

    a_list = bs.select('div[id="head"]') print(a_list)

    1. [<div id="head">
    2. <div class="head_wrapper">
    3. <div id="u1">
    4. <a href="http://news.baidu.com" name="tj_trnews"><!-- 新闻 --></a>
    5. <a class="mnav" href="https://www.hao123.com" name="tj_trhao123">hao123 </a>
    6. <a class="mnav" href="http://map.baidu.com" name="tj_trmap">地图 </a>
    7. <a class="mnav" href="http://v.baidu.com" name="tj_trvideo">视频 </a>
    8. <a class="mnav" href="http://tieba.baidu.com" name="tj_trtieba">贴吧 </a>
    9. <a class="bri" href="//www.baidu.com/more/" name="tj_briicon" style="display: block;">更多产品 </a>
    10. </div>
    11. </div>
    12. </div>]

    6. 直接子标签查找

     

    a_list = bs.select('div > a') print(a_list)

    [<a href="http://news.baidu.com" name="tj_trnews"><!-- 新闻 --></a>, <a class="mnav" href="https://www.hao123.com" name="tj_trhao123">hao123 </a>, <a class="mnav" href="http://map.baidu.com" name="tj_trmap">地图 </a>, <a class="mnav" href="http://v.baidu.com" name="tj_trvideo">视频 </a>, <a class="mnav" href="http://tieba.baidu.com" name="tj_trtieba">贴吧 </a>, <a class="bri" href="//www.baidu.com/more/" name="tj_briicon" style="display: block;">更多产品 </a>]
    

    7. 兄弟节点标签查找

     

    a_list = bs.select('a ~ a') print(a_list)

    [<a class="mnav" href="https://www.hao123.com" name="tj_trhao123">hao123 </a>, <a class="mnav" href="http://map.baidu.com" name="tj_trmap">地图 </a>, <a class="mnav" href="http://v.baidu.com" name="tj_trvideo">视频 </a>, <a class="mnav" href="http://tieba.baidu.com" name="tj_trtieba">贴吧 </a>, <a class="bri" href="//www.baidu.com/more/" name="tj_briicon" style="display: block;">更多产品 </a>]
    

    8. 获取内容

     

    a_list = bs.select('a') for i in a_list: print(i.get_text())

    1. hao123
    2. 地图
    3. 视频
    4. 贴吧
    5. 更多产品

    开始实验

    第6节 附录

     

     

  • 相关阅读:
    你在终端启动的进程,最后都是什么下场?(下)
    2022前端面试题整理
    看完这篇 教你玩转渗透测试靶机Vulnhub——DriftingBlues-9
    PHP NBA球迷俱乐部系统Dreamweaver开发mysql数据库web结构php编程计算机网页
    美术 3.2 2D动画Spine基础教学
    c#对接webservice接口
    新能源汽车OTA升级中的UDS通信分析
    SpringBoot+MyBatis flex实现简单增删改查
    【面试题】JSON.stringify 和fast-json-stringify有什么区别
    金九银十招聘季, APP测试面试题助你拿高薪Offer
  • 原文地址:https://blog.csdn.net/a1234556667/article/details/126447236