05BeautifulSoup遍歷文檔書及搜索文檔樹

BeautifulSoup

1、什麼是BeautifulSoup

BS4是一個解析庫,能夠經過某種解析器來幫咱們提取想要的數據html

2、爲何用BS4

由於他能夠用簡潔的語法快速提取用戶想要的內容函數

3、安裝

# 安裝BeautifulSoup4
pip3 install beautifulsoup4

# 安裝解析器
# 根據官網解釋,推薦使用lxml
pip3 install lxml

4、基本使用

from bs4 import BeautifulSoup

html_doc = """
<html><head><title>The Dormouse's story</title></head>
<body>
<p class="sister"><b>$37</b></p>

<p class="story" id="p">Once upon a time there were three little sisters; and their names were
<a href="http://example.com/elsie" class="sister" >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>
"""
soup = BeautifulSoup(html_doc,'lxml')
#自動補全html標籤功能
print(soup)

html_doc = soup.prettify()
print(html_doc)

5、遍歷文檔樹

from bs4 import BeautifulSoup

html_doc = """
<html><head><title>The Dormouse's story</title></head>
<body>
<p class="sister"><b>$37</b></p>

<p class="story" id="p">Once upon a time there were three little sisters; and their names were
<a href="http://example.com/elsie" class="sister" >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>
"""
soup = BeautifulSoup(html_doc,'lxml')
#     一、直接使用
print(soup.html)
print(type(soup.html)) #類型變成了element_tag
print(soup.a)
#     二、獲取標籤的名稱
print(soup.a.name)
#     三、獲取標籤的屬性
print(soup.a.attrs)
#     四、獲取標籤的內容
print(soup.p.text)
#     五、嵌套選擇
print(soup.html.body.p)
#     六、子節點、子孫節點
print(soup.p.children)
#     七、父節點、祖先節點
print(soup.b.parent)
print(soup.b.parents)
#返回一個生成器
# 生成器:
def f():
    yield 1
    yield 2
    yield 3
    #把值放在生成器中

g=f() #expected results :<generator object parents at 0x000001C03E19E308>

for line in g:
    print(line)
#expected results 1 2 3
#      八、兄弟節點  (sibling: 兄弟姐妹)
print(soup.a)
# 獲取下一個兄弟節點
print(soup.a.next_sibling)
# 獲取下一個的全部兄弟節點,返回的是一個生成器
print(soup.a.next_siblings)
print(list(soup.a.next_siblings))

# 獲取上一個兄弟節點
print(soup.a.previous_sibling)
# 獲取上一個的全部兄弟節點,返回的是一個生成器
print(list(soup.a.previous_siblings))

6、搜索文檔樹

標籤查找與屬性查找:
    find與findall
    find找一個
    findall找全部
    標籤:
        - 字符串過濾器   字符串全局匹配
            name 屬性匹配
            attrs 屬性查找匹配
            text 文本匹配
    
        - 正則過濾器
            re模塊匹配
    
        - 列表過濾器
            列表內的數據匹配
    
        - bool過濾器
            True匹配
    
        - 方法過濾器
            用於一些要的屬性以及不須要的屬性查找。
        
    屬性:
        - class_
        - id
from bs4 import BeautifulSoup
import re

# 注意: 如何初始文本內有換行,也會算在裏面。(坑)
html_doc = """
<html><head><title>The Dormouse's story</title></head><body><p class="sister"><b>$37</b></p><p class="story" id="p">Once upon a time there were three little sisters; and their names were<a href="http://example.com/elsie" class="sister" >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>
"""


# 第一個參數是解析文本
# 第二個參數是解析器
soup = BeautifulSoup(html_doc, 'lxml')

'''
標籤查找與屬性查找:

    標籤:
        - 字符串過濾器   字符串全局匹配
            name 屬性匹配
            attrs 屬性查找匹配
            text 文本匹配
    
        - 正則過濾器
            re模塊匹配
    
        - 列表過濾器
            列表內的數據匹配
    
        - bool過濾器
            True匹配
    
        - 方法過濾器
            用於一些要的屬性以及不須要的屬性查找。
        
    屬性:
        - class_
        - id
'''


# 一、字符串
# find的默認參數 第一個是name、第二個是attrs、第四個是text
# name: 根據標籤名匹配節點
print(soup.find('p'))  # 獲取第一個p標籤
print(soup.find_all(name='p'))  # 獲取全部的p標籤

# attrs: 根據屬性查找匹配節點
print(soup.find(attrs={'id': 'p'}))  # 查找id爲p的標籤
print(soup.find_all(attrs={'class': 'sister'}))  # 查找class爲sister的全部標籤

# text: 根據文本匹配文檔樹內的文本
# 推薦配合其餘匹配規則使用,不然毫無心義
print(soup.find(text='$37'))  # 查找標籤內爲$37的文本

# name與text配合使用
print(soup.find_all(name='p', text='$37'))  # 查找全部文本爲$37的p標籤

# name與attrs配合使用
print(soup.find(name='a', attrs={'id': 'link2'}))  # 查找第一個id爲link2的a標籤

# attrs與text配合使用
print(soup.find_all(attrs={'id': 'link2'}, text='Lacie'))  # 查找全部id爲link2,文本爲Lacie的標籤

# name、attrs、text組合使用
print(soup.find_all(name='a', attrs={'id': 'link3'}, text='Tillie'))  # 查找全部id爲link3,文本爲Tillie的a標籤


# 二、正則
print(soup.find(name=re.compile('a')))  # 經過第一個標籤名帶有a的節點
print(soup.find_all(attrs={'id': re.compile('link')}))  # 匹配全部id名帶有link的節點
print(soup.find_all(text=re.compile('and')))  # 匹配全部文本帶有"and"的節點


# 三、列表 (列表內能夠匹配多個)
print(soup.find_all(name=['a', re.compile('e')]))  # 匹配全部a標籤節點與全部標籤中帶有e的節點
print(soup.find_all(text=['$']))  # 找不到,由於$是精確查找
print(soup.find_all(text=['$37']))  # 查找$37文本,這樣查找是沒有意義的
print(soup.find_all(text=[re.compile('\$')]))  # 正則中$是特殊字符,因此須要轉義


# 四、bool
print(soup.find_all(name=True))  # 查找全部有標籤名的節點
print(soup.find_all(attrs={'id': True}))  # 查找全部有id的節點
print(soup.find_all(text=True))  # 查找全部文本


# 五、方法
# 寫一個只要有class沒有id的a標籤的函數
def has_class_not_id(arg):
    if arg.name == 'a' and arg.has_attr('class') and not arg.has_attr('id'):
        return arg.name

print(soup.find_all(name=has_class_not_id))  # 經過has_class_not_id的函數匹配節點


# 六、標籤與屬性查找
# 標籤
print(soup.find_all(attrs={'class': 'sister'}))

# 屬性
# 根據class屬性查找,由於class是關鍵字,因此後面須要加下劃線
print(soup.find_all(class_='sister'))
# 根據id屬性查找
print(soup.find_all(id='link2'))
相關文章
相關標籤/搜索