1. ホーム
  2. パイソン

Beautiful Soupを学ぶ(5) -- BeautifulSoupでウェブコンテンツを変える

2022-02-26 22:19:09

BeautifulSoupは、Webコンテンツの検索や位置確認だけでなく、Webページの修正も可能です。 修正とは、タグの追加・削除、タグ名の変更、タグ属性の変更、テキスト内容の変更などができることです。

 FixBeautifulSoupでタグを修正する

BeautifulSoup内部では、各タグはタグオブジェクトとして扱われ、このオブジェクトは以下の作業を行うことができます。

  • タグ名の変更
  • タグの属性を変更する
  • 新しいタグを追加する
  • 既存のタグを削除する
  • タグのテキスト内容を変更する

タグの名前を変更する

.nameパラメータを変更するだけで、タグ名を変更することができます。

producer_entries.name = "div"<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255); ">如何嘛</span><img src="file:///C:\Users\ADMINI~1\AppData\Local\Temp\~LWHD)}S}%DE5RTOO[CVEI1.gif" sysface= "15" style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);" alt="" />

なぜ、そんなことを言うのですか? 


タグの属性を変更する

class,id,styleなどのタグ属性の変更。属性は辞書として保存されるので、タグの属性を変更するには、単にpythonの辞書を扱えばよいのです。

既に属性を持つタグを更新する

以下のコードを参照することができます。

producer_entries['id']="producers_new_value"





タグに新しい属性を追加する

例えば、タグにclass属性がない場合、以下のコードを参照してclass属性を追加することができます。

producer_entries['class']='newclass'





タグの属性を削除する

del演算子を使うと、次のようになります。

del producer_entries['class']





新しいタグを追加する

BeautifulSoupには、新しいタグを作成するためのnew_tag()メソッドがあります。新しいタグは、append(), insert(), insert_after(), insert_before() などのメソッドを使用して挿入することができます。

新しいプロデューサーを追加するには、new_tag() を使用し、次に append() を使用します。

先ほどの例を参考に、生産者のplantとalageに加え、今度はphytoplanktonを追加してみます。まず、liタグを最初に作成する必要があります。

new_tag()で新しいタグを作成します。

new_tag()メソッドは、BeautifulSoupオブジェクトにしか使えません。では、liオブジェクトを作成してみましょう。

soup = BeautifulSoup(html_markup,"lxml")
new_li_tag = soup.new_tag("li")





new_tag()オブジェクトの必須パラメータはタグ名で、その他のタグ属性パラメータやその他のパラメータは任意です。例

new_atag=soup.new_tag("a",href="www.example.com")





new_li_tag.attrs={'class':'producerlist'}





append() メソッドを使用して新しいタグを追加する

Pythonのリストメソッドappend()と同じように、append()メソッドはコンテンツの後ろに新しいタグを追加します。

producer_entries = soup.ul
producer_entries.append(new_li_tag)





ulタグの子であるliタグに、新しいタグを追加した後の出力です。

<ul id="producers">
<li class="プロデューサーリスト">
<div class="名前">
植物
</div>
<div class="数字">
100000
</div>
</li>
<li class="プロデューサーリスト">
<div class="名前">
藻類
</div>
<div class="数字">
100000
</div>
</li>s
<li class="プロデューサーリスト">
</li>


</ul>

insert()を使って、liタグに新しいdivタグを追加します。

append() は .contents の後に新しいタグを追加しますが、insert() はそうではありません。挿入する場所を指定する必要があります。PythonのInsert()メソッドと同じです。

new_div_name_tag=soup.new_tag("div")
new_div_name_tag["class"]="name"
new_div_number_tag=soup.new_tag("div")
new_div_number_tag["class"]="number"





まず、2つのdivタグが作成されます。

new_li_tag.insert(0,new_div_name_tag)
new_li_tag.insert(1,new_div_number_tag)
print(new_li_tag.prettify())





その後、挿入が行われ、次のような出力が得られます。

<li class_="producerlist">
<div class="名前">
</div>
<div class="数字">
</div>

</li>

文字列の内容を変更する

上記の例では、タグが追加されただけで、タグの中にコンテンツはありません。コンテンツを追加したい場合は、BeautifulSoupでそれも可能です。

.stringで文字列の内容を変更する

例えば

new_div_name_tag.string="phytoplankton"
print(producer_entries.prettify())

出力はこのようになります。

