1. 概念
Beautiful Soup是一個可以從HTML或XML文件中提取數據(解析)的Python庫,簡單來說,它能將HTML的標籤文件解析成樹形結構,然後方便地獲取到指定標籤的對應屬性。
HTML文檔,是由一組尖括號構成的標籤組織起來的,每對尖括號形成了一對標籤,而標籤之間存在上下級關係,形成了一個標籤樹。
<html>
<body>
<p class="title"...</p>
</body>
</html>
Beautiful Soup庫是解析、遍歷、維護“標籤樹‘的功能庫。
2. 標籤的具體形式
這裏的話,建議猿友們去了解下HTML格式,不需要了解多深,大概能看懂組織形式即可。舉例:P標籤
3. Beautiful Soup 對象初始化
安裝bs4庫:
pip install beautifulsoup4
導入Beautiful Soup 庫
from bs4 import BeautifulSoup
將一段文檔(HTML文檔)傳入 BeautifulSoup 的構造方法(最後一行代碼),就能得到一個文檔對象soup。如下代碼所示,文檔通過請求url獲取:
import requests
from bs4 import BeautifulSoup #BeautifulSoup是一個類
r=requests.get("http://python123.io/ws/demo.html")
r.raise_for_status()
r.encoding=r.apparent_encoding
demo=r.text
soup=BeautifulSoup(demo,"html.parser") #兩個參數,第一個是要解析的文檔對象,第二個是“html的解析器”
Beautiful Soup庫解析器
解析器 | 使用方法 | 條件 |
---|---|---|
bs4的HTML解析器 | BeautifulSoup(mk,'html.parser') | 安裝bs4庫 |
lxml的HTML解析器 | BeautifulSoup(mk,'lxml') | pip install lxml |
lxml的XML解析器 | BeautifulSoup(mk,'xml') | pip install lxml |
html5lib的解析器 | BeautifulSoup(mk,'html5lib') | pip install html5lib |
4. Beautiful Soup類的基本元素
基本元素 | 說明 |
---|---|
Tag | 標籤,最基本的信息組織單元,分別用<>和</>標明開頭和結尾 |
Name | 標籤的名字,< p>…</ p>的名字是‘p’,格式:< tag>.name |
Attributes | 標籤的屬性,字典形式組織,格式:< tag>.attrs |
NaviableString | 標籤內非屬性字符串,<>…</>中字符串,格式:< tag>.string |
Comment | 標籤內字符串的註釋部分,一種特殊的Comment類型 |
這裏先給出一個標籤樹的代碼:
import requests
from bs4 import BeautifulSoup
r=requests.get("http://python123.io/ws/demo.html")
r.encoding=r.apparent_encoding
demo=r.text
soup=BeautifulSoup(demo,"html.parser")
print(soup.prettify()) #重新排版,增強可讀性,運行結果就是HTML文檔的標籤樹形式
運行結果是一個標籤樹(如下,也可以說是HTML文檔的一種清晰的表現形式),下面的所有實例都用這個標籤樹實現。
<html>
<head>
<title>
This is a python demo page
</title>
</head>
<body>
<p class="title">
<b>
The demo python introduces several python courses.
</b>
</p>
<p class="course">
Python is a wonderful general-purpose programming language. You can learn Python from novice to professional by tracking the following courses:
<a class="py1" href="http://www.icourse163.org/course/BIT-268001" id="link1">
Basic Python
</a>
and
<a class="py2" href="http://www.icourse163.org/course/BIT-1001870001" id="link2">
Advanced Python
</a>
.
</p>
</body>
</html>
對於每個基本元素,都用幾個典型的實例來講解,加深印象。(注意和上邊的標籤樹比對着看,這樣纔有效果~~)多看註釋,註釋裏面講解了比較重要的點。
- 標籤、標籤的名字——Tag、Name
>>> import requests
>>> from bs4 import BeautifulSoup
>>> r=requests.get("http://python123.io/ws/demo.html")
>>> r.encoding=r.apparent_encoding
>>> demo=r.text
>>> soup=BeautifulSoup(demo,"html.parser")
>>> soup.title #頁面的標題
<title>This is a python demo page</title>
>>> soup.a #實際上我們知道a標籤有兩個,這樣寫,默認打印第一個出現的a標籤。
<a class="py1" href="http://www.icourse163.org/course/BIT-268001" id="link1">Basic Python</a>
>>> soup.a.name #a標籤的名字
'a'
>>> soup.a.parent.name #a標籤父親標籤的名字,也就是包含a標籤的上一層標籤
'p'
>>> soup.a.parent.parent.name #a標籤爺爺標籤的名字
'body'
- 標籤的屬性——Attributes
>>> tag=soup.a
>>> tag.attrs #a標籤的屬性,返回的是字典類型
{'href': 'http://www.icourse163.org/course/BIT-268001', 'class': ['py1'], 'id': 'link1'}
>>> tag.attrs['class'] #a標籤的屬性中,class所對應的值,列表類型
['py1']
>>> tag.attrs['href'] #a標籤的屬性中,href所對應的值
'http://www.icourse163.org/course/BIT-268001'
>>> type(tag.attrs) #a標籤屬性的類型,是字典
<class 'dict'>
>>> type(tag) #a標籤的標籤類型
<class 'bs4.element.Tag'>
- 標籤內非屬性的字符串——NaviableString
>>> soup.a
<a class="py1" href="http://www.icourse163.org/course/BIT-268001" id="link1">Basic Python</a>
>>> soup.a.string
'Basic Python'
>>> soup.p
<p class="title"><b>The demo python introduces several python courses.</b></p>
>>> soup.p.string #p標籤中實際還包含了b標籤,但打印的卻並不包含b標籤。說明NavigableString是可以跨越多個標籤層次的
'The demo python introduces several python courses.'
>>> type(soup.p.string)
<class 'bs4.element.NavigableString'> #bs4庫定義的類型
- 標籤內字符串的註釋部分——Comment
在HTML頁面表達中, '<! ’ 表示一個註釋的開始。
>>> newsoup=BeautifulSoup("<b><!--This is a comment--></b><p>This is not a comment</p>","html.parser")
>>> newsoup.b.string #註釋和字符串都可以用.string來打印
'This is a comment'
>>> type(newsoup.b.string)
<class 'bs4.element.Comment'>
>>> newsoup.p.string #有的時候我們需要對標籤內字符串進行類型判斷,因爲他可能是註釋
'This is not a comment'
>>> type(newsoup.p.string)
<class 'bs4.element.NavigableString'> #bs4庫定義的類型
5. Beautiful Soup HTML遍歷方法
將上面的HTML標籤樹進行簡化,把他變成更像樹的樣子。,如下(並不完整,只是一個例子,爲了理解而已):
由於Beautiful Soup庫是對標籤樹功能遍歷的集合,遍歷可以分爲上行遍歷、下行遍歷、平行遍歷。下面分別介紹一下。
- 標籤樹的下行遍歷
屬性 | 說明 |
---|---|
.contents | 子節點的列表,將< tag>所有兒子結點存入列表 |
.children | 子節點的迭代類型,與.contents類似,用於循環遍歷兒子結點 |
.descendants | 子孫結點的迭代類型,包含所有子孫結點,用於循環遍歷 |
代碼實例:
>>> soup.head #head標籤
<head><title>This is a python demo page</title></head>
>>> soup.head.contents
[<title>This is a python demo page</title>]
>>> soup.body.contents #對一個標籤的兒子節點,並不僅僅包括標籤節點,也包括字符串節點。比如像’\n‘
['\n', <p class="title"><b>The demo python introduces several python courses.</b></p>, '\n', <p class="course">Python is a wonderful general-purpose programming language. You can learn Python from novice to professional by tracking the following courses:
<a class="py1" href="http://www.icourse163.org/course/BIT-268001" id="link1">Basic Python</a> and <a class="py2" href="http://www.icourse163.org/course/BIT-1001870001" id="link2">Advanced Python</a>.</p>, '\n']
>>> len(soup.body.contents)
5
>>> soup.body.contents[1]
<p class="title"><b>The demo python introduces several python courses.</b></p>
#遍歷兒子節點
for child in soup.body.children:
print(child)
#遍歷子孫節點
for child in soup.body.descendants:
print(child)
- 標籤樹的上行遍歷
屬性 | 說明 |
---|---|
.parent | 子節點的父親標籤 |
.parents | 節點先輩標籤的迭代類型,用於循環遍歷先輩節點 |
代碼實例:
>>> soup.title.parent
<head><title>This is a python demo page</title></head>
>>> soup.html.parent #因爲html標籤是根節點,所以他的父親節點是他自己
<html><head><title>This is a python demo page</title></head>
<body>
<p class="title"><b>The demo python introduces several python courses.</b></p>
<p class="course">Python is a wonderful general-purpose programming language. You can learn Python from novice to professional by tracking the following courses:
<a class="py1" href="http://www.icourse163.org/course/BIT-268001" id="link1">Basic Python</a> and <a class="py2" href="http://www.icourse163.org/course/BIT-1001870001" id="link2">Advanced Python</a>.</p>
</body></html>
>>> soup.parent #soup的父親爲None
- 標籤樹的平行遍歷
屬性 | 說明 |
---|---|
.next_silbling | 返回按照HTML文本順序的下一個平行節點 |
.previous_silbling | 返回按照HTML文本順序的上一個平行節點 |
.next_silblings | 迭代類型,返回按照HTML文本順序的後續所有平行節點 |
.previous_silblings | 迭代類型,返回按照HTML文本順序的前續所有平行節點 |
代碼實例:
>>> soup.a.next_sibling #平行遍歷發生在同一父節點下的各節點之間。標籤之間的NavigableString也構成標籤樹平行的節點。
' and '
>>> soup.a.next_sibling.next_sibling
<a class="py2" href="http://www.icourse163.org/course/BIT-1001870001" id="link2">Advanced Python</a>
>>> soup.a.previous_sibling
'Python is a wonderful general-purpose programming language. You can learn Python from novice to professional by tracking the following courses:\r\n'
>>> soup.a.previous_sibling.previous_sibling #爲空
>>> soup.a.parent
<p class="course">Python is a wonderful general-purpose programming language. You can learn Python from novice to professional by tracking the following courses:
<a class="py1" href="http://www.icourse163.org/course/BIT-268001" id="link1">Basic Python</a> and <a class="py2" href="http://www.icourse163.org/course/BIT-1001870001" id="link2">Advanced Python</a>.</p>
#遍歷後續節點
for sibling in soup.a.next_siblings:
print(sibling)
#遍歷前續節點
for sibling in soup.a.previous_siblings:
print(sibling)
6. 基於bs4庫的HTML格式化
這裏主要介紹,bs4庫的prettify()方法。你可以認爲這個方法是讓輸出顯得更加有條理,更容易被程序識別。你可以試試,使用prettify()方法和不使用prettify()方法的區別,一看便知。最後一句便是方法的實現。
import requests
from bs4 import BeautifulSoup
r=requests.get("http://python123.io/ws/demo.html")
r.encoding=r.apparent_encoding
demo=r.text
soup=BeautifulSoup(demo,"html.parser")
print(soup.prettify()) #重新排版,增強可讀性,運行結果就是HTML文檔的標籤樹形式
7. 總結
文章總結了Beautiful Soup庫的一些基本使用方法。對於做一些簡單的HTML解析已經足夠用了。是非常好的爬蟲入門~
如果說有什麼建議的話,就是實踐!一點點的敲,一點點的試,當你敲完所有代碼的時候,你就會發現,東西已經在你的腦子裏了~~
本寶才疏學淺,文章如有不當之處,還請多多指教~~ (●′ω`●)