本章详细介绍了BeautifulSoup 的安装、 BeautifulSoup 对象创建、BeautifulSoup 对象相关节点选取等内容。
无
1.BeautifulSoup 简介与安装
2.BeautifulSoup 创建及对象种类
3.BeautifulSoup 遍历文档树
4.BeautifulSoup 搜索文档树
5.BeautifulSoup CSS选择器
Beautiful Soup 是一个HTML/XML的解析器,主要的功能也是如何解析和提取 HTML/XML 数据。
通过解析文档为用户提供需要抓取的数据,已成为和lxml、html6lib 一样出色的python 解释器,为用户灵活地提供不同的解析策略或强劲的速度。
简单来说,就是把HTML/XML生成规范性文档,方便查找目标元素。
使用 BeautifulSoup,除了安装beautifulsoup4,最好也安装解析器 lxml
pip install beautifulsoup4
pip install lxml
## 导入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)
exampe.html 内容
BeautifulSoup4将复杂HTML文档转换成一个复杂的树形结构,每个节点都是Python对象,所有对象可以归纳为4种:
BeautifulSoup
BeautifulSoup对象表示的是一个文档的内容,可以当作 Tag 对象。
print(bs) print(bs.name) print(type(bs.name)) print(bs.attrs)
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 标签的类型:
Tag 有两个重要的属性
# 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)
- [document]
- head
- {'class': ['mnav'], 'href': 'http://news.baidu.com', 'name': 'tj_trnews'}
- ['mnav']
- <a class="newClass" href="http://news.baidu.com" name="tj_trnews"><!-- 新闻 --></a>
- <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))
- <title>百度一下,你就知道 </title>
- 百度一下,你就知道
-
- 类型是:
- <class 'bs4.element.NavigableString'>
Comment
Comment 对象是一个特殊类型的NavigableString 对象,其输出的内容不包括注释符号,但包括注释符号里面的内容。
可以简单认为,如果标签内部的内容、文字是注释内容(文档说明内容),即为Comment,否则为NavigableString(网页内容)。
如果不处理,可能会对我们的文本处理造成意想不到的麻烦。
# print(bs.a) print(bs.a.string) # 新闻 print(type(bs.a.string)) #
- <a class="mnav" href="http://news.baidu.com" name="tj_trnews"><!-- 新闻 --></a>
- 新闻
- <class 'bs4.element.Comment'>
- True
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是否包含属性 |
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)
- .contents:获取Tag的所有子节点,返回一个list(含换行符):
-
- ['\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']
- *********************************************此处为分隔符*****************************************
-
- .children:获取Tag的所有子节点,返回一个生成器(含换行符):
-
- <list_iterator object at 0x000002388A6CB940>
-
- 遍历结果:
- <meta content="text/html;charset=utf-8" http-equiv="content-type"/>
- <meta content="IE=Edge" http-equiv="X-UA-Compatible"/>
- <meta content="always" name="referrer"/>
- <link href="https://ss1.bdstatic.com/5eN1bjq8AAUYm2zgoY3K/r/www/cache/bdorz/baidu.min.css" rel="stylesheet" type="text/css"/>
- <title>百度一下,你就知道 </title>
- **************************************此处为分隔符*************************************
-
- .descendants:获取Tag的所有子孙节点,不同的是,.descendants对所有tag 的子孙节点进行递归循环:
-
- <generator object Tag.descendants at 0x000002388A6D2970>
-
- 遍历结果:
- <meta content="text/html;charset=utf-8" http-equiv="content-type"/>
- <meta content="IE=Edge" http-equiv="X-UA-Compatible"/>
- <meta content="always" name="referrer"/>
- <link href="https://ss1.bdstatic.com/5eN1bjq8AAUYm2zgoY3K/r/www/cache/bdorz/baidu.min.css" rel="stylesheet" type="text/css"/>
- <title>百度一下,你就知道 </title>
- 百度一下,你就知道
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)
- .strings:如果Tag包含多个字符串,即在子孙节点中有内容,可以用此获取,而后进行遍历:
-
- <generator object Tag._all_strings at 0x000002388A6D2190>
-
- 遍历结果:
- 百度一下,你就知道
- ******************************************此处为分隔符*****************************************
-
- .stripped_strings:与strings用法一致,只不过可以去除掉那些多余的空白内容:
-
- <generator object Tag.stripped_strings at 0x000002388A6D2190>
-
- 遍历结果:
- 百度一下,你就知道
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
- <a class="mnav" href="http://news.baidu.com" name="tj_trnews"><!-- 新闻 --></a>
- .parent:获取Tag的父节点:
-
- <div id="u1">
- <a class="mnav" 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>
- </div>
-
- *******************************************此处为分隔符*******************************************
- .parents:递归得到父辈元素的所有节点,返回一个生成器:
- <generator object PageElement.parents at 0x000002388A79AF20>
- 遍历结果:
- 第1个父标签
- <div id="u1">
- <a class="mnav" 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>
- </div>
- 第2个父标签
- <div class="head_wrapper">
- <div id="u1">
- <a class="mnav" 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>
- </div>
- </div>
- ...
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
- .previous_sibling:获取当前Tag的上一个节点,属性通常是字符串或空白,真实结果是当前标签与上一个标签之间的顿号和换行符:
- *********************************************此处为分隔符*********************************************
-
- .previous_siblings:获取当前Tag的上面所有的兄弟节点,返回一个生成器:
-
- <generator object PageElement.previous_siblings at 0x000002388A6D2040>
-
- 遍历结果:
- 往上数,第1个同级标签
-
- 往上数,第2个同级标签
-
- <head>
- <meta content="text/html;charset=utf-8" http-equiv="content-type"/>
- <meta content="IE=Edge" http-equiv="X-UA-Compatible"/>
- <meta content="always" name="referrer"/>
- <link href="https://ss1.bdstatic.com/5eN1bjq8AAUYm2zgoY3K/r/www/cache/bdorz/baidu.min.css" rel="stylesheet" type="text/css"/>
- <title>百度一下,你就知道 </title>
- </head>
- 往上数,第3个同级标签
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
- .next_sibling:获取当前Tag的下一个节点,属性通常是字符串或空白,真是结果是当前标签与下一个标签之间的顿号与换行符,同级节点:
- **********************************************此处为分隔符**********************************************
-
- .next_siblings:获取当前Tag的下面所有的兄弟节点,返回一个生成器:
-
- <generator object PageElement.next_siblings at 0x000002388A6D2C10>
-
- 遍历结果:
- 往下数,第1个同级标签
- 往下数,第2个同级标签
-
- <a class="mnav" href="https://www.hao123.com" name="tj_trhao123">hao123 </a>
- 往下数,第3个同级标签
- 往下数,第4个同级标签
-
- <a class="mnav" href="http://map.baidu.com" name="tj_trmap">地图 </a>
- 往下数,第5个同级标签
- 往下数,第6个同级标签
-
- <a class="mnav" href="http://v.baidu.com" name="tj_trvideo">视频 </a>
- 往下数,第7个同级标签
- 往下数,第8个同级标签
-
- <a class="mnav" href="http://tieba.baidu.com" name="tj_trtieba">贴吧 </a>
- 往下数,第9个同级标签
- 往下数,第10个同级标签
-
- <a class="bri" href="//www.baidu.com/more/" name="tj_briicon" style="display: block;">更多产品 </a>
- 往下数,第11个同级标签
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
- .previous_element:获取解析过程中上一个被解析的对象(字符串或tag),与previous_sibling不同的,这里包括不同级的:
- **********************************************此处为分隔符**********************************************
-
- .previous_elements:返回一个生成器,可以向前访问文档的解析内容:
-
- <generator object PageElement.previous_elements at 0x000002388A6D30B0>
-
- 遍历结果:
- 往上数,第1个元素
- 往上数,第2个元素
-
- <div id="u1">
- <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>
- </div>
- 往上数,第3个元素
- 往上数,第4个元素
- ...
- 往上数,第27个元素
-
- html
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
- .next_element:获取解析过程中下一个被解析的对象(字符串或tag),可能与next_sibling不同,这里包括不同级的:
- **********************************************此处为分隔符**********************************************
-
- .next_elements:返回一个生成器,可以向后访问文档的解析内容:
-
- <generator object PageElement.next_elements at 0x000002388A6D2190>
-
- 遍历结果:
- 往下数,第1个元素
- 往下数,第2个元素
-
- <meta content="IE=Edge" http-equiv="X-UA-Compatible"/>
- 往下数,第3个元素
- ...
print(".has_attr:判断Tag是否包含属性:\n") print(bs.a.has_attr("href"))
- .has_attr:判断Tag是否包含属性:
-
- True
BeautifulSoup 通过find_all 和find 对文档树进行搜索。
正在上传…重新上传取消
find_all () 方法搜索当前 tag 的所有 tag 子节点,并判断是否符合过滤器的条件。
name 参数
查找所有名字为 name 的 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>]
import re pattern = re.compile("^b") a_list = bs.find_all(pattern) print(a_list)
[ ]
a_list = bs.find_all(["a", "meta"]) print(a_list)
[, , , , hao123 , 地图 , 视频 , 贴吧 , 更多产品 ]
## 校验当前元素,如果包含 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('
[
recursive 参数
调用 tag 的 find_all() 方法时,Beautiful Soup 会检索当前 tag 的所有子孙节点,如果只想搜索 tag 的直接子节点,可以使用参数 recursive=False。
a_list = bs.find_all(text="html", recursive=False) print(a_list)
- <!DOCTYPE html>
- <html>
- <head>
- <meta content="text/html;charset=utf-8" http-equiv="content-type"/>
- <meta content="IE=Edge" http-equiv="X-UA-Compatible"/>
- <meta content="always" name="referrer"/>
- <link href="https://ss1.bdstatic.com/5eN1bjq8AAUYm2zgoY3K/r/www/cache/bdorz/baidu.min.css" rel="stylesheet" type="text/css"/>
- <title>百度一下,你就知道 </title>
- </head>
- <body link="#0000cc">
- <div id="wrapper">
- <div id="head">
- <div class="head_wrapper">
- <div id="u1">
- <a class="mnav" 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>
- </div>
- </div>
- </div>
- </div>
- </body>
- </html>
- ['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)
- [<div id="wrapper">
- <div id="head">
- <div class="head_wrapper">
- <div id="u1">
- <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>
- </div>
- </div>
- </div>
- </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)
[]
find() 与 find_all() 方法唯一的区别是 find_all() 方法的返回结果是值包含一个元素的列表,而 find() 方法直接返回去全部结果
从结果可以看出find_all(),尽管传入了limit=1,但是返回值仍然为一个列表,当我们只需要取一个值时,远不如find()方法方便。但是如果未搜索到值时,将返回一个None。
BeautifulSoup支持发部分的CSS选择器,在Tag获取BeautifulSoup对象的.select()方法中传入字符串参数,即可使用CSS选择器的语法找到Tag,返回类型是 list
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>]
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>]
a_list = bs.select('#wrapper') print(a_list)
- [<div id="wrapper">
- <div id="head">
- <div class="head_wrapper">
- <div id="u1">
- <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>
- </div>
- </div>
- </div>
- </div>]
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>]
a_list = bs.select('div[id="head"]') print(a_list)
- [<div id="head">
- <div class="head_wrapper">
- <div id="u1">
- <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>
- </div>
- </div>
- </div>]
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>]
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>]
a_list = bs.select('a') for i in a_list: print(i.get_text())
- hao123
- 地图
- 视频
- 贴吧
- 更多产品
开始实验