<ul id="producers">
<li class="プロデューサーリスト">
<div class="名前">
植物
</div>
<div class="数字">
100000
</div>
</li>
<li class="プロデューサーリスト">
<div class="名前">
藻類
</div>
<div class="数字">
100000
</div>
</li>
<li class="プロデューサーリスト">
<div class="名前">
植物プランクトン
</div>

<div class="数字">
</div>
</li>
</ul>

.append/(), insert(), new_string() を使って文字列を追加する

append()とinsert()を使用すると、新しいタグを追加する際に使用するのと同じ効果があります。例えば

new_div_name_tag.append("producer")
print(soup.prettify())





出力します。

<html>
<body>
<div class="ecopyramid">
<ul id="producers">
<li class="producerlist">
<div class="name">
plants
</div>
<div class="number">
100000
</div>
</li>
<li class="producerlist">
<div class="name">
algae
</div>
<div class="number">
100000
</div>
</li>
<li class="producerlist">
<strong><div class="name">
phytoplankton
producer
</div>
</strong><div class="number">
</div>
</li>
</ul>
</div>
</body>
</html>





また、new_string() メソッドには

new_string_toappend = soup.new_string("producer")
new_div_name_tag.append(new_string_toappend)





ページ内のタグを削除する

タグを削除するメソッドは、decomose()とextract()です。


decompose() によるプロデューサの削除


ここで、class="name"属性の付いたdivタグを削除し、decompose()メソッドを使用します。

third_producer = soup.find_all("li")[2]
div_name = third_producer.div
div_name.decompose()
print(third_producer.prettify())





出力します。

<li class_="producerlist">
<div class_="数字">
10000
</div>

</li>

decompose()メソッドは、タグとタグの子を削除します。

extract() を使用してプロデューサーを削除する

extract() は、HTMNL ドキュメントからタグや文字列を削除するために使用します。さらに、削除されたタグや文字列へのハンドルも返します。decompose() とは異なり、extract は文字列に対しても使用することができます。

third_producer_removed=third_producer.extract()
print(soup.prettify())





BeautifulSoupを使ってタグの内容を削除する

タグは子としてNavigableStringオブジェクトまたはタグオブジェクトを持つことができます。これらの子オブジェクトの削除は、clear() を使って行うことができます。

例えば、植物が描かれたdivタグと、それに対応するclass=number属性タグを削除することができます。

li_plants=soup.li





li_plants.clear()





出力します。

<li class="プロデューサーリスト"></li>

liに関連するタグの内容がきれいに削除されているのがわかると思います。


コンテンツを修正するための特殊機能

BeautifulSoupには、先ほど見たメソッド以外にも、コンテンツを修正するためのメソッドが用意されています。

  • Insert_after()、Insert_before()メソッド。

これら2つのメソッドは、タグや文字列の前や後に挿入するために使用されます。このメソッドに必要なパラメータは、NavigavleStringとタグ・オブジェクトだけです。

soup = BeautifulSoup(html_markup,"lxml")
div_number = soup.find("div",class_="number")
div_ecosystem = soup.new_tag("div")
div_ecosystem['class'] = "ecosystem"
div_ecosystem.append("soil")
div_number.insert_after(div_ecosystem)
print(soup.prettify())





出力します。

<html>
<body>
<div class="エコピラミッド">
<ul id="プロデューサー">
<li class="プロデューサーリスト">
<div class="名前">
植物
</div>
<div class="数字">
100000
</div>
<div class="エコシステム">
土壌
</div>

</li>
<li class="プロデューサーリスト">
<div class="名前">
藻類
</div>

<div class="数字">
100000
</div>
</li>
</ul>
</div>
</body>
</html>


  • replace_with()メソッドです。

このメソッドは、既存のタグや文字列を新しいタグや文字列に置き換えるために使用されます。replace_with() は、置換されるラベルや文字列へのハンドルを返します。

soup = BeautifulSoup(html_markup,"lxml")
div_name =soup.div
div_name.string.replace_with("phytoplankton")
print(soup.prettify())





replace_with() は、タグを完全に置き換えるために使用することもできます。

  • wrap() および unwrap() メソッド。

wrap() メソッドは、タグや文字列をタグや文字列の外側で囲むために使用します。例えば、liタグの中にあるコンテンツ全体をdivタグで囲むことができます。

li_tags = soup.find_all("li")
for li in li_tags:
<span style="white-space:pre"> </span>new_divtag = soup.new_tag("div")
<span style="white-space:pre"> </span>li.wrap(new_divtag)
print(soup.prettify())





そして、unwrap()はwrap()が行うことの反対を行います。 unwrap()はreplace_with()と同様に、置き換えられたタグへのハンドルを返します。