Python BeautifulSoup庫的用法

BeautifulSoup是一個能夠從HTML或者XML文件中提取數據的Python庫,它經過解析器把文檔解析爲利於人們理解的文檔導航模式,有利於查找和修改文檔。css

BeautifulSoup3目前已經中止開發,如今推薦使用BeautifulSoup4,它被移植到了bs4中。html

# 使用時須要導入
from bs4 import BeautifulSoup

解析器

BeautifulSoup4中經常使用4種主要的解析器,使用前須要安裝:html5

#不一樣系統安裝方法
$ apt-get install Python-lxml
$ easy_install lxml
$ pip install lxml

# pycharm中安裝能夠先import xxx,顯示有錯誤而後點擊安裝,安裝後刪除import語句,便可正常使用

 

解析器的優缺點對比
解析器 使用方法 優點 劣勢
Python標準庫

BeautifulSoup(DocumentName, "html.parser")python

 

  • Python的內置標準庫
  • 不須要單獨安裝
  • 執行速度適中
  • 文檔容錯能力強
Python 2.7.3 or 3.2.2前的班中文容錯能力差
lxml HTML解析器 BeautifulSoup(DocumentName, "lxml")
  • 速度快
  • 文檔容錯能力強
須要安裝C語言庫
lxml XML解析器

BeautifulSoup(DocumentName, "xml")express

BeautifulSoup(DocumentName, ["lxml","xml"])瀏覽器

  • 速度快
  • 惟一支持XML的解析器
須要安裝C語言庫
html5lib BeautifulSoup(DocumentName, "html5lib")
  • 最好的容錯
  • 以瀏覽器的方式解析文檔
  • 生成HTML5格式的文檔
速度慢,須要依賴python庫

 

不一樣解析器的解析結果:編碼

# 符合HTML標準的解析結果
htmldoc = "<a><p></p></a>" print("None :",BeautifulSoup(htmldoc)) print("html.parser :", BeautifulSoup(htmldoc, "html.parser")) print("lxml :", BeautifulSoup(htmldoc, "lxml")) print("xml :", BeautifulSoup(htmldoc, "lxml-xml")) print("html5lib :", BeautifulSoup(htmldoc, "html5lib")) """ 結果爲: None : <html><body><a><p></p></a></body></html> html.parser : <a><p></p></a> lxml : <html><body><a><p></p></a></body></html> xml : <?xml version="1.0" encoding="utf-8"?>   <a><p/></a> html5lib : <html><head></head><body><a><p></p></a></body></html> """
# 不符合HTML標準的解析結果
htmldoc = "<a></p></a>"
print("None        :",BeautifulSoup(htmldoc))
print("html.parser :", BeautifulSoup(htmldoc, "html.parser"))
print("lxml        :", BeautifulSoup(htmldoc, "lxml"))
print("xml         :", BeautifulSoup(htmldoc, "lxml-xml"))
print("html5lib    :", BeautifulSoup(htmldoc, "html5lib"))

"""
結果爲:
None        : <html><body><a></a></body></html>
html.parser : <a></a>
lxml        : <html><body><a></a></body></html>
xml         : <?xml version="1.0" encoding="utf-8"?>
          <a/>
html5lib    : <html><head></head><body><a><p></p></a></body></html>
"""

html5lib會把全部的標籤不全,而且加上html、head、body,標準的html格式;默認、html.parser、lxml 解析器會把錯誤標籤忽略掉。spa

編碼

任何HTML或者XML文檔都有本身的編碼方式,但使用BeautifulSoup解析後,文檔都會被轉換爲Unicode,輸出時編碼均爲UTF-8。code

由於BeautifulSoup用來編碼自動檢測庫來識別當前文檔的編碼,並自動轉換爲Unicode編碼。但也有小几率會識別出錯,能夠用.original_encoding來檢測編碼格式。orm

而且設置from_encoding參數能夠提升文檔的解析速度。

htmldoc = b"<h1>\xed\xe5\xec\xf9</h1>"
soup = BeautifulSoup(htmldoc, from_encoding="iso-8859-8")
print(soup.h1)
print(soup.original_encoding)


"""
結果:
<h1>םולש</h1>
'iso8859-8'
"""

指定輸出編碼:

 
 
htmldoc = b"<h1>\xed\xe5\xec\xf9</h1>"
soup = BeautifulSoup(htmldoc, from_encoding="iso-8859-8")
print(soup.prettify("latin-1"))
"""
結果:
b'<h1>\n &#957;&#949;&#956;&#969;\n</h1>' """

 遍歷文檔樹:

1. 註釋<class 'bs4.element.Comment'> 和 替換Comment內容

htmldoc = "<b><!--Hey, buddy. Want to buy a used parser?--></b>"
soup = BeautifulSoup(htmldoc)
comment = soup.b.string
print(comment)
print(type(comment))
print(soup2.b)
print(soup2.b.prettify()) #comment特點輸出方式

