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瀏覽器模擬