BeautifulSoup4入門

對象的種類

BeautifulSoup會將HTML文檔抓換成一個樹形結構, 每一個節點都是Python對象,全部對象能夠分爲4類:Tag,NavigableString,BeautifulSoup,Commentphp

Tag

Tag與XML或HTML中的tag相同:css

soup = BeautifulSoup('<b class="boldest">Extremely bold</b>')
tag = soup.b
print(type(tag))
print(tag)

--<class 'bs4.element.Tag'> --<b class="boldest">Extremely bold</b>

name

每個Tag都有本身的name,能夠經過.name。改變tag的name,將會影響經過當前BS對象生成的HTML文檔html

soup = BeautifulSoup('<b class="boldest">Extremely bold</b>',"html.parser")
tag = soup.b
print(tag)
print(tag.name)
tag.name="blockquote"
print(tag)

---<b class="boldest">Extremely bold</b> ---b ---<blockquote class="boldest">Extremely bold</blockquote>

attributes

一個tag可能有多個屬性python

soup = BeautifulSoup('<b class="boldest">Extremely bold</b>',"html.parser")
tag = soup.b
print(tag['class'])
print(tag.attrs)

---['boldest']
---{'class': ['boldest']}

tag的屬性能夠被添加,刪除或修改正則表達式

soup = BeautifulSoup('<b class="boldest">Extremely bold</b>',"html.parser")
tag = soup.b
#更改屬性
tag['class']="verybold"
tag['id']=1
print(tag)

#刪除屬性
del tag['class']
print(tag)
print(tag.get('class'))

---<b class="verybold" id="1">Extremely bold</b> ---<b id="1">Extremely bold</b> ---
多值屬性

多值屬性即爲可包含多個值的屬性,最多見的即爲class
xml中沒有多值屬性ruby

多值屬性的返回類型是listmarkdown

css_soup = BeautifulSoup('<p class="body strikeout"></p>',"html.parser")
print(css_soup.p['class'])

---['body', 'strikeout']

若某個屬性看起來像多值屬性,可是在任何版本HTML中都沒有被定義爲多值屬性,那麼BS會將這個屬性做爲字符串返回spa

id_soup = BeautifulSoup('<p id="my id"></p>',"html.parser")
print(id_soup.p['id'])

---my id

NavigableString不支持.content,.string,find()方法。code

若是想在Beautiful Soup以外使用NavigableString對象,須要調用unicode()方法,將該對象轉換成普通的Unicode字符串,不然就算Beautiful Soup已方法已經執行結束,該對象的輸出也會帶有對象的引用地址.這樣會浪費內存.orm

soup = BeautifulSoup('<b class="boldest">Extremely bold</b>',"html.parser")
tag = soup.b
print(tag.string)
print(type(tag.string))
tag.string.replace_with("No long bold")
print(tag)

---Extremely bold
---<class 'bs4.element.NavigableString'> ---<b class="boldest">No long bold</b>

BeautifulSoup

BeautifulSoup對象表示的是一個文檔的所有內容.大部分時候,能夠把它看成 Tag 對象,它支持 遍歷文檔樹 和 搜索文檔樹 中描述的大部分的方法.

BeautifuSoup沒有name和attribute屬性。但有一個值爲[document]的特殊屬性.name

soup = BeautifulSoup('<b class="boldest">Extremely bold</b>',"html.parser")
print(soup.name)

---[document]

Comment

遍歷文檔樹

html_doc = """
<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>
"""

.content.children

tag的.contents屬性能夠將tag的子節點以列表的方式輸出:
經過tag的.children生成器,能夠對tag的子節點進行循環:

print(soup.title.contents)
print(soup.title.contents[0])

---["The Dormouse's story"]
---The Dormouse's story
for i in soup.head.children:
    print(i)

---<title>The Dormouse's story</title>

.descendants

.descendants屬性能夠對全部tag的子孫節點進行遞歸循環

print(soup.head.contents)
for child in soup.head.descendants:
    print(child)

print(len(list(soup.children)))
print(len(list(soup.descendants)))

---[<title>The Dormouse's story</title>] ---<title>The Dormouse's story</title>
---The Dormouse's story ---2 ---25

.string

若是tag只有一個NavigableString類型子節點,那麼這個tag可使用.string獲得子節點

print(soup.head.string)

---The Dormouse's story

.stringsstripped_strings

若是tag中有多個字符串,可使用.strings循環獲取
使用.stripped_strings能夠去除多餘空白內容:

for string in soup.stripped_strings:
    print(repr(string))

.parent.parents

經過.parent屬性來獲取某個元素的父節點
經過元素的.parents屬性能夠遞歸獲得元素的全部父輩節點。

for parent in soup.a.parents:
    if parent is None:
        print(parent)
    else:
        print(parent.name)

---p
---html
---[document]

兄弟節點

.next_sibling.previous_sibling

使用。next_sibling.previous_sibling屬性來查詢兄弟節點

實際文檔中的tag的 .next_sibling 和 .previous_sibling 屬性一般是字符串或空白。由於中間可能會隔着一些字符以及標點。

.next_siblings.previous_siblings

for sibling in soup.a.next_siblings:
    print(repr(sibling))

---',\n' ---<a class="sister" href="http://example.com/lacie" id="link2">Lacie</a> ---' and\n' ---<a class="sister" href="http://example.com/tillie" id="link3">Tillie</a> ';\nand they lived at the bottom of a well.'

重現解析過程

.next_element.previous_element

next_element屬性指向解析過程當中下一個被解析的對象(字符串或tag),結果可能與.next_sibling相同,但一般是不同的.

last_a_tag=soup.find("a",id="link3")
print(last_a_tag)
print(last_a_tag.next_sibling)
print(last_a_tag.next_element)

---<a class="sister" href="http://example.com/tillie" id="link3">Tillie</a> ---; ---and they lived at the bottom of a well. ---Tillie

.next_elements.previous_elements

搜索文檔樹

過濾器

字符串

正則表達式

for tag in soup.find_all(re.compile("^b")):
    print(tag.name)

列表

若是傳入列表參數,Beautiful Soup會將與列表中任一元素匹配的內容返回.

True

True能夠匹配任何值,可是不會返回字符串節點

方法

若是沒有合適過濾器,那麼還能夠定義一個方法,方法只接受一個元素參數,若是這個方法返回True表示當前元素匹配而且被找到,若是不是則反回False。

def has_class_but_no_id(tag):
    return tag.has_attr('class') and not tag.has_attr('id')

find_all()

name參數

keyword參數

soup.find_all(id='link2')

按CSS搜索

由於class是python保留字,因此用class_
例:
soup.find_all("a",class_="sister")

class_參數一樣接受不一樣類型的過濾器 ,字符串,正則表達式,方法或 True :

tag的class屬性是 多值屬性 .按照CSS類名搜索tag時,能夠分別搜索tag中的每一個CSS類名:

text參數

經過text參數能夠搜搜文檔中的字符串內容.

limit參數

limit參數限制返回結果的數量

recursive參數

調用tag的find_all()方法時,Beautiful Soup會檢索當前tag的全部子孫節點,若是隻想搜索tag的直接子節點,可使用參數 recursive=False.

簡寫

soup.find_all("a")
soup("a")
soup.title.find_all(text=True)
soup.title(text=True)

find()

只返回一個結果

find_parents()find_parent()

find_next_siblings()和find_next_sibling()`

find_all_next()find_next()

find_all_previous()find_previous()

CSS選擇器

在Tag或BeautifulSoup對象的.select()方法中傳入字符串參數,便可使用CSS選擇器的語法找到tag:

相關文章
相關標籤/搜索