1. 程式人生 > >Beautiful Soup 的使用

Beautiful Soup 的使用

esc 屬性 TP 文件 解析器 獲得 成了 字符串 IE

Beautiful Soup 的使用

  Beautiful Soup 就是python的一個HTML或XML的解析庫,也是用於從網頁中提取數據。廢話不多說,直接看基本用法:

from bs4 import BeautifulSoup

html = """<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>The Dormouse‘s story</title>
</head>
<body>
    <p class="title" name="dromouse"><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/tittle" class="sister" id="link3">Tillie</a>;
        and they lived at the bottom of a well.
    </p>
    <p class="story">...</p>
</body>
</html>
""" soup = BeautifulSoup(html,lxml) print(soup.prettify()) print(soup.title.string)

這裏首先聲明了html,它是一個HTML字符串,接著,將它作為第一個參數傳遞給BeautifulSoup對象,該對象的第二個參數為解析器的類型,此時就完成了BeautifulSoup對象的初始化。接下來就可以調用soup對象的方法和屬性去解析HTML代碼了。

上面的prettify方法可以把要解析的字符串以標準的縮進格式輸出;soup.title.string屬性實際上輸出的是HTML中title標簽的內容,也就是說,soup.title可以拿到HTML中的title對象,再調用string屬性就可以得到裏面的文本了,這比正則或是xpath都要方便很多了。

BeautifulSoup跟XPath一樣,也可以獲取標簽的屬性,子節點等等,下面來詳細介紹:

1. 節點選擇器

直接調用節點的名稱就可以選擇元素節點,再調用string屬性就可以得到節點內的文本了。

<!--test_beautifulSoup.html-->
<!
DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>The Dormouse‘s story</title> </head> <
body> <p class="title" name="dromouse"><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/tittle" class="sister" id="link3">Tillie</a>; and they lived at the bottom of a well. </p> <p class="story">...</p> </body> </html>

from bs4 import BeautifulSoup
soup = BeautifulSoup(open(./test_beautifulSoup.html),lxml)
print(soup.title.string)
print(type(soup.p))
print(soup.p.string)

註意BeautifulSoup的第一個參數除了可以傳HTML文本以外還可以傳一個HTML的文件句柄。經過選擇器選擇後的結果都是Tag類型,這是bs4中一個重要的數據結構。另外,如果選擇的對象有多個,比如上面有個p元素,而使用這種方式只會獲取到第一個p元素。

2.提取信息

2.1 獲取名稱

可以利用name屬性獲取節點的名稱:

from bs4 import BeautifulSoup
soup = BeautifulSoup(open(./test_beautifulSoup.html),lxml)
print(soup.title.name)

輸出結果就是title

2.2 獲取屬性

每個節點都可能有一個或多個屬性,比如id或者class等,選擇這個節點元素後,可以調用attrs獲取所有的屬性:

from bs4 import BeautifulSoup

soup = BeautifulSoup(open(./test_beautifulSoup.html),lxml)
print(soup.p.attrs)
print(soup.p.attrs[name])

attrs返回的結果是一個包含所有屬性的字典,所以如果需要獲取這個元素的屬性就通過訪問字典的方式來獲取就可以了;其實,attrs也可以直接省略不寫:

from bs4 import BeautifulSoup

soup = BeautifulSoup(open(./test_beautifulSoup.html),lxml)
print(soup.p.attrs[name])
print(soup.p[name])

上面兩行的輸出是一致的,需要註意的是,如果返回的結果不唯一時,就是一個列表,如果結果唯一就是一個字符串。

2.3 獲取內容

通過string屬性即可獲取元素包含的文本內容,前面已經說了,在此就不再闡述了。

在上面的例子中,我們知道每一個返回結果都是Tag類型,它同樣可以繼續調用節點進行下一步的選擇。比如,獲取了head節點,我們可以繼續用head來獲取其內部的元素,這種方式稱為嵌套選擇:

from bs4 import BeautifulSoup

soup = BeautifulSoup(open(./test_beautifulSoup.html),lxml)
print(soup.head.title)

在做選擇的時候,很多時候不能一步就選到想要的節點元素,需要先選中某一個節點元素,然後以它為基準再選擇它的子節點、父節點、兄弟節點等等,下面就來詳細介紹如何選擇這些節點:

子節點和子孫節點:

選取節點元素之後,如果想要獲取它的直接子節點,可以調用contents屬性:

from bs4 import BeautifulSoup

soup = BeautifulSoup(open(./test_beautifulSoup.html),lxml)
print(soup.p.contents)

可以看到,返回的結果是列表形式,p節點裏面既包含了文本,也包含了元素節點。除了contents屬性以外,還可以通過children屬性得到相應的結果:

from bs4 import BeautifulSoup

soup = BeautifulSoup(open(./test_beautifulSoup.html),lxml)
print(soup.p.children)
for i,child in enumerate(soup.p.children):
    print(i,child)

返回的結果是生成器對象,使用for循環可以輸出所有子節點。

如果需要得到所有子孫節點,可以調用descendants屬性:

from bs4 import BeautifulSoup

soup = BeautifulSoup(open(./test_beautifulSoup.html),lxml)
print(soup.p.descendants)
for i,child in enumerate(soup.p.descendants):
    print(i,child)

這裏返回結果還是生成器,遍歷輸出就可以得到所有的子孫節點。

父節點和祖先節點:

如果想獲取某個節點的父節點,可以調用parent屬性:

from bs4 import BeautifulSoup
soup = BeautifulSoup(open(./test_beautifulSoup.html),lxml)
print(soup.a.parent)

這裏輸出的僅僅是第一個a節點的直接父元素,如果想獲取所有的祖先節點,可以調用parents屬性,此時返回的結果是一個生成器,遍歷即可獲得具體的結果。

兄弟節點:

next_sibling、previous_sibling、next_siblings和previous_siblings分別獲取節點的下一個兄弟元素,節點的上一個兄弟元素,節點之前所有的兄弟元素和節點之後所有的兄弟元素。

上面說到的方法都局限於只能查出一個結果就終止了,那麽肯定有時候需要查找所有匹配的節點,這時候就需要用到find_all(name,attrs,recursive,text,**kwargs)方法了:

name代表節點名,attrs代表屬性,text代表文本。

除此以外,還有類似的方法:

find() 匹配第一個節點

find_parents() 和 find_parent() 前者返回所有祖先節點,後者返回直接父節點

find_next_siblings() 和 find_next_sibling() 前者返回後面所有的兄弟節點,後者返回後面第一個兄弟節點

find_previous_siblings() 和 find_previous_sibling() 前者返回前面所有的兄弟節點,後者返回前面第一個兄弟節點。

find_all_next() 和 find_next() 前者返回節點後所有符合條件的節點,後者返回第一個符合條件的節點。

find_all_previous() 和 find_previous() 前者返回節點後所有符合條件的節點,後者返回節點後第一個符合條件的節點。

有沒有想過這麽多API太復雜了,既然在操作HTML代碼,如果能提供一種CSS的API那不要爽飛天了嗎?是的,Beautiful Soup提供了一個select(CSS選擇器字符串)方法用於獲取信息。

Beautiful Soup 的使用