Python爬虫:用Beautifulsoup爬取html文本数据
Beautifulsoup介绍:
- 是一个高效的网页解析库,可以从HTML或XML文件中提取数据
- 支持不同的解析器,比如,对HTML解析,对XML解析,对HTML5解析
- 就是一个非常强大的工具,爬虫利器
- 一个灵活又方便的网页解析库,处理高效,支持多种解析器
- 利用它就不用编写正则表达式也能方便的实现网页信息的抓取
第一步:安装BeautifulSoup4,lxml
pip install BeautifulSoup4
BeautifulSoup 是一个可以从HTML或XML文件中提取数据的Python库
pip install lxml
lxml 是一种使用 Python 编写的解析库,可以迅速、灵活地处理 XML 和 HTML
第二步:导包,from bs4 import BeautifulSoup
第三步:实例化对象
html = """
The Dormouse's story
Once upon a time there were three little sisters; and their names were
Elsie
Lacie
and
Tillie
and they lived at the bottom of a well.
...
"""
soup = BeautifulSoup(html, 'lxml') # h:要解析的内容 lxml:解析器
知识补充:print(soup.prettify()) # 代码补全
第四步:打印
一、通过标签选取,会返回包含标签本身及其里面的所有内容
# print(soup.head) # 包含head标签在内的所有内容
# print(soup.p) # 返回匹配的第一个结果
1.print(soup.head)打印结果:
2.print(soup.p)打印结果:
The Dormouse's story
二、打印标签中间的文本内容,不包含<>
# .string是属性,作用是获取字符串文本
print(soup.html.head.title.string)
print(soup.title.string)
打印结果都为:The Dormouse's story
三、打印标签名
.name --获取标签本身名称
print(soup.title.name)
打印结果为:title
四、打印属性的值
.attrs[] --通过属性拿属性的值
print(soup.p.attrs['name'])# 获取p标签name属性的属性值
print(soup.a.attrs['id']) # 获取p标签id属性的属性值
print(soup.a['id']) #第二种写法
print(soup.p['class']) # 以列表得形式保存
print(soup.a['href']) # 也是只返回第一个值
1.print(soup.p.attrs['name'])打印结果:
dromouse
2.print(soup.p.attrs['id'])和print(soup.a['id'])打印结果:
link1
3.print(soup.p['class'])打印结果:
['title', 'asdas']
4.print(soup.a['href'])打印结果:
http://example.com/elsie
五、打印父标签下的所有子标签
.contents 获取标签子节点,以列表形式返回
.children 获取子节点,返回的是一个list类型的迭代器
print(soup.body.contents) # a是p的子节点,获取P标签所有子节点内容 返回一个list
print(soup.body.children) #返回的是一个list类型的迭代器
1.print(soup.body.contents)的打印结果:
['\n',
The Dormouse's story
, '\n',Once upon a time there were three little sisters; and their names were
Lacie and
and they lived at the bottom of a well.
, '\n',...
, '\n']2.print(soup.body.children)的打印结果:
.children 获取子节点讲解
1.和for循环一起使用
for i in soup.p.children:
print(i)
打印结果:
The Dormouse's story
Once upon a time there were three little sisters; and their names were
Lacie and
and they lived at the bottom of a well.
...
2.和enumerate()一起使用
enumerate()
#用于将一个可遍历的数据对象,并在其前面添加一个索引序列,即同时列出数据下标值和数据,一般用在 for 循环当中
for i, child in enumerate(soup.body.children):
print(i, child) #i用来接收索引,child用来接收数据
打印结果:
六、打印子孙节点
.descendants 获取子孙节点,返回的是一个生成器
用法:
from bs4 import BeautifulSoup
soup = BeautifulSoup(h, 'lxml')
print(soup.body.descendants) # 获取子孙节点 生成器本身是一种特殊的迭代器
for i, child in enumerate(soup.body.descendants):
print(i, child)
七、打印父节点
.parent 获取父节点,返回的结果是某一标签的上一层级节点以及某一标签里的内容,返回的不是列表
用法:
from bs4 import Beautifulsoup
soup = Beautifulsoup(h, 'lxml')
print(soup.body.parent)
.parents 获取祖先节点,返回的结果是,返回的是生成器
用法:
from bs4 import BeautifulSoup
soup = BeautifulSoup(h, 'lxml')
print(soup.a.parents) # 获取祖先节点 返回的是生成器,生成器本身是一种特殊的迭代器
# print(list(soup.a.parents))
#list是内置的列表类,它有一个构造函数,可以接受一个Iterable(可迭代)的对象作为参数,返回一个列表对象
for i, child in enumerate(soup.a.parents):
print(i, child)
返回的结果是按层级来返回,首先返回a标签的上一层级,再返回a标签的上上层级,再返回a标签的上上上层级,以此类推
for i, child in enumerate(soup.a.parents)的打印结果
八、打印兄弟节点
.next_siblings 获取后面的兄弟节点,可以是多个兄弟节点
.previous_siblings 获取前面的兄弟节点
两者返回的都是一个生成器对象
用法:
from bs4 import BeautifulSoup
soup = BeautifulSoup(h, 'lxml')
print(list(enumerate(soup.a.next_siblings))) # 默认为找第一个a标签后边的所有的兄弟节点
print(list(enumerate(soup.a.previous_siblings))) # 默认为找第一个a标签前边的所有的同一层级的兄弟节点
九、find_all(),根据标签名查找
from bs4 import BeautifulSoup
soup = BeautifulSoup(h, 'lxml')
# print(soup.find_all('a')) # 拿到所有a标签及其里面内容
# print(soup.find_all('a')[0]) # 拿到第一个a标签及其里面内容
# print(soup.find_all('p')) # 拿到所有p标签及其里面内容,包括在p标签里其他标签的内容
.string 获取标签中间的文本值
用法
from bs4 import BeautifulSoup
soup = BeautifulSoup(h, 'lxml')
for i in soup.find_all('p'):
print(i.string)
有时候用.string取不到,可以用get_text(),get_text()可以用来获取特殊符号
用法:print(i.get_text())
十、根据属性取值,.find_all(attrs={'属性':'属性值'})
from bs4 import BeautifulSoup
soup = BeautifulSoup(h, 'lxml')
for ul in soup.find_all(attrs={'name': 'elements'}):
# print(ul) # 从列表中遍历取出
# print(ul.li.string) #只返回第一个值
# print('-----')
for li in ul:
# print(li) # 都是同级标签
print(li.string)
第二种写法:.find_all(属性='属性值')
print(soup.find_all(id='list-1'))
这种方法打印不出class属性,因为class属于Python关键字,需做特殊处理,在class后面加_
第三种写法:指定标签和属性(常用)
print(soup.find_all('li',{'class':'element'}))
print(soup.find_all('ul',{'id':'list-2'}))
可以通过父标签.子标签['属性']来获取对应的属性值
例如获取class='element'的属性值'element',可以这样写:
classes = soup.find_all('ul',{'class':'list'})
for i in classes:
new_class = i.li['class']
print(new_class)
打印结果为:
['element']
['element']
十一、查找标签中的指定文本,text=()
print(soup.find_all(text='Foo')) # 可以做内容统计用
print(len(soup.find_all(text='Foo'))) # 统计数量
打印结果:
['Foo', 'Foo']
2
十二、find和find_all用法一样,但是也有区别
find返回单个元素,find_all返回所有元素
十三、用CSS选择器提取
CSS选择器介绍:
1,类别选择器 -- class
2,标签选择器 --
3,ID选择器 -- id
用法:
通过select()直接传入CSS选择器即可完成选择
例如:print(soup.select('ul li')) # 提取ul选择器下的li标签
注意:
1,用CSS选择器时,标签名不加任何修饰,class类名前加. , id名前加#
2,用到的方法是soup.select(),返回类型是list
3,多个过滤条件需要用空格隔开,严格遵守从前往后逐层筛选
html='''
q321312321
Hello
- Foo
- Bar
- Jay
- Foo
- Bar
'''
class类名前加.
print(soup.select('.panel'))
print("----"*10)
# 多个条件用空格隔开
print(soup.select('.panel .panel-heading'))
print("----"*10)
打印结果:
id名前加#
print(soup.select('#list-1'))
打印结果:
可以混合使用!!
# 比如:根据id和class去找
print(soup.select('#list-1 .element')) #从这个例子可以看出.select方法会获取满足条件的所有内容
打印结果:
十四、获取属性的值
两种写法:
ul['id']
ul.attrs['id']
具体用法:
for ul in soup.select('ul'):
# print(ul)
# print(ul['id'])
# print(ul['class'])
print(ul.attrs['id'])
print(ul.attrs['class'])
打印结果: