Python のライブラリ BeautifulSoup を使って HTML を加工したいときの小ネタ集です。
以下すべてのサンプルコードでこの↓ import
文が省略されています。
from bs4 import BeautifulSoup
目次
- タグの属性を追加する
- タグの属性を削除する
- タグの中身を削除する
- 中身を残してタグを削除する
- タグとその中身を削除する
- タグの種類を変更する
- タグを特定の文字列に置き換える
- 空白文字だけのテキスト要素を削除する
タグの属性を追加する
属性を追加するには tag.attrs
に要素を追加します。
tag.attrs
はシンプルな dict
です。
soup = BeautifulSoup('', 'html.parser')
tag = soup.new_tag('p')
print(tag)
# => <p></p>
tag.attrs['class'] = 'mx4'
print(tag)
# => <p class="mx4"></p>
タグの属性を削除する
特定の属性を削除するには tag.attrs[name]
に対して del
を使います。
del tag.attrs['style']
すべての属性を削除するには tag.attrs.clear()
を使います。
tag.attrs.clear()
タグの中身を削除する
タグを残してその子要素だけ削除したい場合は tag.clear()
を使います。
soup = BeautifulSoup('', 'html.parser')
a_tag = soup.new_tag('a')
a_tag.attrs['href'] = '/sample'
a_tag.string = 'Click here'
a_tag
# => <a href="/sample">Click here</a>
a_tag.clear()
print(a_tag)
# => <a href="/sample"></a>
中身を残してタグを削除する
逆に、タグの中身を残してタグだけ削除したい場合は tag.unwrap()
を使います。
soup = BeautifulSoup('', 'html.parser')
# 子に `p` タグを持った `div` タグをツリーに追加する
div_tag = soup.new_tag('div')
p_tag = soup.new_tag('p')
p_tag.string = 'Hello'
div_tag.append(p_tag)
soup.append(div_tag)
print(div_tag)
# => <div><p>Hello</p></div>
# `div` タグを中身を残して削除する
div_tag.unwrap()
print(soup)
# => <p>Hello</p>
タグとその中身を削除する
タグをその子要素も含めてツリーから削除したい場合は tag.extract()
を使います。
tag.extract()
タグの種類を変更する
タグの種類をするには wrap()
と unwrap()
を使います。
def change_tag(soup, tag, new_tag_name: str, copy_attrs: bool = False):
"""タグを別のタグに置き換える"""
new_tag = soup.new_tag(new_tag_name)
new_tag.attrs = tag.attrs.copy()
tag.wrap(new_tag)
tag.unwrap()
return new_tag
この change_tag()
は次のように利用できます。
soup = BeautifulSoup('', 'html.parser')
# `p` タグをツリーに追加する
p_tag = soup.new_tag('p')
p_tag.string = 'Hello'
soup.append(p_tag)
# `p` タグを `div` タグに変換する
new_tag = change_tag(soup, p_tag, 'div')
print(new_tag)
# => '<div>Hello</div>'
もしタグの属性を持ち越したい場合は上の copy_attrs
が True
のときの処理を行います。
タグを特定の文字列に置き換える
タグの特定の文字列に置き換えて削除するには tag.insert()
tag.append()
tag.unwrap()
あたりを駆使します。
たとえば <pre>
タグを Markdown のコードブロックに変換するには次のようにします。
def change_pre_to_markdown_codeblock(pre_tag):
pre_tag.insert(0, '\n\n```')
pre_tag.append('```\n\n')
pre_tag.unwrap()
この change_pre_to_markdown_codeblock()
は次のようして使います。
soup = BeautifulSoup('', 'html.parser')
pre_tag = soup.new_tag('pre')
pre_tag.string = '\nprint("Hello")\n'
soup.append(pre_tag)
print(soup)
# => <pre>
# => print("Hello")
# => </pre>
change_pre_to_markdown_codeblock(pre_tag)
print(soup)
# =>
# => ```
# => print("Hello")
# => ```
# =>
空白文字だけのテキスト要素を削除する
等の空白文字だけからなるテキスト要素を削除するには replace_with()
を使います( WYSIWYG 等を使って書いた HTML の中にこのような要素が混入することがあります)。
import re
for text_element in soup.find_all(string=re.compile(r'^\s+$')):
text_element.replace_with('')