BeautifulSoup是Python的一个HTML或XML的解析库,可以用它来方便地从网页提取数据
[TOC]
# 一. 环境准备
## 安装方式
```python
#安装beautifulsoup4
pip install beautifulsoup4
#安装lxml
pip install lxml
#转化本地文件:
soup = BeautifulSoup(open('本地文件'), 'lxml')
#转化网络文件:
soup = BeautifulSoup('字符串类型或者字节类型', 'lxml')
```
## 快速掌握知识点
```python
#(1)根据标签名查找
soup.a 只能找到第一个符合要求的标签
#(2)获取属性
soup.a.attrs 获取a所有的属性和属性值,返回一个字典
soup.a.attrs['href'] 获取href属性
soup.a['href'] 也可简写为这种形式
#(3)获取内容
soup.a.string
soup.a.text
soup.a.get_text()
【注意】如果标签还有标签,那么string获取到的结果为None,而其它两个,可以获取文本内容
#(4)find:找到第一个符合要求的标签
soup.find('a') 找到第一个符合要求的
soup.find('a', title="xxx")
soup.find('a', alt="xxx")
soup.find('a', class_="xxx")
soup.find('a', id="xxx")
#(5)find_all:找到所有符合要求的标签
soup.find_all('a',title="xxx") 找到title为xxx的a标签
soup.find_all(['a','b']) 找到所有的a和b标签
soup.find_all('a', limit=2) 限制前两个
#(6)根据选择器选择指定的内容
select:soup.select('#feng')
常见的选择器:标签选择器(a)、类选择器(.)、id选择器(#)、层级选择器
层级选择器:
div .dudu #lala .meme .xixi 下面好多级
div > p > a > .lala 只能是下面一级
【注意】select选择器返回永远是列表,需要通过下标提取指定的对象
```
# 二. 语法详解
## 准备环境
```html
from bs4 import BeautifulSoup
# 先定义一个html内容
html = """
The Dormouse's storyHello
- Foo
- Bar
- Jay
- Foo
- Bar
"""
```
## 1. 节点选择器:
**初始化beautifulsoup**
```python
soup = BeautifulSoup(html, 'lxml')
```
初始化对于一些不标准的html,可以自动更正格式,如补全标签等等
**获取title节点,查看它的类型**
```python
print(soup.title)
print(type(soup.title))
#输出结果
The Dormouse's story```
获取到的title节点,正是节点加文本内容
**获取title节点文本内容**
```python
print(soup.title.string)
#输出结果
The Dormouse's story
```
如果想获取其他信息,比如节点的名字及其属性,这些也比较方便
**获取title节点的名字**
```python
print(soup.title.name)
#输出结果
title
```
**获取p节点的多个属性和某一属性**
p节点有多个属性,比如class和name等,可以调用attrs获取所有属性
```python
#获取多个属性
print(soup.ul.attrs)
#输出结果:
{'class': ['list'], 'id': 'list-1'}
#获取某个属性:方法一
print(soup.ul.attrs['id'])
#输出结果:
list-1
#获取某个属性:方法二
print(soup.ul['id'])
#输出结果:
list-1
#获取单个属性需要注意的地方
print(soup.ul['class'])
#输出结果:
['list']
```
>如果属性的值是唯一的,返回的结果就是单个字符串;
>如果属性不唯一,返回的是列表,但只反复第一个p的值
**嵌套选择或层级选择**
如果多个节点层级嵌套在一起,可以通过层级关系依次选择,比如要选择title节点及其内容,之前我们是soup.title,现在可以这样操作:soup.head.title
```python
print(soup.head.title)
print(type(soup.head.title))
print(soup.head.title.string)
#输出结果:
The Dormouse's storyThe Dormouse's story
```
## 2. 方法选择器
**find_all():查询所有符合条件的元素**
```python
print(type(soup.find_all(name='ul')))
print(soup.find_all(name='ul'))
#运行结果:
[
- Foo
- Bar
- Jay
- Foo
- Bar
```
利用find_all方法查询ul节点,返回结果是列表类型,长度为2,
可以通过列表操作方法操作,也可以通过for循环继续操作
```python
for ul in soup.find_all(name='ul'):
print(ul.find_all(name='li'))
#输出结果:
[
Foo, Bar, Jay][
Foo, Bar]```
除了根据节点名查询,还可以传入一些属性来查询
```python
print(soup.find_all(attrs={'id': 'list-1'}))
#输出结果:
[
- Foo
- Bar
- Jay
```
对于一些常用的属性,比如id和class等,可以不用attrs来传递。
比如,要查询class为element的节点,可以直接传入class这个参数。
```python
print(soup.find_all(class_='element'))
#class由于是python的关键字,所以要改为class_
#输出结果:
[
Foo, Bar, Jay, Foo, Bar]```
text参数可以用来匹配节点的文本,传入的形式可以是字符串,可以是正则表达式对象
```python
print(soup.find_all(text='Foo'))
#输出结果:
['Foo', 'Foo']
```
**find():返回单个元素,也就是第一个匹配的元素**
```python
print(soup.find(name='ul'))
#输出结果:
- Foo
- Bar
- Jay
```
**其他的查询方法**
* find_parents()和find_parent():
前者返回所有祖先节点,后者返回直接父节点
* find_next_siblings()和find_next_sibling():
前者返回后面所有的兄弟节点,后者返回后面第一个兄弟节点
* find_previous_siblings()和find_previous_sibling():
前者返回前面所有的兄弟节点,后者返回前面第一个兄弟节点
* find_all_next()和find_next():
前者返回节点后所有符合条件的节点,后者返回第一个符合条件的节点
* find_all_previous()和find_previous():
前者返回节点前所有符合条件的节点,后者返回第一个符合条件的节点
## 3. CSS选择器
使用CSS选择器时,只需要调用select()方法,传入相应的CSS选择器即可
```python
print(soup.select('.panel .panel-heading'),'\n')
print(soup.select('ul li'),'\n')
print(soup.select('#list-2 .element'),'\n')
print(type(soup.select('ul')[0]))
#输出结果:
[
Hello
[
Foo, Bar, Jay, Foo, Bar][
Foo, Bar]```
**嵌套选择**
select()方法同样支持嵌套选择。例如,先选择所有ul节点,再遍历每个ul节点
```python
for ul in soup.select('ul'):
print(ul.select('li'))
#输出结果:
"C:\Program Files\Python36\python.exe" D:/data/python/t-class/pc.py
[
Foo, Bar, Jay][
Foo, Bar]```
可以看到,这里正常输出了所有ul节点下所有li节点组成的列表
**获取属性**
```python
for ul in soup.select('ul'):
print(ul['id'])
print(ul.attrs['id'])
#输出结果:
list-1
list-1
list-2
list-2
```
可以看到,直接传入中括号和属性名,或通过attrs属性获取属性值,都可以成功
**获取文本**
要获取文本,可以用前面所讲的string属性或者get_text()方法
```python
for li in soup.select('li'):
print('Get Text:', li.get_text())
print('String:', li.string,'\n')
#输出结果:
Get Text: Foo
String: Foo
Get Text: Bar
String: Bar
Get Text: Jay
String: Jay
Get Text: Foo
String: Foo
Get Text: Bar
String: Bar
```