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 = """
<html>
<head>
<title>The Dormouse's story</title>
</head>
<body>
<div class="panel">
<div class="panel-heading">
<h4>Hello</h4>
</div>
<div class="panel-body">
<ul class="list" id="list-1">
<li class="element">Foo</li>
<li class="element">Bar</li>
<li class="element">Jay</li>
</ul>
<ul class="list list-small" id="list-2">
<li class="element">Foo</li>
<li class="element">Bar</li>
</ul>
</div>
</div>
</body>
</html>
"""
```
## 1. 节点选择器:
**初始化beautifulsoup**
```python
soup = BeautifulSoup(html, 'lxml')
```
初始化对于一些不标准的html,可以自动更正格式,如补全标签等等
**获取title节点,查看它的类型**
```python
print(soup.title)
print(type(soup.title))
#输出结果
<title>The Dormouse's story</title>
<class 'bs4.element.Tag'>
```
获取到的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)
#输出结果:
<title>The Dormouse's story</title>
<class 'bs4.element.Tag'>
The Dormouse's story
```
## 2. 方法选择器
**find_all():查询所有符合条件的元素**
```python
print(type(soup.find_all(name='ul')))
print(soup.find_all(name='ul'))
#运行结果:
<class 'bs4.element.ResultSet'>
[<ul class="list" id="list-1">
<li class="element">Foo</li>
<li class="element">Bar</li>
<li class="element">Jay</li>
</ul>, <ul class="list list-small" id="list-2">
<li class="element">Foo</li>
<li class="element">Bar</li>
</ul>]
```
利用find_all方法查询ul节点,返回结果是列表类型,长度为2,
可以通过列表操作方法操作,也可以通过for循环继续操作
```python
for ul in soup.find_all(name='ul'):
print(ul.find_all(name='li'))
#输出结果:
[<li class="element">Foo</li>, <li class="element">Bar</li>, <li class="element">Jay</li>]
[<li class="element">Foo</li>, <li class="element">Bar</li>]
```
除了根据节点名查询,还可以传入一些属性来查询
```python
print(soup.find_all(attrs={'id': 'list-1'}))
#输出结果:
[<ul class="list" id="list-1">
<li class="element">Foo</li>
<li class="element">Bar</li>
<li class="element">Jay</li>
</ul>]
```
对于一些常用的属性,比如id和class等,可以不用attrs来传递。
比如,要查询class为element的节点,可以直接传入class这个参数。
```python
print(soup.find_all(class_='element'))
#class由于是python的关键字,所以要改为class_
#输出结果:
[<li class="element">Foo</li>, <li class="element">Bar</li>, <li class="element">Jay</li>, <li class="element">Foo</li>, <li class="element">Bar</li>]
```
text参数可以用来匹配节点的文本,传入的形式可以是字符串,可以是正则表达式对象
```python
print(soup.find_all(text='Foo'))
#输出结果:
['Foo', 'Foo']
```
**find():返回单个元素,也就是第一个匹配的元素**
```python
print(soup.find(name='ul'))
#输出结果:
<ul class="list" id="list-1">
<li class="element">Foo</li>
<li class="element">Bar</li>
<li class="element">Jay</li>
</ul>
```
**其他的查询方法**
* 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]))
#输出结果:
[<div class="panel-heading">
<h4>Hello</h4>
</div>]
[<li class="element">Foo</li>, <li class="element">Bar</li>, <li class="element">Jay</li>, <li class="element">Foo</li>, <li class="element">Bar</li>]
[<li class="element">Foo</li>, <li class="element">Bar</li>]
<class 'bs4.element.Tag'>
```
**嵌套选择**
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
[<li class="element">Foo</li>, <li class="element">Bar</li>, <li class="element">Jay</li>]
[<li class="element">Foo</li>, <li class="element">Bar</li>]
```
可以看到,这里正常输出了所有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
```
- 基础部分
- 基础知识
- 变量
- 数据类型
- 数字与布尔详解
- 列表详解list
- 字符串详解str
- 元组详解tup
- 字典详解dict
- 集合详解set
- 运算符
- 流程控制与循环
- 字符编码
- 编的小程序
- 三级菜单
- 斐波那契数列
- 汉诺塔
- 文件操作
- 函数相关
- 函数基础知识
- 函数进阶知识
- lambda与map-filter-reduce
- 装饰器知识
- 生成器和迭代器
- 琢磨的小技巧
- 通过operator函数将字符串转换回运算符
- 目录规范
- 异常处理
- 常用模块
- 模块和包相关概念
- 绝对导入&相对导入
- pip使用第三方源
- time&datetime模块
- random随机数模块
- os 系统交互模块
- sys系统模块
- shutil复制&打包模块
- json&pickle&shelve模块
- xml序列化模块
- configparser配置模块
- hashlib哈希模块
- subprocess命令模块
- 日志logging模块基础
- 日志logging模块进阶
- 日志重复输出问题
- re正则表达式模块
- struct字节处理模块
- abc抽象类与多态模块
- requests与urllib网络访问模块
- 参数控制模块1-optparse-过时
- 参数控制模块2-argparse
- pymysql数据库模块
- requests网络请求模块
- 面向对象
- 面向对象相关概念
- 类与对象基础操作
- 继承-派生和组合
- 抽象类与接口
- 多态与鸭子类型
- 封装-隐藏与扩展性
- 绑定方法与非绑定方法
- 反射-字符串映射属性
- 类相关内置方法
- 元类自定义及单例模式
- 面向对象的软件开发
- 网络-并发编程
- 网络编程SOCKET
- socket简介和入门
- socket代码实例
- 粘包及粘包解决办法
- 基于UDP协议的socket
- 文件传输程序实战
- socketserver并发模块
- 多进程multiprocessing模块
- 进程理论知识
- 多进程与守护进程
- 锁-信号量-事件
- 队列与生产消费模型
- 进程池Pool
- 多线程threading模块
- 进程理论和GIL锁
- 死锁与递归锁
- 多线程与守护线程
- 定时器-条件-队列
- 线程池与进程池(新方法)
- 协程与IO模型
- 协程理论知识
- gevent与greenlet模块
- 5种网络IO模型
- 非阻塞与多路复用IO实现
- 带着目标学python
- Pycharm基本使用
- 爬虫
- 案例-爬mzitu美女
- 案例-爬小说
- beautifulsoup解析模块
- etree中的xpath解析模块
- 反爬对抗-普通验证码
- 反爬对抗-session登录
- 反爬对抗-代理池
- 爬虫技巧-线程池
- 爬虫对抗-图片懒加载
- selenium浏览器模拟