Python爬虫:BeautifulSoup库
Beautiful Soup的简介
Beautiful Soup是python的一个库,最主要的功能是从网页抓取数据。官方解释如下:
1、Beautiful Soup提供一些简单的、python式的函数用来处理导航、搜索、修改分析树等功能。它是一个工具箱,通过解析文档为用户提供需要抓取的数据,因为简单,所以不需要多少代码就可以写出一个完整的应用程序
2、Beautiful Soup自动将输入文档转换为Unicode编码,输出文档转换为utf-8编码。你不需要考虑编码方式,除非文档没有指定一个编码方式,这时,Beautiful Soup就不能自动识别编码方式了。然后,你仅仅需要说明一下原始编码方式就可以了
3、Beautiful Soup已成为和lxml、html6lib一样出色的python解释器,为用户灵活地提供不同的解析策略或强劲的速度
安装BeautifulSoup
1、BeautifulSoup4通过PyPi发布,所以如果你无法使用系统包管理安装,那么也可以通过easy_install或pip来安装。包的名字是beautifulsoup4这个包兼容Python2和Python3
2、 pip install BeautifulSoup4==4.0.1
安装解析器
1、Beautiful Soup支持Python标准库中的HTML解析器,还支持一些第三方的解析器。其中一个是lxml
2、根据操作系统不同,可以选择pip方法来安装lxml:pip install lxml
各种解析器优缺点
Beautiful Soup支持Python标准库中的HTML解析器,还支持一些第三方的解析器,如果我们不安装它,则 Python 会使用 Python默认的解析器,lxml 解析器更加强大,速度更快,推荐安装(pip install lxml)
解析器 | 使用方法 | 优势 | 劣势 |
Python标准库 | BeautifulSoup(markup, “html.parser”) | Python的内置标准库、执行速度适中、文档容错能力强 | Python 2.7.3 or 3.2.2)前 的版本中文档容错能力差 |
lxml HTML 解析器 | BeautifulSoup(markup, “lxml”) | 速度快、文档容错能力强 | 需要安装C语言库 |
lxml XML 解析器 | BeautifulSoup(markup, [“lxml”, “xml”])或BeautifulSoup(markup, “xml”) | 速度快、唯一支持XML的解析器 | 需要安装C语言库 |
html5lib | BeautifulSoup(markup, “html5lib”) | 最好的容错性、以浏览器的方式解析文档、生成HTML5格式的文档、不依赖外部扩展 | 速度慢 |
BeautifulSoup简介
1、将一段文档传入BeautifulSoup 的构造方法,就能得到一个文档的对象(beautifulsoup对象)。同时也可以传入一段字符串或一个文件句柄
2、首先,文档被转换成Unicode,并且HTML的实例都被转换成Unicode编码
3、然后Beautiful Soup选择最合适的解析器来解析这段文档,如果手动指定解析器,那么Beautiful Soup会选择指定的解析器来解析文档
例1:
from bs4 import BeautifulSoup #导入bs4库html = """
<html><head><title>The Dormouse's story</title></head> <body> <p class="title" name="dromouse"><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></body>
</html>
"""soup = BeautifulSoup(html,"lxml")#指定解析器,返回一个beautifulsoup对象print(type(soup))HTML_prettify = soup.prettify() #打印一下soup对象的内容,格式化输出
print(HTML_prettify)"""
<class 'bs4.BeautifulSoup'>
<html><head><title>The Dormouse's story</title></head><body><p class="title" name="dromouse"><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></body>
</html>
"""
例1_1:使用HTML文件来创建beautifulsoup对象
from bs4 import BeautifulSouphtml = open("F:\\test.txt","r",encoding="utf-8")
soup = BeautifulSoup(html,features="lxml") #将本地文件打开,用它来创建soup对象
注:
1、BeautifulSoup()方法返回的是一个bs4.BeautifulSoup对象,我们可以根据这个对象来使用不同的方法来获得HTML中我们需要的数据
2、在BeautifulSoup()方法中感觉最好指定解析器(使用lxml解析器),不然有时候会报错
3、上面例子中使用了prettify()方法:该方法用于格式化打印出获得的内容。这个函数经常用到所以要记住了
四大对象种类
Beautiful Soup将复杂HTML文档转换成一个复杂的树形结构,每个节点都是Python对象,所有对象可以归纳为4种:
对象名 | 描述 |
BeautifulSoup | 文档自身:表示的是一个文档的全部内容 |
Tag | 标签对:Tag对象与XML或HTML原生文档中的tag相同,即标签对 |
NavigableString | 标签值:标签对中的字符串 |
Comment | 注释:文档的注释部分 |
Tag对象
1、Tag即HTML或XML中的标签对:Tag对象与XML或HTML原生文档中的tag相同
2、HTML中tag是由尖括号包围的关键词,即HTML中的一个个标签。一般是成对出现的。比如<p>和</p>
3、成对的tag里,第一个(不带"/"的)叫开始tag(又叫开放tag),第二个叫结束tag(又叫闭合tag)
4、例如:<title>The Dormouse's story</title>或<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>
⑴上面的title、a等等HTML标签加上里面包括的内容就是Tag
⑵在BeautifulSoup中可以利用beautifulsoup对象下面的方法返回这些标签数据,这些标签数据称为Tag对象(Tag对象指的是整个标签对:从开始标签到结束标签,包括里面的嵌套标签)
⑶获取到Tag对象后,可以继续使用其下面的属性(方法)来获取标签对中的具体数据
5、Tag有很多方法和属性,暂时先介绍一下tag对象中最重要的属性:name属性和attributes属性
获取Tag对象
1、从一个beautifulsoup对象中获取指定的Tag对象,可以使用:beautifulsoup对象.标签名
⑴要获取哪个标签的Tag对象,就传入哪个标签的标签名
2、注:这种方法返回的Tag对象是所有内容中第一个符合要求的标签
⑴即:文档中存在多个同名的标签时,使用"beautifulsoup对象.标签名"返回的始终是第一个符合的标签(至于查找所有符合要求的标签,后面介绍)
例2:
from bs4 import BeautifulSoup #导入bs4库html = """
<html><head><title>The Dormouse's story</title></head>
<body>
<p class="title" name="dromouse"><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>
"""soup = BeautifulSoup(html,"lxml")#指定解析器
HTML_title = soup.title #获取title标签
print("获取到的title标签为:",HTML_title)HTML_head = soup.head #获取header标签
print("获取到的header标签为:",HTML_head)HTML_a = soup.a #获取a标签
print("获取到的a标签为:",HTML_a)HTML_p = soup.p #获取p标签
print("获取到的p标签为:",HTML_p)
print("获取到的p标签类型为:",type(HTML_p))"""
获取到的title标签为: <title>The Dormouse's story</title>
获取到的header标签为: <head><title>The Dormouse's story</title></head>
获取到的a标签为: <a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>
获取到的p标签为: <p class="title" name="dromouse"><b>The Dormouse's story</b></p>
获取到的p标签类型为: <class 'bs4.element.Tag'>
"""
注:
1、从上面例子中我们可以看出:可以使用soup对象加标签名轻松地获取这些标签的内容,返回的标签是一个" <class 'bs4.element.Tag'>",即Tag对象
2、不过需要注意的是:它查找的是在所有内容中的第一个符合要求的标签,如果要查询所有符合要求的标签,我们在后面进行介绍
tag对象的name属性
1、每个tag都有自己的名字,其成为tag对象的name属性(name属性:标签对的名称)
2、获取一个Tag对象的name属性,可以使用:Tag对象.name
例3:
from bs4 import BeautifulSoup #导入bs4库html = """
<html><head><title>The Dormouse's story</title></head>
<body>
<p class="title" name="dromouse"><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>
"""soup = BeautifulSoup(html,"lxml") #指定解析器
soup_tag_name = soup.name #获取整个BeautifulSoup对象的name属性
title_tag_name = soup.title.name #获取title标签对象的name属性
head_tag_name = soup.head.name #获取head标签对象的name属性
a_tag = soup.a #获取a标签对象
a_tag_name = a_tag.name #获取a标签对象的name属性print("整个BeautifulSoup对象的name属性为:",soup_tag_name)
print("title标签对象的name属性为:",title_tag_name)
print("header标签对象的name属性为:",head_tag_name)
print("a标签对象为:",a_tag)
print("a标签对象的name属性为:",a_tag_name)"""
整个BeautifulSoup对象的name属性为: [document]
title标签对象的name属性为: title
header标签对象的name属性为: head
a标签对象为: <a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>
a标签对象的name属性为: a
"""
注:
1、对于soup对象来说:soup对象本身比较特殊,它的name即为[document]
2、对于其他内部标签:输出的值便为标签本身的名称(值类型为字符串)
3、不过感觉获取一个Tag对象的name属性意义不大,毕竟都是通过其标签名来获取的tag对象,然后再通过Tag对象去获取其name属性就显得多此一举了
tag对象的attrs属性
1、attrs属性:指的是一个标签的属性
⑴一个标签的属性一般是由键值对组成,属性名=值
⑵<blockquote class="boldest">Extremely bold</blockquote>,其中的'class="boldest"'就是标签的属性
2、一个标签可能有很多个属性
3、获取一个Tag对象的attrs属性,可以使用:Tag对象.attrs
4、使用Tag对象的attrs属性可以把标签对的属性以字典形式返回
⑴ Tag对象无属性时返回的是一个空字典
例4:
from bs4 import BeautifulSoup #导入bs4库html = """
<html><head><title>The Dormouse's story</title></head>
<body>
<p class="title" name="dromouse"><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>
"""soup = BeautifulSoup(html,"lxml") #指定解析器
soup_tag_attrs = soup.attrs #获取整个BeautifulSoup对象的attrs属性
title_tag_attrs = soup.title.attrs #获取title Tag对象的attrs属性
head_tag_attrs = soup.head.attrs #获取head Tag对象的attrs属性
a_tag = soup.a #获取a标签的Tag对象
a_tag_attrs = a_tag.attrs #获取a Tag对象的attrs属性print("BeautifulSoup对象的attrs属性为:",soup_tag_attrs)
print("titlea标签的Tag对象的attrs属性为:",title_tag_attrs)
print("heada标签的Tag对象的attrs属性为:",head_tag_attrs)
print("a标签的Tag对象为:",a_tag)
print("a标签的Tag对象的attrs属性为:",a_tag_attrs)"""
BeautifulSoup对象的attrs属性为: {}
titlea标签的Tag对象的attrs属性为: {}
heada标签的Tag对象的attrs属性为: {}
a标签的Tag对象为: <a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>
a标签的Tag对象的attrs属性为: {'id': 'link1', 'href': 'http://example.com/elsie', 'class': ['sister']}
"""
注:
1、从上面的输出结果可以看出对于soup对象、head标签对、title标签对来说返回的为空字典:其标签对里面没有属性值以及对应的值(key:value)
2、对应存在key:value的标签:使用attrs方法可以将其所有的属性打印输出了出来,得到的类型是一个字典
3、如果想要单独获取某个属性具体的值时,可以使用下面三种方法:
⑴使用字典方法:字典索引、字典get()方法
⑵使用tag对象的get()方法:soup对象.标签名.get(属性名)
⑶使用soup对象.标签名.属性名(键名)
例5:
from bs4 import BeautifulSoup #导入bs4库# 单独的一个标签也是可以构造为BeautifulSoup对象的
html = """<a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>"""soup = BeautifulSoup(html,"lxml") #指定解析器
print("BeautifulSoup对象为:",soup)print("--------")a_tag_attrs = soup.a.attrs
print("a标签的tag对象的属性为:",a_tag_attrs)a_tag_attrs_href_dict = a_tag_attrs["href"] #使用字典的索引
print("通过字典索引获取到的tag对象的属性",a_tag_attrs_href_dict)print("--------")a_tag_attrs_href_dict1 = soup.a.attrs.get("href") #使用字典的get方法
print("通过字典get方法获取到的tag对象的属性",a_tag_attrs_href_dict1)print("--------")a_tag_attrs_href_get = soup.a.get("href")#使用soup对象.标签名.get(属性名)
print(a_tag_attrs_href_get)a_tag_attrs_href = soup.a["href"]#使用soup对象.标签名.属性名(键名)
print(a_tag_attrs_href )"""
BeautifulSoup对象为: <html><body><a class="sister" href="http://example.com/tillie" id="link3">Tillie</a></body></html>
--------
a标签的tag对象的属性为: {'class': ['sister'], 'href': 'http://example.com/tillie', 'id': 'link3'}
通过字典索引获取到的tag对象的属性 http://example.com/tillie
--------
通过字典get方法获取到的tag对象的属性 http://example.com/tillie
--------
http://example.com/tillie
http://example.com/tillie
"""
注:
1、从上面例子中可以看出要获得标签对中具体属性的值时,共有三种方法:
⑴使用字典的方法相对于其他两种来说多了一步,会显得麻烦。不过毕竟字典方法用得比较多,用来很熟悉
⑵使用使用soup对象.标签名.属性名方法时:需要注意,需要使用中括号将属性名括起来
⑶使用get方法,传入属性的名称,这种方法与上面一种第二种是等价的
多值属性
1、一般情况下,对于标签的属性都是以键值对存在的(一键一值,键=值)。但是某些属性可以存在多个值的情况(一键多值)。这种情况就称为多值属性
2、最常见的多值的属性是 class (一个tag可以有多个CSS的class)。还有一些属性rel , rev , accept-charset , headers , accesskey。在Beautiful Soup中多值属性的返回类型是列表
例5_1:
from bs4 import BeautifulSoupsoup = BeautifulSoup('<p class="body strikeout"></p>',"lxml")print("p标签的tag对象为",soup.p)print("p标签的tag对象的属性为",soup.p.attrs) #其值为一个字典
print("p标签的class属性为",soup.p.attrs.get("class"))css_soup = BeautifulSoup('<p class="body"></p>',"lxml")
print(css_soup.p['class'])"""
p标签的tag对象为 <p class="body strikeout"></p>
p标签的tag对象的属性为 {'class': ['body', 'strikeout']}
p标签的class属性为 ['body', 'strikeout']['body']
"""
注:
1、如果某个属性看起来好像有多个值,但在任何版本的HTML定义中都没有被定义为多值属性,那么Beautiful Soup会将这个属性作为字符串返回
2、将tag转换成字符串时,多值属性会合并为一个值
3、如果转换的文档是XML格式,那么tag中不包含多值属性
例5_3:
from bs4 import BeautifulSoupcss_soup = BeautifulSoup('<p id="my id"></p>',"lxml")
print(css_soup.p['id'])rel_soup = BeautifulSoup('<p>Back to the <a rel="index">homepage</a></p>',"lxml")
print(rel_soup.a['rel'])#如果转换的文档是XML格式,那么tag中不包含多值属性
xml_soup = BeautifulSoup('<p class="body strikeout"></p>', 'xml')
print(xml_soup.p['class'])"""
my id
['index']
body strikeout
"""
NavigableString
1、NavigableString对象:指的是标签对中的数据
2、字符串常被包含在tag内。BeautifulSoup用NavigableString类来包装tag中的字符串
3、获取一个Tag对象中的数据(NavigableString对象),可以使用:Tag对象.string
4、使用"Tag对象.string"方法返回的数据的类型为NavigableString对象,可以使用str()方法将其转为字符串(Unicode字符串)
⑴也可以使用str()方法将一个Tag对象转为字符串
例6:
from bs4 import BeautifulSoup #导入bs4库html = """
<html><head><title>The Dormouse's story</title></head>
<body>
<p class="title" name="dromouse"><b>The Dormouse's story A</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">Tillie</a>,
<a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> and
<a href="http://example.com/tillie" class="sister" id="link3"><!-- Elsie --></a>;
and they lived at the bottom of a well.</p>
<p class="story">...</p>
"""soup = BeautifulSoup(html,"lxml")#指定解析器,创建beautifulsoup对象head_string = soup.head.string
p_string = soup.p.stringa_tag = soup.a
a_tag_string = a_tag.stringprint("header标签中的数据为:",head_string)
print("p标签中的数据为:",p_string)print("a标签的tag对象为:",a_tag)
print("a标签中的数据为:",a_tag_string)
print("a标签中的数据的类型为为:",type(a_tag_string))print("转换数据类型后为:",type(str(a_tag_string))) #使用str()方法将NavigableString对象转为字符串
print("转换数据类型后为--tag对象:",type(str(a_tag))) #使用str()方法将tag对象转为字符串
"""
header标签中的数据为: The Dormouse's story
p标签中的数据为: The Dormouse's story A
a标签的tag对象为: <a class="sister" href="http://example.com/elsie" id="link1">Tillie</a>
a标签中的数据为: Tillie
a标签中的数据的类型为为: <class 'bs4.element.NavigableString'>
转换数据类型后为: <class 'str'>
转换数据类型后为--tag对象: <class 'str'>
"""
BeautifulSoup
BeautifulSoup 对象表示的是一个文档的全部内容。大部分时候可以把它当作Tag对象,是一个特殊的Tag,我们可以分别获取它的类型,名称,以及属性来感受一下
例7:
from bs4 import BeautifulSoup #导入bs4库html = """
<html><head><title>The Dormouse's story</title></head>
<body>
<p class="title" name="dromouse"><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>
"""soup = BeautifulSoup(html,"lxml")#指定解析器,创建beautifulsoup对象soup_name = soup.name
print(soup_name)
print(type(soup_name))soup_attrs = soup.attrs
print(soup_attrs)"""
[document]
<class 'str'>
{}
"""
Comment
Comment 对象是一个特殊类型的NavigableString对象,其实输出的内容仍然不包括注释符号,但是如果不好好处理它,可能会对我们的文本处理造成意想不到的麻烦
例8:找一个带注释的标签
from bs4 import BeautifulSoup #导入bs4库html = """
<html><head><title>The Dormouse's story</title></head>
<body>
<p class="title" name="dromouse"><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>
"""soup = BeautifulSoup(html,"lxml")#指定解析器,创建beautifulsoup对象print("a标签的tag对象为:",soup.a)
print("a标签内的数据为:",soup.a.string) #a标签内的数据为一个注释
print("a标签内的数据的类型为:",type(soup.a.string))"""
a标签的tag对象为: <a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>
a标签内的数据为: Elsie
a标签内的数据的类型为: <class 'bs4.element.Comment'>
"""
注:a标签里的内容实际上是注释,但是如果我们利用 .string 来输出它的内容,我们发现它已经把注释符号去掉了,所以这可能会给我们带来不必要的麻烦
补充
获取Tag对象
获取某个指定的tag有两种情况:一种是获取指定的第一个标签(这种实际中用得很少),另一种是获取指定的全部标签对
获取指定的第一个标签
获取指定的第一个标签就是使用前面介绍的"soup对象.标签名"
例9:soup对象.标签名
from bs4 import BeautifulSouphtml = """
<html><head><title>The Dormouse's story</title></head>
<body>
<p class="title" name="dromouse"><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>
"""soup = BeautifulSoup(html,"lxml")#一个<class 'bs4.BeautifulSoup'>tag_p = soup.p
print("p标签对为:",tag_p)tag_a = soup.a
print("a标签对为:",tag_a)"""
p标签对为: <p class="title" name="dromouse"><b>The Dormouse's story</b></p>
a标签对为: <a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>
"""
注:由上面的结果可以看出
1、获取某个标签对可以使用:soup对象.标签名
2、只是使用这种方法:只能获得整个文档中第一个符合要求的标签(存在多个一样的标签对时只会返回第一个)
3、如果想要的标签对中镶嵌了其他标签对,那么也会把里面镶嵌的标签对一起返回
4、这种方法在实际运用中发现:不能把标签名定义成变量,就是不能通过变量来批量获得一些标签对,所以这种方法有比较大的局限性
获取指定的全部标签对
1、要获取一个文档中某个指定的所有标签,就需要使用find_all()方法:BeautifulSoup对象或Tag对象都可以使用find_all()或find()方法来找其下面的子标签(只是查找范围不一样:BeautifulSoup对象->整个xml对象内,Tag对象->该Tag对象内)
2、其参数可以是很多类型,最常用的是:传入需要获取的标签的标签名
3、find_all()方法返回的是一个由所有符合要求的标签组成的列表
4、find_all()方法这里只是简单的介绍了,后面会详细介绍
5、个人感觉:就是不管HTML或XML文档中有无重复的标签,都最好用find_all()方法来找对应的Tag对象
例9_1:find_all()
from bs4 import BeautifulSouphtml = """
<html><head><title>The Dormouse's story</title></head>
<body>
<p class="title" name="dromouse"><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>
"""soup = BeautifulSoup(html,"lxml")tag_body = soup.find_all("p") #获取所有p标签的tag对象
print("p标签对为:",tag_body)tag_a = soup.find_all("a") #获取所有a标签的tag对象
print("a标签对为:",tag_a)"""
p标签对为: [<p class="title" name="dromouse"><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>]
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>]
"""
注:由上面的结果可以看出
1、find_all()方法用于返回整个文档中所有符合要求的标签对:返回值是由所有符合要求的tag对象组成的列表(遍历后就是一个个tsg对象)
2、同样的方法还有find()方法:只是说find()方法只是返回第一个符合要求的标签对
3、使用这种方法的话,就可以将标签名定义成变量,所以感觉这种方法比较好
tag对象的name和attrs属性
1、感觉解析过程就是:soup对象->Tag对象->通过tag对象的name、attrs和另外的string属性来获取想要的数据
2、只要是一个tag对象,就可以使用name、attrs和另外的string属性
例10:
from bs4 import BeautifulSouphtml = """
<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></body>
</html>"""soup = BeautifulSoup(html,"lxml")tag_a_name = soup.a.name
print("a标签对name属性为:",tag_a_name)tag_a_attrs = soup.a.attrs
print("a标签对attrs属性为:",tag_a_attrs)"""
a标签对name属性为: a
a标签对attrs属性为: {'href': 'http://example.com/elsie', 'class': ['sister'], 'id': 'link1'}
"""
注:
1、可以使用:soup.标签名.attrs或soup.标签名.name来获得标签对的name和attrs属性
⑴其实分开来看就是先使用soup.标签名来返回tag对象,然后使用tag对象.name、tag对象.attrs来获得name和attrs,以及tag对象.string来获得标签对之间的数据
2、使用这种方法的话也是:只会返回第一个符合要求的标签名的name和attrs(因为返回的只有一个tag对象)
3、标签对的attrs属性返回值是一个字典,可以对其使用字典的方法
4、tag的属性可以被添加,删除或修改,与字典处理方法一致,如:tag['class'] = 'verybold'
例10_1:
from bs4 import BeautifulSouphtml = """
<html><head><title>The Dormouse's story</title></head>
<body>
<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>
"""soup = BeautifulSoup(html,"lxml")def parse_msg(tagName):tags = soup.find_all(tagName) #find_all()返回的是一个由tag对象组成的列表,因此需要遍历for tag in tags:print("标签的tag对象为为:", tag)print("标签的名称为:",tag.name)print("标签的属性为:",tag.attrs)print("标签的数据为:", tag.string)parse_msg("a")
parse_msg("p")"""
标签的tag对象为为: <a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>
标签的名称为: a
标签的属性为: {'class': ['sister'], 'href': 'http://example.com/elsie', 'id': 'link1'}
标签的数据为: Elsie
标签的tag对象为为: <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>
标签的名称为: a
标签的属性为: {'class': ['sister'], 'href': 'http://example.com/lacie', 'id': 'link2'}
标签的数据为: Lacie
标签的tag对象为为: <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>
标签的名称为: a
标签的属性为: {'class': ['sister'], 'href': 'http://example.com/tillie', 'id': 'link3'}
标签的数据为: Tillie标签的tag对象为为: <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']}
标签的数据为: None
标签的tag对象为为: <p class="story">...</p>
标签的名称为: p
标签的属性为: {'class': ['story']}
标签的数据为: ...
"""
注:
1、上面的流程就是:先使用find_all()方法获取所有符合要求的tag对象组成的列表,然后遍历出每一个tag对象,最后获得每一个tag对象的name、attrs属性以及string
2、也可以可以使用soup.标签名["属性名"]来获取指定名字的attrs属性
2、这种嵌套在里面的标签对,如果返回的是外层的tag对象,那也只能获得外层tag对象的name和attrs属性
NavigableString对象
1、即可以遍历的字符串:就是被包含在tag内的字符串
例11:
from bs4 import BeautifulSouphtml = """
<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></body>
</html>
"""
soup = BeautifulSoup(html,"lxml")tag_a_string = soup.a.string
print("第一个a标签对中的字符串:",tag_a_string)
print(type(tag_a_string))for tag_a_name in soup.find_all("a"):print("as标签对name属性为:",tag_a_name.string)"""
第一个a标签对中的字符串: Elsie
<class 'bs4.element.NavigableString'>
as标签对name属性为: Elsie
as标签对name属性为: Lacie
as标签对name属性为: Tillie
"""
注:从上面的输出结果可以看出
1、获取标签对中的NavigableString对象,可以使用:soup对象.标签名.string的方法来获取(跟前面name或attrs一样,只是说这里的字符串属于另一个对象)。且这种方法只会返回第一个符合要求的标签对中的字符串
2、也可以先试用find_all()的方法先找出全部符合要求的标签对,然后遍历得到每一个标签对内的字符串
3、返回的是一个NavigableString对象:可以通过str()方法可以直接将NavigableString对象转换成Unicode字符串
4、如果想在Beautiful Soup之外使用NavigableString对象,需要调用str()方法,将该对象转换成普通的Unicode字符串,否则就算Beautiful Soup已方法已经执行结束,该对象的输出也会带有对象的引用地址.这样会浪费内存
5、tag中包含的字符串不能编辑,但是可以被替换成其它的字符串,用replace_with()方法(后面单独介绍吧)
解析XML文档
1、使用BeautifulSoup同样能解析XML文档,解析XML文档的方法、步骤与解析HTML文档一样
2、只是说在解析XML文档时最好指定解析器为"xml"
例12:
from bs4 import BeautifulSouphtml = """
<?xml version="1.0" encoding="utf-8"?>
<data> <time>20200706</time> <country name="Liechtenstein"> <rank>1</rank> <year type="year">2008</year> <year type="month" date="week">11</year> <gdppc>141100</gdppc> <neighbor name="Austria" direction="E"/></country>
</data>
"""soup = BeautifulSoup(html, 'xml') # 使用xml解析器,将一个文件或字符串转为BeautifulSoup对象
# print(type(soup)) #返回一个<class 'bs4.BeautifulSoup'>
# print(soup.prettify()) #格式化输出HTML文件tag_year = soup.find_all("year") # find_all()方法返回文档中全部的year标签组成的列表
print("year标签对有:", tag_year)
for i in tag_year:print("返回的标签类型为:", type(i)) # 返回的是一个字符串型的Tag对象,可以直接使用str()方法进行强转换print(i.name) # 通过Tag对象的name属性来获得标签的名字print(i.attrs) # 通过Tag对象的attrs属性来获得标签的属性(为属性名与属性值组成的字典)print(i.string) # 通过Tag对象的string属性来获得标签对中的数据(值)"""
year标签对有: [<year type="year">2008</year>, <year date="week" type="month">11</year>]
返回的标签类型为: <class 'bs4.element.Tag'>
year
{'type': 'year'}
2008返回的标签类型为: <class 'bs4.element.Tag'>
year
{'type': 'month', 'date': 'week'}
11
"""
例13:
from bs4 import BeautifulSoup"""
解析目标:将标签名及其数据组成字典
[{标签名:值},{标签名:值}]
"""msg = """
<?xml version="1.0" encoding="utf-8"?>
<breakfast_menu> <food> <name>Belgian Waffles</name> <price>$5.95</price> <description>two of our famous Belgian Waffles with plenty of real maple syrup</description> <calories>650</calories> </food> <food> <name>Strawberry Belgian Waffles</name> <price>$7.95</price> <description>light Belgian waffles covered with strawberries and whipped cream</description> <calories/></food>
</breakfast_menu>
"""def parse_msg(msg):soup = BeautifulSoup(msg, 'xml')# 通过xml可以看到,我们需要的数据都在"food"标签下面,且"food"标签可以存在一个或多个,# 因此可以先找到"food"标签,然后依次根据"food"标签来找其下面的子标签foods = soup.find_all("food")food_info_list = []for food in foods:# 获取所需标签值# food标签下name标签不会存在多个,因此使用find()方法比较方便,这里只是演示下find_all()方法food_name = food.find_all("name")[0].stringfood_price = food.find("price").stringfood_calories = food.find("calories").stringfood_info = {"name":food_name,"price":food_price,"calories":food_calories}food_info_list.append(food_info)return food_info_listfood_info_list = parse_msg(msg)
print(food_info_list)"""
输出:
[{'name': 'Belgian Waffles', 'calories': '650', 'price': '$5.95'}, {'name': 'Strawberry Belgian Waffles', 'calories': None, 'price': '$7.95'}]
这里是找"标签名:值",也可以用同样的方法来找"标签名:属性值"等等
"""
注:
本文是在按照Beautiful Soup 4.2.0 文档学习时记录的。只是为了方便自己以后学习和搜索的,文章中肯定会有错误或者遗漏的,因此如果有幸被您看到,可以直接参考其官方文档:
https://www.crummy.com/software/BeautifulSoup/bs4/doc/index.zh.html#string
Python爬虫:BeautifulSoup库相关推荐
- 数据之路 - Python爬虫 - BeautifulSoup库
一.BeautifulSoup介绍 Beautiful Soup就是Python的一个HTML或XML的解析库,可以用它来方便地从网页中提取数据.Beautiful Soup自动将输入文档转换为Uni ...
- python爬虫BeautifulSoup库抓取500彩票网竞彩足球信息并在excel表中对中奖赔率设置格式
目录 前言 数据的储存 格式设置 代码 结果展示 疑惑 前言 上一篇博客记录了使用BeautifulSoup模块抓取500彩票网竞彩足球赛果及赔率,但最后呈现的数据不够细致和美观,对最终开奖的赔率没有 ...
- Python爬虫基础库(RBX)的实践_田超凡
转载请注明原作者:田超凡 20190410 CSDN博客:https://blog.csdn.net/qq_30056341# Python爬虫基础库RBX指的是:Requests Beautiful ...
- Python爬虫扩展库scrapy选择器用法入门(一)
关于BeutifulSoup4的用法入门请参考Python爬虫扩展库BeautifulSoup4用法精要,scrapy爬虫案例请参考Python使用Scrapy爬虫框架爬取天涯社区小说"大宗 ...
- Python爬虫-BeautifulSoup
Python爬虫-BeautifulSoup Python爬虫-BeautifulSoup "美丽汤"的爱恨 使用 爱丽丝文档示例 标签 遍历 find(),findAll() 综 ...
- 已解决(Python爬虫requests库报错 请求异常SSL错误,证书认证失败问题)requests.exceptions.SSLError: HTTPSConnectionPool
成功解决(Python爬虫requests库报错 请求异常,SSL错误,证书认证失败问题)requests.exceptions.SSLError: HTTPSConnectionPool(host= ...
- 【python】python爬虫requests库详解
1.安装:pip install requests 简介:Requests是一个优雅而简单的Python HTTP库,与之前的urllibPython的标准库相比,Requests的使用方式非常的简单 ...
- Python爬虫——Requests 库基本使用
文章目录 Python爬虫--Requests 库基本使用 1.Requests简介和下载 2.Requests 库基本使用 Python爬虫--Requests 库基本使用 1.Requests简介 ...
- Python爬虫 —— urllib库的使用(get/post请求+模拟超时/浏览器)
Python爬虫 -- urllib库的使用(get/post请求+模拟超时/浏览器) 这里写目录标题 Python爬虫 -- urllib库的使用(get/post请求+模拟超时/浏览器) 1.Py ...
- Python爬虫高级库之一的lxml库中,ET.parse()是一个非常重要的方法。它可以将任意XML或HTML格式的文档解析成一个ElementTree对象,...
Python爬虫高级库之一的lxml库中,ET.parse()是一个非常重要的方法.它可以将任意XML或HTML格式的文档解析成一个ElementTree对象,方便我们对结构化的数据进行处理和分析.在 ...
最新文章
- 集员法对3D激光雷达和相机的外部校准
- MySQL工作中的实际用_数据库在工作中的应用,以及什么是MySQL?
- C++ hamming distance汉明距离算法(附完整源码)
- linux主机数据拷贝,linux 服务器之间拷贝文件
- 函数的傅立叶展开掐死我吧_关于文章《傅里叶分析之掐死教程》的再一点小思考...
- java中和char功能相反的是_JAVA基础语法
- Maple: 多项式相乘
- 机器学习:神经网络实现中的技巧
- jflash烧录教程_Jflash烧录(windows)原理分析
- netbeans 插件安装
- FreeRTOS-CortexM4-相关函数说明
- 通过爬虫获取银行名称
- Unity3D之矩阵运用
- 在家月入5q+有手机就能赚米,推荐14个让你在家就能挣米的软件
- Python实现excel表合入
- 老挑毛 win7 linux,老挑毛u盘启动工具下载
- JAVA编程思想第四版笔记 十、内部类
- Linux下使用libpcap进行网络抓包并保存到文件
- 前端工程师和后端工程师的区别?
- 游戏开发的数学知识(一)三维向量绕某一向量旋转
热门文章
- Puppeteer入门
- VUE 返回上一页 不刷新页面、重复进入同一页面created重复执行、每次进入页面时都执行created、vue单页面多路由,前进刷新,返回不刷新
- ios分屏_升级iPadOS(13.1)正式版后如何分屏?iPadOS分屏方法
- root开启有什么坏处吗,手机开启了root对手机有什么影响吗?
- 如何简单理解执行上下文?
- es内嵌文档查询_Elasticsearch 7.x Nested 嵌套类型查询 | ES 干货
- Section 1.快速排序
- 搜狗浏览器的页面静音
- 3dmax室内设计,建筑视频
- SurfaceView 与 TextureView 详解