# 指定文檔解析器
如果僅是想要解析HTML文檔,只要用文檔創建 `BeautifulSoup` 對象就可以了.Beautiful Soup會自動選擇一個解析器來解析文檔.但是還可以通過參數指定使用那種解析器來解析當前文檔.
`BeautifulSoup` 第一個參數應該是要被解析的文檔字符串或是文件句柄,第二個參數用來標識怎樣解析文檔.如果第二個參數為空,那么Beautiful Soup根據當前系統安裝的庫自動選擇解析器,解析器的優先數序: lxml, html5lib, Python標準庫.在下面兩種條件下解析器優先順序會變化:
* 要解析的文檔是什么類型: 目前支持, “html”, “xml”, 和 “html5”
* 指定使用哪種解析器: 目前支持, “lxml”, “html5lib”, 和 “html.parser”
[安裝解析器](#id9) 章節介紹了可以使用哪種解析器,以及如何安裝.
如果指定的解析器沒有安裝,Beautiful Soup會自動選擇其它方案.目前只有 lxml 解析器支持XML文檔的解析,在沒有安裝lxml庫的情況下,創建 `beautifulsoup` 對象時無論是否指定使用lxml,都無法得到解析后的對象
## 解析器之間的區別
Beautiful Soup為不同的解析器提供了相同的接口,但解析器本身時有區別的.同一篇文檔被不同的解析器解析后可能會生成不同結構的樹型文檔.區別最大的是HTML解析器和XML解析器,看下面片段被解析成HTML結構:
```
BeautifulSoup("<a><b /></a>")
# <html><head></head><body><a><b></b></a></body></html>
```
因為空標簽`<b />`不符合HTML標準,所以解析器把它解析成`<b></b>`
同樣的文檔使用XML解析如下(解析XML需要安裝lxml庫).注意,空標簽`<b />`依然被保留,并且文檔前添加了XML頭,而不是被包含在`<html>`標簽內:
```
BeautifulSoup("<a><b /></a>", "xml")
# <?xml version="1.0" encoding="utf-8"?>
# <a><b/></a>
```
HTML解析器之間也有區別,如果被解析的HTML文檔是標準格式,那么解析器之間沒有任何差別,只是解析速度不同,結果都會返回正確的文檔樹.
但是如果被解析文檔不是標準格式,那么不同的解析器返回結果可能不同.下面例子中,使用lxml解析錯誤格式的文檔,結果`</p>`標簽被直接忽略掉了:
```
BeautifulSoup("<a></p>", "lxml")
# <html><body><a></a></body></html>
```
使用html5lib庫解析相同文檔會得到不同的結果:
```
BeautifulSoup("<a></p>", "html5lib")
# <html><head></head><body><a><p></p></a></body></html>
```
html5lib庫沒有忽略掉`</p>`標簽,而是自動補全了標簽,還給文檔樹添加了`<head>`標簽.
使用pyhton內置庫解析結果如下:
```
BeautifulSoup("<a></p>", "html.parser")
# <a></a>
```
與lxml \[7\] 庫類似的,Python內置庫忽略掉了`</p>`標簽,與html5lib庫不同的是標準庫沒有嘗試創建符合標準的文檔格式或將文檔片段包含在`<body>`標簽內,與lxml不同的是標準庫甚至連`<html>`標簽都沒有嘗試去添加.
因為文檔片段“`<a></p>`”是錯誤格式,所以以上解析方式都能算作”正確”,html5lib庫使用的是HTML5的部分標準,所以最接近”正確”.不過所有解析器的結構都能夠被認為是”正常”的.
不同的解析器可能影響代碼執行結果,如果在分發給別人的代碼中使用了 `BeautifulSoup` ,那么最好注明使用了哪種解析器,以減少不必要的麻煩.