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 2.7.3 or 3.2.2前的班中文容錯能力差 |
lxml HTML解析器 | BeautifulSoup(DocumentName, "lxml") |
|
須要安裝C語言庫 |
lxml XML解析器 | BeautifulSoup(DocumentName, "xml")express BeautifulSoup(DocumentName, ["lxml","xml"])瀏覽器 |
|
須要安裝C語言庫 |
html5lib | BeautifulSoup(DocumentName, "html5lib") |
|
速度慢,須要依賴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 νεμω\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)