python BeautifulSoup用法介紹

qq_41858657發表於2020-10-05

1.選擇解析器

直接選擇lxml,在lxml中有HTML和XML的功能,速度快,容錯能力強。

2.基本用法

from bs4 import BeautifulSoup
soup = BeautifulSoup(html,'lxml')        #BeautifulSoup物件初始化
print(soup.prettify())								#把要解析的字串按標準的縮排格式輸出
print(soup.titlte.string)							#輸出HTML中title節點的文字內容,string屬性用以獲取文字內容

3選擇器

3.1 節點選擇器

優點:通過屬性直接進行選擇,非常快速。
弊端:當有多個節點時,這種選擇方式只會選擇到第一個匹配的點,其他的後面節點都會忽略。

3.1.1 選擇元素

from bs4 import BeautifulSoup
soup=BeautifulSoup(html,'lxml')
print(soup.title)
print(type(soup.title))   #獲取資料型別  
print(soup.title.string)   #獲取文字的值
print(soup.head)
print(soup.p)     # 選擇p節點

上面獲取的資料型別為bs4.element.Tag型別,是BeautifulSoup中的一個重要資料結構。Tag具有一些屬性,比如string屬性,呼叫該屬性,可以獲取節點的文字內容,接下來的輸出結果正是節點的文字內容。

3.1.2 提取資訊

1)獲取名稱

print(soup.title.name)
  1. 獲取屬性
    利用attrs取屬性值
print (soup.p.attrs)
print(soup.p.attrs['name'])

或者直接取用在節點後用[]取用

print(soup.p['name'])
print(soup.p['class'])

3)獲取文字內容.string

print(soup.p.string)  ##獲取第一個p中的文字

3.1.3 巢狀選擇

html='''
<html><head><title>The Dormouse's story</title></head>
<body>
'''
from bs4 import BeautifulSoup
soup=BeautifulSoup(html,'lxml')
print(soup.head.title)
print(soup.head.title.string)

在呼叫head之後再呼叫title節點元素,可以依此做巢狀選擇

3.1.4 關聯選擇

1)獲取直接子節點
contents或者children

print(soup.p.contents)

contents會返回p節點中的子節點和文字
children同樣,但是結果是生成器型別

print(soup.p.children)
for i,child in enumerate(soup.p.children):
	print(i,child)
  1. 子孫節點
print(soup.p.descendants)
for i,child in enumerate(soup.p.descendants):
	print(i,child)

descendants會遞迴查詢所有子節點和孫節點,即一條一條返回所有的子節點和孫節點
3)父節點和祖先節點

print(soup.a.parent)   #選擇第一個a節點的直接父節點元素
print(soup.a.parents)  #選擇第一個a節點的所有父節點元素,返回生成器型別
print(list(enumerate(soup.a.parents)))  #利用列表輸出其索引和內容

4)兄弟節點

print(soup.a.next_sibling)   #獲取下一個節點
print(soup.a.previous_sibling)   #獲取上一個節點
print(list(enumerate(soup.a.next_siblings)))  #返回a後面的節點
print(list(enumerate(soup.a.next_siblings)))  #返回a前面的節點

5)提取資訊

print(soup.a.next_sibling.string) ##  獲取下一個節點的文字資訊
print(soup.a.parents)[0].attrs(['class']) ##獲取第一個父節點的屬性class

3.2 方法選擇器

find_all()和find()

3.2.1 find_all()

find_all() 顧名思議,查詢所有符合條件的元素,給它傳入一些屬性或文字,就可以得到符合條件的元素,功能十分強大。
API如下:

find_all(name,attrs,rescursive,text,**kwargs)

1)name

from bs4 import Beautifulsoup
soup=BeautifulSoup(html,'lxml')
print(soup.find_all(name='ul'))  ##查詢所有ul節點

2)巢狀查詢
因為上面name返回的是tag型別,所以可以繼續查詢,查詢ul之後的li節點

for ul in soup.find_all(name='ul'):
	print(ul.find_all(name='li'))

返回依然是tag型別,可以繼續查詢至li的文字內容

for ul in soup.find_all(name='ul'):
	print(ul.find_all(name='li'))
for li in ul.find_all(name='li'):
   print(li.string)
  1. attrs
    除了根據節點名查詢,還可以傳入一些屬性來查詢
print(soup.find_all(attrs={'id':'list-1'}))
print(soup.find_all(attrs={'name':'elements'}))

attrs引數是字典型別
對於一些常用的型別可以不用attrs來傳遞,可以直接寫入

print(soup.find_all(id='list-1'))
print(soup.find_all(class_='element'))

由於class在python裡是一個關鍵字,所有後面需要加一個下劃線
4)text
text引數用來匹配節點的文字,傳入的形式可以是字串,可以是正規表示式物件

print(soup.find_all(text=re.compile('link')))

上述輸入為正規表示式輸入,結果返回所有匹配正規表示式的節點文字組成的列表

3.2.2 find()

與前面的基礎用法一致,只返回單個元素
find_all() 與find()用法完全一致,只不過查詢範圍不同

find_parents(),find_parent()前者返回所有祖先節點,後者返回直接父節點
find_next_siblings(),find_next_sibling()前者返回所有兄弟節點,後者返回後面第一個兄弟節點
find_previous_siblings()和find_previous_sibling()前者返回前面所有的兄弟節點,後者返回前面第一個兄弟節點
find_all_text(),find_text() 前者返回所有符合條件的節點,後者返回第一個符合條件的節點
find_all_previous() ,find_previous()前者返回節點前所有符合條件的節點,後者返回第一個符合條件的節點

3.3 CSS選擇器

使用CSS選擇器只需要呼叫select()方法,傳入相應的CSS選擇器即可
1)基礎選擇

from bs4 import BeautifulSoup
soup=BeautifulSoup(html,'lxml')
print(soup.select('.panel.panel-heading'))  ## 選擇class為panel下class為panel-heading的節點
print(soup.select('ul li'))   ##選擇ul節點下的li節點
print(soup.select('#list-2.element'))    ##選擇id為list-2下class為element的節點內容

2)巢狀選擇

for ul in soup.select('ul'):
	print(ul.select('li'))

3)獲取屬性

for ul in soup.select('ul'):
	print(ul['id'])  
	print(ul.attrs['id'])
  1. 獲取文字
    除了string以外,還可以使用get_text()方法
for li in soup.select('li'):
	print(li.get_text())
	print(li.string)

4 總結

推薦使用lxml解析庫,必要時使用html.parser

節點選擇篩選功能弱但是速度快

建議使用find()或者find_all()查詢匹配單個結果或者多個結果

如果對CSS選擇器熟悉的話,可以使用select() 方法選擇

相關文章