2011年4月9日土曜日

ドキュメントの解析

Beautiful SoupコンストラクタはXMLやHTMLドキュメントを文字形式(やファイルのようなオブジェクトを開いて)で引数に取ります。また、Beautiful Soupコンストラクタはドキュメントを解析し、対応するデータ構造をメモリー中に作成します。

Beautiful Soupに完全な形式のドキュメントを渡したら、解析されたデータ構造は、元のドキュメントと全く同じに見えます。しかし、ドキュメントに何か問題がある場合、Beautiful Soupはデータ構造に対して、合理的な構造を見つけ出すために、ヒューリスティックを使用します。


HTMLの解析


HTMLドキュメントを解析するために、Beautiful Soupクラスを使用します。ここでは、BeautifulSoupが知っていることをいくつか示します:
  • ネスト出来るタグ(<BLOCKQUOTE>)があり 、出来ないタグ(<P>)がある。
  • Table タグと list タグには、自然なネストの順序がある。例えば、
    <TD> タグは <TR> タグ中にあり、それ以外の箇所では使われない。
  • <SCRIPT> タグの中身はHTMLとして解析されるべきではない。
  • <META> タグはドキュメントのエンコーディングを指定するかもしれない。
ここで、実際の動作をご覧ください:
from BeautifulSoup import BeautifulSoup
html = "<html><p>Para 1<p>Para 2<blockquote>Quote 1<blockquote>Quote 2"
soup = BeautifulSoup(html)
print soup.prettify()
# <html>
#  <p>
#   Para 1
#  </p>
#  <p>
#   Para 2
#   <blockquote>
#    Quote 1
#    <blockquote>
#     Quote 2
#    </blockquote>
#   </blockquote>
#  </p>
# </html>
BeautifulSoupは、たとえ元のドキュメントに終了タグがなくても、終了タグを置くのにふさわしい場所を見つけることに注意してください。
元のドキュメントは正しいHTMLではありませんが、それほど悪いHTMLでもありません。

ここに、本当にひどいドキュメントがあります。
終了タグの欠落以外の問題の中でも、 <FORM>タグが <TABLE>タグの外側で始まり、 <TABLE>タグの中で終了しています(このようなHTMLは主なweb企業によって運営されているウェブサイトで見つけられます。)
from BeautifulSoup import BeautifulSoup
html = """
<html>
<form>
 <table>
 <td><input name="input1">Row 1 cell 1
 <tr><td>Row 2 cell 1
 </form> 
 <td>Row 2 cell 2<br>This</br> sure is a long cell
</body> 
</html>"""
Beautiful Soupは、このドキュメントも同様に処理します:
print BeautifulSoup(html).prettify()
# <html>
#  <form>
#   <table>
#    <td>
#     <input name="input1" />
#     Row 1 cell 1
#    </td>
#    <tr>
#     <td>
#      Row 2 cell 1
#     </td>
#    </tr>
#   </table>
#  </form>
#  <td>
#   Row 2 cell 2
#   <br />
#   This 
#   sure is a long cell
#  </td>
# </html>
テーブルの最後のセルが <TABLE> タグの外側にあります;
Beautiful Soupは、 <FORM> タグを閉じる時、 <TABLE> タグを閉じることを決定します。
おそらく、元のドキュメントの著者は、 <FORM> タグがテーブルの終わりまで拡張されると考えたのでしょう、しかし、Beautiful Soupはそのことを知る由もありません。
このような変な場合でも、Beautiful Soupは不良ドキュメントを解析し、全てのデータにアクセスできるようにしてくれます。


XMLの解析


BeautifulSoup クラスは、HTML作者の意図を推測するため、webブラウザのようにヒューリスティックがたくさんあります。
しかし、 XML は修正タグの集合を持っておらず、そのため、これらのヒューリスティックは適用されません。したがって、 BeautifulSoup は、 XML をうまく扱えません.
XML ドキュメントを解析するためには、BeautifulStoneSoup クラスを使ってください。
BeautifulStoneSoup は、あらゆるXML方言についての特別な知識がいらず、タグのネストについての極めて単純なルールを持つ、一般的なクラスです:
ここで、実際の動作をご覧ください:
from BeautifulSoup import BeautifulStoneSoup
xml = "<doc><tag1>Contents 1<tag2>Contents 2<tag1>Contents 3"
soup = BeautifulStoneSoup(xml)
print soup.prettify()
# <doc>
#  <tag1>
#   Contents 1
#   <tag2>
#    Contents 2
#   </tag2>
#  </tag1>
#  <tag1>
#   Contents 3
#  </tag1>
# </doc> 
BeautifulStoneSoup の最も一般的な欠点は、自己終了タグを知らないことです。
HTML は、自己終了タグの修正集合を持っていますが、 XML では、DTD が何と言っているかに依ります。
自己終了タグ名を、selfClosingTags引数としてコンストラクタに渡すことで、BeautifulStoneSoup に、特定のタグが自己終了タグだと教えることが出来ます:
from BeautifulSoup import BeautifulStoneSoup
xml = "<tag>Text 1<selfclosing>Text 2"
print BeautifulStoneSoup(xml).prettify()
# <tag>
#  Text 1
#  <selfclosing>
#   Text 2
#  </selfclosing>
# </tag>

print BeautifulStoneSoup(xml, selfClosingTags=['selfclosing']).prettify()
# <tag>
#  Text 1
#  <selfclosing />
#  Text 2
# </tag>

動作しない場合には


これら2つとは異なるヒューリスティックを持つ他の解析クラスもあります。また、解析木をサブクラス化、カスタマイズ出来、解析木に自分のヒューリスティックを渡すことも出来ます。

0 件のコメント:

コメントを投稿

【和訳】Django Rest Framework 目次

目次 【和訳】Django Rest Framework クイックスタート 【和訳】Django Rest Framework チュートリアル1:シリアル化 【和訳】Django Rest Framework チュートリアル2:リクエストとレスポンス 【和訳】Django Res...