一.bs4簡介
Beautiful Soup提供一些簡單的、python式的函數用來處理導航、搜尋、修改分析樹等功能。它是一個工具箱,通過解析文檔為使用者提供需要抓取的資料,因為簡單,是以不需要多少代碼就可以寫出一個完整的應用程式。
Beautiful Soup自動将輸入文檔轉換為Unicode編碼,輸出文檔轉換為utf-8編碼。你不需要考慮編碼方式,除非文檔沒有指定一個編碼方式,這時,Beautiful Soup就不能自動識别編碼方式了。然後,你僅僅需要說明一下原始編碼方式就可以了。
官方文檔:https://beautifulsoup.readthedocs.io/zh_CN/v4.4.0/
二.bs4子產品的解析器
1.Python标準庫
使用方法:
BeautifulSoup(markup, “html.parser”)
優點:
Python的内置标準庫
執行速度适中
文檔容錯能力強
劣勢:
Python 2.7.3 or 3.2.2)前 的版本中文檔容錯能力差
2.lxml HTML 解析器
使用方法:
BeautifulSoup(markup, “lxml”)
優點:
速度快
文檔容錯能力強
劣勢:
需要安裝C語言庫
3.lxml XML 解析器
使用方法:
BeautifulSoup(markup, [“lxml-xml”])
BeautifulSoup(markup, “xml”)
優點:
速度快
唯一支援XML的解析器
劣勢:
需要安裝C語言庫
4.html5lib
使用方法:
BeautifulSoup(markup, “html5lib”)
優點:
最好的容錯性
以浏覽器的方式解析文檔
生成HTML5格式的文檔
劣勢:
速度慢
不依賴外部擴充
推薦使用lxml作為解析器,因為效率更高.但需要安裝
安裝方法:
pip install lxml
三.使用方法
1.如果僅是想要解析HTML文檔,隻要用文檔建立 BeautifulSoup 對象就可以了.Beautiful Soup會自動選擇一個解析器來解析文檔.例如:
html = """
<html>
<head><title class='title'>story12345</title></head>
<body>
<p class="title" name="dromouse">The Dormouse's story</p>
<p class="story">Once upon a time there were three little sisters; and their names were
<a href="http://example.com/elsie" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" class="sister" id="link1"><span>westos</span><!-- Elsie --></a>,
<a href="http://example.com/lacie" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" class="sister1" id="link2">Lacie</a> and
<a href="http://example.com/tillie" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" class="sister" id="link3">Tillie</a>;
and they lived at the bottom of a well.</p>
<p class="story">...</p>
<input type="text">
<input type="password">
"""
from bs4 import BeautifulSoup
#可以傳入一段字元串或者時檔案
soup = BeautifulSoup(open("檔案名"))
soup = BeautifulSoup("html")
2.還可以通過features參數指定使用那種解析器來解析目前文檔.
from bs4 import BeautifulSoup
#可以傳入一段字元串或者時檔案
soup = BeautifulSoup(open("檔案名"),'lxml')
soup = BeautifulSoup("html",'lxml')
四.bs4子產品的四種對象
Beautiful Soup将複雜HTML文檔轉換成一個複雜的樹形結構,每個節點都是Python對象,所有對象可以歸納為4種: Tag , NavigableString , BeautifulSoup , Comment .
1.BeautifulSoup 對象
BeautifulSoup 對象表示的是一個文檔的全部内容,上面内容’三.使用方法’ 所建立的就是BeautifulSoup對象
2.Tag對象
我們可以從 BeautifulSoup 對象中得到 Tag 對象,也就是 HTML/XML 中的标簽。
soup = BeautifulSoup(html, 'lxml')
tag = soup.a
print(type(tag))
#<class 'bs4.element.Tag'>
3.NavigableString類
字元串常被包含在tag内.Beautiful Soup用 NavigableString 類來包裝tag中的字元串:
tag = soup.p
print(tag.string)
# The Dormouse's story
print(type(tag.string))
# <class 'bs4.element.NavigableString'>
4.Comment類
Comment類是用來包裝注釋
markup = "<b><!--Hey, buddy. Want to buy a used parser?--></b>"
soup = BeautifulSoup(markup)
comment = soup.b.string
type(comment)
# <class 'bs4.element.Comment'>
五.周遊文檔樹
tag标簽的常用屬性
1.可以通過‘soup.标簽名‘來獲得你所需要的标簽,但隻會傳回第一個滿足條件的标簽。
soup = BeautifulSoup(html, 'lxml')
print(soup.a)
#<a class="sister" href="http://example.com/elsie" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" id="link1"><span>westos</span><!-- Elsie --></a>
2.可以通過 .name 方式得到 Tag 對象的名稱
soup = BeautifulSoup(html, 'lxml')
tag = soup.a
print(tag.name)
#a
3.可以通過.attrs擷取标簽裡面的屬性資訊
soup = BeautifulSoup(html, 'lxml')
print(soup.a.attrs)
#傳回一個字典
#{'href': 'http://example.com/elsie', 'class': ['sister'], 'id': 'link1'}
print(soup.a.attrs['href'])
#可以通過字典的方法來擷取想要的屬性
#http://example.com/elsie
tag标簽的常用方法
1.get方法用于得到标簽下的屬性值
print(soup.a.get('href'))
#http://example.com/elsie
2.string方法可以得到标簽下的文本内容(隻有在此标簽下沒有子标簽,或者隻有一個子标簽的情況下才能傳回其中的内容,否則傳回的是None)
print(soup.p.string)
# The Dormouse's story
print(soup.a.string)
# None
3.get_text()可以獲得一個标簽中的所有文本内容,包括子孫節點的内容
print(soup.a.get_text())
# westos
4.對擷取的屬性資訊進行修改
print(soup.a.get('href'))
#http://example.com/elsie
soup.a['href'] = 'http://www.baidu.com'
print(soup.a.get('href'))
print(soup.a)
#http://www.baidu.com
#<a class="sister" href="http://www.baidu.com" target="_blank" rel="external nofollow" id="link1"><span>westos</span><!-- Elsie --></a>
六.搜尋文檔樹
1.find_all()方法
find_all() 方法搜尋目前tag的所有tag子節點,并判斷是否符合過濾器的條件,并傳回所有符合條件的tag(傳回的是一個清單)
aTagObj = soup.find_all('a')
print(aTagObj)
# [<a class="sister" href="http://example.com/elsie" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" id="link1"><span>westos</span><!-- Elsie --></a>, <a class="sister1" href="http://example.com/lacie" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" id="link2">Lacie</a>, <a class="sister" href="http://example.com/tillie" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" id="link3">Tillie</a>]
for item in aTagObj:
print(item)
# <a class="sister" href="http://example.com/elsie" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" id="link1"><span>westos</span><!-- Elsie --></a>
# <a class="sister1" href="http://example.com/lacie" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" id="link2">Lacie</a>
# <a class="sister" href="http://example.com/tillie" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" id="link3">Tillie</a>
2.find()方法
find()的用法與find_all一樣,差別在于find用于查找第一個符合條件的tag
3.css比對
寫CSS時,标簽名不加任何修飾,類名前加英文句号 .,id名前加 #
在這裡我們也可以利用類似的方法來篩選元素,用到的方法是soup.select(),傳回類型是list
- 标簽選擇器
print(soup.select("title"))
# [<title class="title">story12345</title>]
- 類選擇器
print(soup.select(".sister"))
# [<a class="sister" href="http://example.com/elsie" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" id="link1"><span>westos</span><!-- Elsie --></a>, <a class="sister" href="http://example.com/tillie" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" id="link3">Tillie</a>]
- id選擇器
print(soup.select("#link1"))
# [<a class="sister" href="http://example.com/elsie" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" id="link1"><span>westos</span><!-- Elsie --></a>]
- 屬性選擇器
print(soup.select("input[type='password']"))
# [<input type="password"/>]