Beautiful Soup 是一個能夠從HTML或XML文件中提取數據的Python庫。使用它來處理HTML頁面就像JavaScript代碼操做HTML DOM樹同樣方便。官方中文文檔地址css
Beautiful Soup3 目前已經中止維護,推薦使用 Beautiful Soup4,如今已經被移植到 bs4,導入的時候須要從 bs4 導入。安裝方法以下:html
# 使用 pip 安裝 pip install beautifulsoup4 # 使用 easy_install 安裝 easy_install beautifulsoup4
另外還須要安裝相應的解析器,lxml,html5lib 任選一個便可。html5
# 安裝 lxml pip install lxml # 安裝 html5lib pip install html5lib
安裝了 BeautifulSoup 之後能夠導入使用。將一段文檔傳入BeautifulSoup 的構造方法,就能獲得一個文檔的對象, 能夠傳入一段字符串或一個文件句柄.node
# 首先從 bs4 導入 from bs4 inport BeautifulSoup # 使用解析器和html文檔能夠初始化 soup = BeautifulSoup(open("index.html"), 'lxml') content = '<html>data</html>' soup = BeautifulSoup(content, 'lxml')
文檔須要轉換成Unicode,而且HTML的實例都被轉換成Unicode編碼python
Beautiful Soup將複雜HTML文檔轉換成一個複雜的樹形結構,相似於瀏覽器中的DOM節點數,每一個節點都是Python對象,全部對象能夠概括爲4種: Tag , NavigableString , BeautifulSoup , Comment 。正則表達式
tag 對象相似於一個標籤節點。與XML或HTML原生文檔中的標籤相同,如 body,div,a,span。tag 對象有不少方法和屬性。tag 對象的屬性能夠像字典同樣進行增刪改查操做。瀏覽器
name 屬性表示 tag 的名稱。經過 .name 獲取。若是改變了tag的name,那將影響全部經過當前Beautiful Soup對象生成的HTML文檔。app
一個tag可能有不少個屬性,使用 tag.attrs 獲取 tag 的全部節點屬性,能夠對這些屬性進行增刪改查。獲取方法以下:函數
在HTML文檔中有典型像 class 同樣的有多個屬性值,這些多值屬性返回的值不是 string ,而是 list 。這些多值屬性的節點類型以下:編碼
在XML文檔中沒有多值屬性
content = '<a href="index.html" class="button button-blue" data="1 2 3"></a>' soup = BeautifulSoup(content, 'lxml') tag = soup.a # 獲取 a 標籤 tag.name # 標籤名稱:a tag.attrs # 屬性列表:['href', 'class', 'data'] tag.get('href') # 獲取href屬性:index.html tag['class'] # 獲取class屬性爲list:[button,button-blue] tag['data'] # data屬性的值爲string:1 2 3
字符串常被包含在tag內,Beautiful Soup用 NavigableString 類來包裝tag中的字符串。
BeautifulSoup 對象表示的是一個文檔的所有內容。大部分時候,能夠把它看成 tag 對象。
由於 BeautifulSoup 對象並非真正的HTML或XML的tag,BeautifulSoup 對象包含了一個值爲 「[document]」 的特殊屬性 .name。
Comment 對象是一個特殊類型的 NavigableString 對象,用來表示文檔的註釋部分。
markup = "<b><!--Hey, buddy. Want to buy a used parser?--></b>" soup = BeautifulSoup(markup) comment = soup.b.string type(comment) # <class 'bs4.element.Comment'> print(soup.b.prettify()) # <b> # <!--Hey, buddy. Want to buy a used parser?--> # </b>
經過遍歷文檔樹,可以從文檔中找到指定的內容。
一個 tag 可能包含多個字符串或者其餘 tag,這些 tag 就是頂層的子節點,Beautiful Soup提供了許多操做和遍歷子節點的屬性。須要注意:
假設有如下幾種簡單的方式獲取子節點:
div_html = ' <div> <p>uu</p> <p>sa</p> <p> <a>ma</a> --> </p> </div>' soup = BeautifulSoup(div_html), 'lxml') div = soup.div # 獲取 div 節點 div.p # <p>uu</p> div.contents # [<p>uu</p>, <p>sa</p>, <p><a>ma</a>--></p>] div.contents[0] # <p>uu</p> for child in div.children: print(child) # <p>uu</p><p>sa</p><p><a>ma</a>--></p> for child in div.descendants: pring(child)
每一個tag或字符串都有父節點,即每一個節點都被包含在tag中,經過 .parent 屬性來獲取某個元素的父節點: p.parent,經過元素的 .parents 屬性能夠遞歸獲得元素的全部父輩節點。
soup = BeautifulSoup(div_html), 'lxml') # 使用3.1中定義的 div_html div = soup.div # 獲取 div 節點 sa = div.a.string # 第一個 a 節點的string sa.parent # a 節點 sa.parent.parent # div 節點 for parent in sa.parents: print(parent) # a # div # [document] # None
兄弟節點就是具備相同父節點的同義詞節點。如3.1中定義的 div_html 中的3個p標籤互相爲兄弟節點。使用下面的節點tag屬性訪問兄弟節點
搜索功能能夠說是寫爬蟲過程當中必用的功能,用來查找指定的節點,Beautiful Soup定義了不少搜索方法,這些搜索方法的參數和用法都很相似,查詢功能很是強大,下面主要針對 find_all 方法說明。
過濾器是使用搜索方法過程當中的匹配規則,即參數的可能取值。過濾器能夠爲下面幾種形式:
content = '<nav><a>a_1</a><a>a_2</a>string</nav>' soup = BeautifulSoup(content), 'lxml') nav_node = soup.nav # <nav><a>a_1</a><a>a_2</a>string</nav> nav_node.find_all(True) # 不匹配 string # ['<a>a_1</a>', '<a>a_2</a>'] def has_class_but_no_id(tag): # 定義匹配函數 return tag.has_attr('class') and not tag.has_attr('id') soup.find_all(has_class_but_no_id) # 返回有class屬性沒有id屬性的節點
find_all 方法返回匹配搜索的全部節點的列表或者空,而 find 方法直接返回第一個匹配搜索的結果。詳細的定義以下:
find_all(name=None, attrs={}, recursive=True, text=None, limit=None, **kwargs) find_find(name=None, attrs={}, recursive=True, text=None, limit=None, **kwargs)
各參數含義以下:
以上的參數值均可以是 4.1 中說明的任意一種過濾器值。另外還須要注意如下幾點:
# 搜索全部 div 標籤 soup.find_all('div') # 搜索全部具備id屬性而且id屬性值爲 link1 或者 link2 的節點 soup.find_all(id=['link1', 'link2']) # 搜索全部 class 屬性包含 button 的節點 soup.find_all(class_='button') # 搜索全部匹配給定正則表達式內容的 p 標籤 soup.find_all('p', text=re.compile('game')) # 搜索具備 button 類,而且具備值爲 link1 的 href 屬性的 a 標籤 soup.find_all('a', {'classl': 'button', 'href': 'link1'}) # 只搜索一個直接子節點的 a 標籤 soup.find_all('a', limit=1, recursive=False)
其餘的搜索方法參數和 find_all 和 find 相似,它們成對出現,分別返回結果列表和第一個匹配的結果,只是搜索文檔的範圍不同,下面列舉一些經常使用的:
Beautiful Soup支持大部分的CSS選擇器,使用 select() 方法來搜索。如id選擇器,標籤選擇器,屬性選擇器設置組合選擇器。如:
當咱們獲得搜索結果之後,但願搜索結果中的某些節點不參與以後的搜索,那麼就須要把這些節點刪除掉,這就須要對文檔樹修改。修改的方法以下:
有時候,須要對查到的或者修改過的文檔樹展現或者保存。
prettify() 方法將Beautiful Soup的文檔樹格式化後以Unicode編碼輸出,每一個XML/HTML標籤都獨佔一行。BeautifulSoup 對象和它的tag節點均可以調用 prettify() 方法。
能夠對一個 BeautifulSoup 對象或 Tag 對象使用Python的 unicode() 或 str() 方法,從而對輸出結果進行壓縮。