BeautifulSoup
アセンブラの魔女 ⧫ BeautifulSoup ⧫ パースツリー
アセンブラの魔女 ⧫ BeautifulSoup ⧫ パースツリー
パースツリー
ツリーのナビゲート
 parent
 contents
 string
 nextSiblingとpreviousSibling
 nextとprevious
 タグの繰り返し処理
 タグ名をメンバーとして使う
パースツリーの検索
 パーサーオブジェクト(BeautifulSoup やBeautifulStoneSoupのインスタンス)は、HTMLやXMLの構造に対応するように接続された深いネストのデータ構造を持ちます。これをこのドキュメントでは「パースツリー」と呼んでいます。パーサーオブジェクトには2つのタイプのオブジェクトがあります。一つはTagオブジェクトで<TITLE>のようなHTMLやXMLのタグに対応します。もう一つはNavigableStringオブジェクトで"Page title"や"This is paragraph"のような文字列に対応します。NavigableStringオブジェクトには、特別なXML構文に対応する、CData, Comment, Declaration, ProcessingInstructionなどのサブクラスもあります。これらのサブクラスはサブクラスの持つエクストラデータを出力する場合を除いて、NavigableStringオブジェクトと同じように振舞います。  Tagオブジェクトは以下のメンバーを持ちます。NavigableStringオブジェクトもcontentsとstring以外のすべてのメンバーを持ちます。  以下の構造のHTMLドキュメントで、<HEAD>に対応するTagオブジェクトのparentは<HTML>に対応するTagオブジェクトとなります。<HTML>に対応するTagオブジェクトのparentはBeautifulSoup(またはBeautifulStoneSoup)パーサーオブジェクトになります。このパーサーオブジェクトのparentはNoneとなります。
<html>
  <head>
    <title>
...
 以下はサンプルコードです。
#coding: UTF-8

from BeautifulSoup import BeautifulSoup
doc = ['<HTML><head><TITLE>Page title</title></head>',
  '<body><p id="para1" align="left">paragraph-1',
  '<p id="para2" align="center">paragraph-2',
  '<div class = cls1>cls1<b>test</b><div class=cls2>class2 div</div></div>'
  '</html>']
soup = BeautifulSoup(''.join(doc))

# <head>Tagのparentは<html>Tag
print soup.head.parent.name

# <head>Tagのparentのparentは<html>BeautifulSoup
print soup.head.parent.parent.__class__.__name__

# BeautifulSoupのparentはNone
print soup.parent
 上記のコードを実行すると、以下が出力されます。
html
BeautifulSoup
None
 parentによってツリーを上に移動することができますが、contentsを使うとツリーを下に移動することができます。contentsはページ要素のTagやobjects オブジェクトの順番のリストです。トップレベルのパーサーオブジェクトとTagオブジェクトのみがcontentsを持ちます。NavigableStringは文字列なのでサブ要素を持つことができないのでcontentsを持ちません。
#coding: UTF-8

from BeautifulSoup import BeautifulSoup
doc = ['<HTML><head><TITLE>Page title</title></head>',
  '<body><p id="para1" align="left">paragraph-1',
  '<p id="para2" align="center">paragraph-2',
  '<div class = cls1>cls1<b>test</b><div class=cls2>class2 div</div></div>'
  '</html>']
soup = BeautifulSoup(''.join(doc))

# <head>Tagのparentは<html>Tag
pBody = soup.body

print pBody.contents
上記のスクリプトを実行すると、以下のように<body>の下のサブ要素が表示されます。
[<p id="para1" align="left">paragraph-1</p>, <p id="para2" align="center">paragraph-2<div class="cls1">cls1<b>test</b><div class="cls2">class2 div</div>
</div></p>]
 タグが1つだけのチャイルドノードを持ち、そのチャイルドノードが文字列の場合、それはtag.stringとして参照することができます。
#coding: UTF-8
from BeautifulSoup import BeautifulSoup
doc = "<html><head><title>Page title</title></head><body><p>paragraph-1</html>"
soup = BeautifulSoup( doc )
pBody = soup.body
上記のスクリプトを実行すると、<title>タグの内容(文字列)"Page Title"が表示されます。  nextSiblingとpreviousSiblingはパースツリーの同じ階層の前後のノードへのリンクです。以下の構造のHTMLドキュメントの場合、&lh;head>タグのnextSiblingは&lh;body>タグ、&lh;body>タグのpreviousSiblingは&lh;head>タグとなります。
<html>
  <head>
    <title>
      Page title
    </title>
  </head>
  <body>
