Warning: Undefined variable $position in /home/pystyles/pystyle.info/public_html/wp/wp-content/themes/lionblog/functions.php on line 4897

スクレイピング – Beautiful Soup の DOM ツリーの編集方法まとめ

スクレイピング – Beautiful Soup の DOM ツリーの編集方法まとめ

概要

Beautiful Soup で DOM ツリーに要素を追加したり、既存の要素を削除する方法を解説します。

Advertisement

関連記事

機能一覧

メソッド 概要
append(要素) 子要素の末尾に追加する
extend(要素) 子要素の末尾に複数追加する
`insert(i, 要素) I 番目の子要素の直前に追加する
insert_before(要素) この要素の直前に追加する
insert_after'(要素) この要素の直後に追加する
clear() この要素の子孫を削除する
extract() この要素を DOM ツリーから削除して返す
decompose() この要素を DOM ツリーから削除する
replace_with(要素) この要素を指定した要素で置き換える
wrap(要素) この要素を指定した要素で囲む
unwrap() この要素 (子孫は含まない) を DOM ツリーから削除する
prettify() この要素を整形した HTML 文字列にして返す
str(要素) この要素を HTML 文字列にして返す
encode() この要素を UTF8 でエンコードされた HTML 文字列にして返す

要素名を変更する

Tag.name に文字列を代入することで、要素名を変更できます。

In [1]:
from bs4 import BeautifulSoup

soup = BeautifulSoup('<b class="boldest">Extremely bold</b>')

# 要素名を変更する。
soup.b.name = "blockquote"

print(soup)
<html><body><blockquote class="boldest">Extremely bold</blockquote></body></html>

属性値を変更、追加、削除する

Tag[<AttributeName>] に値を代入した場合、指定した属性が存在すれば属性値の変更、存在しない場合は新しく属性を追加することになります。また、属性は del で削除できます。

In [2]:
soup = BeautifulSoup('<b class="boldest">Extremely bold</b>')

# 属性値を変更する。
soup.b["class"] = "verybold"

# 属性を追加する。
soup.b["id"] = 1
print(soup)

# 属性を削除する。
del soup.b["class"]
print(soup)
<html><body><b class="verybold" id="1">Extremely bold</b></body></html>
<html><body><b id="1">Extremely bold</b></body></html>

値を変更する

Tag.string に文字列を代入することで、要素の値を変更できます。

In [3]:
soup = BeautifulSoup('<a href="http://example.com/">I linked to <i>example.com</i></a>')

# 値を変更する。
soup.a.string = "New link text."
print(soup.a)
<a href="http://example.com/">New link text.</a>
Advertisement

子を追加する

子要素の末尾に追加する

Tag.append(要素 or 文字列) で子要素の末尾に文字列や要素を追加できます。

In [4]:
# "a" 要素の子に文字列 "Bar" を追加する。
soup = BeautifulSoup("<a>Foo</a>")
soup.a.append("Bar")
print(soup)

# タグを追加したい場合は new_tag() でまずタグを作成する。
soup = BeautifulSoup("<b></b>")
new_tag = soup.new_tag("a", href="http://www.example.com")

# "a" 要素の子に文字列 "a" 要素を追加する。
soup.b.append(new_tag)
print(soup)
<html><body><a>FooBar</a></body></html>
<html><body><b><a href="http://www.example.com"></a></b></body></html>

Tag.extend(要素 or 文字列) で子要素の末尾に複数の文字列や要素を追加できます。

In [5]:
# "a" 要素の子に文字列 "Soup", "Guide" を追加する。
soup = BeautifulSoup("<a>Beautiful</a>")
soup.a.extend(["Soup", "Guide"])
print(soup)
<html><body><a>BeautifulSoupGuide</a></body></html>

指定した子要素の直前に追加する

Tag.insert(n, 要素 or 文字列)n 番目の子要素の直前に文字列や要素を追加できます。

In [6]:
# "a" 要素の子に "Bar" を挿入する。
soup = BeautifulSoup("<a>Foo</a>")
soup.a.insert(0, "Bar")
print(soup)
<html><body><a>BarFoo</a></body></html>

兄弟要素を追加する

指定した要素の直前に追加する

Tag.insert_before(要素 or 文字列) でこの要素の直前に要素や文字列を追加できます。

In [7]:
# "b" 要素の直前に挿入する。
soup = BeautifulSoup("<b>stop</b>")
tag = soup.new_tag("i")
soup.b.insert_before(tag)
print(soup)
<html><body><i></i><b>stop</b></body></html>

指定した要素の直後に追加する

Tag.insert_after(要素 or 文字列) でこの要素の直後に要素や文字列を追加できます。

In [8]:
# "b" 要素の直後に挿入する。
soup = BeautifulSoup("<b>stop</b>")
tag = soup.new_tag("i")
soup.b.insert_after(tag)
print(soup)
<html><body><b>stop</b><i></i></body></html>

削除する

子孫ノードを削除する

Tag.clear() でこの要素のすべての子孫要素を削除できます。

In [9]:
soup = BeautifulSoup('<a href="http://example.com/">I linked to <i>example.com</i></a>')
print(soup.a)

# "a" 要素の子孫をすべて削除する。
soup.a.clear()
print(soup.a)
<a href="http://example.com/">I linked to <i>example.com</i></a>
<a href="http://example.com/"></a>

この要素を DOM ツリーから削除して返す

Tag.extract() でこの要素を DOM ツリーから削除して返します。

In [10]:
soup = BeautifulSoup('<a href="http://example.com/">I linked to <i>example.com</i></a>')

# "i" 要素を DOM ツリーから削除して、その要素を返す。
removed_tag = soup.i.extract()
print(removed_tag)
print(soup)
<i>example.com</i>
<html><body><a href="http://example.com/">I linked to </a></body></html>

この要素を DOM ツリーから削除する

Tag.decompose() でこの要素を DOM ツリーから削除します。

In [11]:
soup = BeautifulSoup('<a href="http://example.com/">I linked to <i>example.com</i></a>')

# "i" 要素を DOM ツリーから削除する。
soup.i.decompose()

print(soup)
<html><body><a href="http://example.com/">I linked to </a></body></html>

この要素のみを DOM ツリーから削除する

Tag.extract()Tag.decompose() との違い、Tag.unwrap() はこの要素のみを削除し、その子孫要素はそのまま残します。

In [12]:
soup = BeautifulSoup('<a href="http://example.com/">I linked to <i>example.com</i></a>')

# "i" 要素を取り除く。
soup.a.i.unwrap()
print(soup)
<html><body><a href="http://example.com/">I linked to example.com</a></body></html>

要素を置換する

Tag.replace_with(要素 or 文字列) でこの要素を指定した要素や文字列で置換します。

In [13]:
soup = BeautifulSoup('<a href="http://example.com/">I linked to <i>example.com</i></a>')

b_tag = soup.new_tag("b")
b_tag.string = "example.net"

# "i" タグを "b" タグに置換する。
soup.a.i.replace_with(b_tag)
print(soup)
<html><body><a href="http://example.com/">I linked to <b>example.net</b></a></body></html>
Advertisement

指定した要素で囲む

Tag.wrap(要素) でこの要素を指定した要素で囲みます。

In [14]:
soup = BeautifulSoup("<p>I wish I was bold.</p>")

# "p" 要素の値を "b" 要素で囲む。
b_tag = soup.p.string.wrap(soup.new_tag("b"))
print(b_tag)

print(soup)
<b>I wish I was bold.</b>
<html><body><p><b>I wish I was bold.</b></p></body></html>

DOM ツリーを HTML で出力する

整形した HTML で出力する

Tag.prettify() で指定した要素以下を整形された HTML 文字列に変換して返します。 formatter="html" を指定した場合、Unicode 文字は HTML エンティティに変換します。

In [15]:
soup = BeautifulSoup("<p>Il a dit &lt;&lt;Sacr&eacute; bleu!&gt;&gt;</p>")

print(soup.prettify())

# Unicode 文字は HTML エンティティに変換して出力する。
# é が &eacute; に変換されている。
print(soup.prettify(formatter="html"))
<html>
 <body>
  <p>
   Il a dit &lt;&lt;Sacré bleu!&gt;&gt;
  </p>
 </body>
</html>
<html>
 <body>
  <p>
   Il a dit &lt;&lt;Sacr&eacute; bleu!&gt;&gt;
  </p>
 </body>
</html>

formatter="html5" を指定した場合、空要素 br/ を付けないで変換します。

In [16]:
soup = BeautifulSoup("<br>")
print(soup.prettify())

soup = BeautifulSoup("<br>")
print(soup.prettify(formatter="html5"))
<html>
 <body>
  <br/>
 </body>
</html>
<html>
 <body>
  <br>
 </body>
</html>

formatter=None を指定した場合、なにも修正せずにそのまま変換します。

In [17]:
soup = BeautifulSoup("<br>")

# 何も変更を加えずに表示する。
print(soup.prettify(formatter=None))
<html>
 <body>
  <br/>
 </body>
</html>

整形せずに HTML で出力する

str(Tag) で指定した要素以下を HTML 文字列に変換できます。また、Tag.encode() で UTF8 でエンコードしたバイト列に変換できます。

In [18]:
soup = BeautifulSoup("<p>Il a dit &lt;&lt;Sacr&eacute; bleu!&gt;&gt;</p>")
print(str(soup))

print(soup.encode())
<html><body><p>Il a dit &lt;&lt;Sacré bleu!&gt;&gt;</p></body></html>
b'<html><body><p>Il a dit &lt;&lt;Sacr\xc3\xa9 bleu!&gt;&gt;</p></body></html>'

連続する NavigableString を1つに統合する

DOM ツリーを編集して、連続した NavigableString ができてしまった場合に、Tag.smooth() を呼び出すことで1つに統合できます。

In [19]:
soup = BeautifulSoup("<a>Foo</a>")
soup.a.append("Hoge")
soup.a.append("Fuga")
root (BeautifulSoup)
└── html (Tag)
    └── body (Tag)
        └── a (Tag)
            ├── 'Foo' (NavigableString)
            ├── 'Hoge' (NavigableString)
            └── 'Fuga' (NavigableString)
In [20]:
soup.smooth()
root (BeautifulSoup)
└── html (Tag)
    └── body (Tag)
        └── a (Tag)
            └── 'FooHogeFuga' (NavigableString)