# 替換Comment
cdata= CData("A CData block")
comment.replace_with(cdata)
print(soup2.b.prettify())

"""
結果:
Hey, buddy. Want to buy a used parser?
<class 'bs4.element.Comment'>
<b><!--Hey, buddy. Want to buy a used parser?--></b>
<b>
 <!--Hey, buddy. Want to buy a used parser?-->
</b>
<b>
<![CDATA[A CData block]]>
</b>
"""

CData使用時須要導入 from bs4 import CData

2. soup.tagName  返回類型 <class 'bs4.element.Tag'>,獲得文檔中第一個tagName標籤 ==  soup.find(tagName)

soup.div #獲得文章中第一個div標籤
soup.a #獲得文章中第一個a標籤

3. soup.tagName.get_text() / soup.tagName.text 返回類型 <class 'str'>,獲得該標籤內容,對每一個BeautifulSoup處理後的對象都生效。

soup.a.get_text()
soup.a.text

4. soup.tagName.tagName["AttributeName"] 得到標籤內屬性值,逐級訪問標籤能夠用 . 鏈接,某個屬性值用 ["屬性名"] 訪問。

soup.div.a['href']

5. soup.ul.contents 返回類型爲<class 'list'>,能夠用下標訪問其中的元素

 list內元素類型爲 <class 'bs4.element.Tag'> or <class 'bs4.element.NavigableString'>

 若是是單一標籤能夠用 string 返回文本,若是超過1個標籤就返回None

soup.ul.contents
type(soup.ul.contents) #<class 'list'>
soup.ul.contents[0].string
type(soup.ul.contents[0])

6. find_all(name, attrs, recursice, text, limit, **kwargs),返回的類型爲 <class 'bs4.element.ResultSet'>

# 找到全部標籤爲tagName的集合
soup.find_all("tagName")
soup.find_all("a")

# 找到全部標籤爲tagName 且 class=className的集合
soup.find_all("tagName", "className")
soup.find_all("div","Score")

# 找到全部id=idName的標籤
soup.find_all(id = "idName")

# 使用多個指定名字的參數能夠同時過濾tag的多個屬性:
soup.find_all(href = re.compile("else"))
soup.find_all(href=re.compile("elsie"), id='link1')
# [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>]

# 有些tag屬性在搜索不能使用,好比HTML5中的 data-* 屬性
data_soup = BeautifulSoup('<div data-foo="value">foo!</div>')
data_soup.find_all(data-foo="value")
# SyntaxError: keyword can't be an expression
# 能夠用attrs 參數定義一個字典參數來搜索包含特殊屬性的tag
data_soup.find_all(attrs={"data-foo": "value"})
# [<div data-foo="value">foo!</div>]

# 找到全部有id的標籤
soup.find_all(id = True)

# 找到全部標籤爲tagName且class = "className"的標籤
soup.find_all("tagName", class_ = "className")
# css class參數過濾
soup.find_all(class_=re.compile("itl"))
# [<p class="title"><b>The Dormouse's story</b></p>]

# 經過文本查找文本
soup.find_all(text = "textContent")
soup.find_all(text = ["Content1", "Content2"])
# 文本參數過濾
soup.find_all(text=re.compile("Dormouse"))

# 限制結果個數
soup.find_all("tagName", limit = 2)
elemSet = soup.find_all("div", limit = 2)
# 可循環出每一個元素
for item in elemSet:
    print(item)
    print(item.text)

7. 經過 css 選擇器查找,返回值 <class 'list'>,list中元素類型爲 <class 'bs4.element.Tag'>

htmldoc = """
<html><head><title>The Dormouse's story</title></head>
<p class="title"><b>The Dormouse's story</b></p>
<p class="story">Once upon a time there were three little sisters; and their names were
<a href="http://example.com/elsie" class="sister" id="link1">Elsie</a>,
<a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> and
<a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>;
and they lived at the bottom of a well.</p>
<p class="story">...</p>
"""
soup = BeautifulSoup(htmldoc, "lxml")

# tag標籤查找
soup.select("title")

# tag標籤逐層查找
soup.select("html head title")
soup.select("head title")
soup.select("body a")

# tag標籤下的直接子標籤
soup.select("head > title")
soup.select("p > a")
soup.select("p > a:nth-of-type(2)")
soup.select("p > #link1")

# css類名查找
soup.select(".sister")

# id 查找
soup.select("#link1")

# 經過屬性查找
soup.select("a[href]")
soup.select('a[href="http://example.com/elsie"]')
soup.select('a[href^="http://example.com/"]')
soup.select('a[href$="tillie"]')
soup.select('a[href*=".com/el"]')
type(soup.select("a[href]")) # <class 'list'>

# 經過循環獲取到每一個tag
list = soup.select("a[href]") 
for item in list:
    print(item)
    print(type(item)) # <class 'bs4.element.Tag'>
    print(item.text)
    print(item.string)
相關文章
相關標籤/搜索