..
 以下のスクリプトを実行すると、<head>タグと同じ階層の次のノード<body>タグの名前"body"が表示されます。
#coding: UTF-8
from BeautifulSoup import BeautifulSoup
doc = "<html><head><title>Page title</title></head><body>body</body></html>"
soup = BeautifulSoup( doc )
print soup.head.nextSibling.name
 nextとpreviusもnextSiblingとpreviousSiblingと同じようにノード間のリンクのためのメンバーですが、nextとpreviusはノードがパーサーのよって処理された順番でリンクされます(おそらくドキュメント上でのタグの出現順)。
 タグをリストとして扱うことで、タグの内容を繰り返し処理することができます。たとえば、次のような書き方ができます。
from BeautifulSoup import BeautifulSoup
doc = \"<html><head><title>Page title</title></head><body><div>__div1__</div><div>__div2__</div></body></html>\"
soup = BeautifulSoup( doc )

#<body>のサブノードの数を表示
print len( soup.body )

#<body>のサブノードを表示
for subNode in soup.body:
  print subNode
 上記のスクリプトを実行すると、以下が出力されます。
2
<div>__div1__</div>
<div>__div2__</div>
 パーサーやTagオブジェクトのメンバーとしてタグ名を使うこともできます。これはあらかじめドキュメントの構造が分かっている場合に便利な方法です。
#coding: UTF-8
from BeautifulSoup import BeautifulSoup
doc = \"<html><head><title>Page title</title></head><body><div>__div1__</div><div>__div2__</div></body></html>\"
soup = BeautifulSoup( doc )
print \"head =\", soup.head
print \"title=\", soup.head.title
 上記のスクリプトを実行すると、以下が出力されます。
head = <head><title>Page title</title></head>
title= <title>Page title</title>
 この方法では、同じ親ノードに同じ名前のタグが複数ある場合、最初に出現するノードだけが参照されます。たとえば、以下のコードでは<body>タグには二つの<div>タグがありますがbodyのdivメンバーとして参照できるのは、最初の<div>となります。タグ名で参照できるメンバーはリストではないので5行目のような書き方はできません。二番目の<div>タグを参照するには7行目のような書き方をします。このような書き方(タグ名で表現されるメンバー)は実際にはfirstメソッドのエイリアスです。
#coding: UTF-8
from BeautifulSoup import BeautifulSoup
doc = "<html><head><title>Page title</title></head><body><div>__div1__</div><div>__div2__</div></body></html>"
soup = BeautifulSoup( doc )
#print soup.body.div[1]
print soup.body.div
print soup.body.contents[1]
 タグ名の最後に"Tag"をつけた名前のメンバーも使うことができます。たとえば、object.bodyで参照されるタグはobject.bodyTagという名前でも参照することができます。
#coding: UTF-8
from BeautifulSoup import BeautifulSoup
doc = \"<html><head><title>Page title</title></head><body><div>__div1__</div><div>__div2__</div></body></html>\"
soup = BeautifulSoup( doc )

#soup.headと同じ意味
print \"head =\", soup.headtag

#soup.head.titleと同じ意味
print \"title=\", soup.headTag.titleTag
 Pythonの識別子として無効なタグ名(たとえばハイフン付きの名前)を使う場合、ここで説明した方法は使えません。この場合は、findメソッドを使います。  Beautiful Soupは構文解析ツリーをたどったり、指定した条件に一致するTagオブジェクトやNavigableStringオブジェクトを取得するためのメソッドを持っています。 findAll
 条件にマッチするすべてのTagオブジェクトとNavigableStringオブジェクトを検索する
▼ Property
記事情報
datePublished2011-01-01
dateModified2018-06-27
authorアセンブラの魔女
headlinePython用HTML/XMLパーサー「BeautifulSoup」のパースツリー(Parse Tree)についての説明ページです
keywordsBeautifulSoup
keywordsPython
keywordsXMLパーサー
keywordsHTMLパーサー
keywordsパース
keywordsparse
publisher name= wiredFish, logo.name= wiredFish, logo.url= https://books-nekoya.jp/Programming/chigu-hagu-title-01.png size= 208 pixel x 50 pixel
image.url url= https://books-nekoya.jp/Programming/chigu-hagu-title-01.png , size= 208 pixel x 50 pixel