web-dev-qa-db-ja.com

標準ライブラリを使用して、Pythonで不正な形式のHTMLを解析する方法

非常に多くの pythonに組み込まれているhtmlおよびxmlライブラリ であるため、実際のHTML解析がサポートされていないことは信じられません。

このタスクに最適なサードパーティライブラリをたくさん見つけましたが、この質問はpython標準ライブラリについてです。

要件:

  • Python標準ライブラリコンポーネント(任意の2.xバージョン)のみを使用)
  • DOMサポート
  • HTMLエンティティを処理します( 
  • 部分的なドキュメントを処理します(例:Hello, <i>World</i>!

ボーナスポイント:

  • XPATHサポート
  • 閉じていない/不正な形式のタグを処理します。 (<big>does anyone here know <html ???

リクエストに応じて、これが私の90%ソリューションです。これは、私が試した限られたHTMLセットで機能しますが、誰もがはっきりとわかるように、これは完全に堅牢ではありません。私は15分間ドキュメントと1行のコードを見つめてこれを行ったので、同様の、しかしより良い解決策についてstackoverflowコミュニティに相談できると思いました...

from xml.etree.ElementTree import fromstring
DOM = fromstring("<html>%s</html>" % html.replace('&nbsp;', '&#160;'))
37
bukzor

HTMLを確実に解析することは、比較的最近の開発です(奇妙に思えるかもしれませんが)。結果として、標準ライブラリには間違いなく何もありません。 HTMLParser may appear HTMLを処理する方法ですが、そうではありません-非常に一般的なHTMLの多くで失敗します。これらの失敗を回避することはできますが、常に失敗します。あなたが考えもしなかった別のケースです(実際にすべての失敗を処理することに成功した場合、基本的にBeautifulSoupを再作成します)。

HTMLを解析するための合理的な方法は実際には3つしかありません(Web上にあります): lxml.htmlBeautifulSoup 、および html5lib 。 lxmlは群を抜いて最速ですが、インストールが少し難しい場合があります(App Engineのような環境では不可能です)。 html5libは、HTML5が解析を指定する方法に基づいています。実際には他の2つと似ていますが、壊れたHTMLを解析する方法がおそらくより「正しい」です(これらはすべて、かなり良いHTMLを同じように解析します)。それらはすべて、壊れたHTMLを解析する際に立派な仕事をします。 BeautifulSoupは、そのAPIが不必要に風変わりだと思いますが、便利な場合があります。

44
Ian Bicking

BeautifulSoupのソースコードをスクリプトにコピーします;-)私は冗談です...あなたがその仕事をするために書くことができるものは、多かれ少なかれそのようなライブラリにすでに存在する機能を複製するでしょう。

それが本当にうまくいかない場合、私は尋ねなければなりません、なぜあなたが標準ライブラリコンポーネントだけを使うことがそれほど重要なのですか?

5
David Z

要件を変更するか、サードパーティモジュールの開発者が行ったすべての作業を複製するかを選択できます。

美しいスープは、約2000行のコードを含む単一のpythonファイルで構成されています。依存関係が大きすぎる場合は、先に進んで独自のファイルを作成してください。うまく機能しない可能性があります。ずっと小さくなることはありません。

4
mikerobi

Stdlibに優れた堅牢なヒューリスティックHTML解析ライブラリがある人気のある言語は考えられません。 Python確かにそれはありません、それはあなたが知っていると思います。

なぜstdlibモジュールが必要なのですか?人々がその要求をするのを聞くほとんどの場合、彼らはばかげています。ほとんどの主要なタスクでは、サードパーティのモジュールが必要になるか、全体の作業を再実装するために費やします。依存関係の導入は良いことです。なぜなら、それはあなたがする必要がなかった仕事だからです。

だからあなたが欲しいのは lxml.html 。それが問題である場合は、コードと一緒にlxmlを出荷します。その時点で、難易度、バグ、保守性を除いて、自分で作成するのと機能的に同等になります。

1
Mike Graham

stdだけの要件には適合しませんが、 beautifulsoup は素晴らしいです

1
PW.

すでに述べたように、現在、standardlibだけで満足のいく解決策はありません。独自の拡張機能とpython2.6のみをインストールする可能性なしに、古いホスティング環境でプログラムの1つを実行しようとしたとき、私はあなたと同じ問題に直面していました。解決:

Grab このファイル および最新の安定版 BeautifulSoup 3erシリーズのバージョン(現在は3.2.1)。そこにあるtarファイルからBeautifulSoup.pyだけを選択します。これは、コードとともに出荷する必要がある唯一のファイルです。したがって、パスにこれら2つのファイルがあり、lxmlから取得するのと同じように、HTML文字列からカジュアルなetreeオブジェクトを取得するために必要なことは次のとおりです。

from StringIO import StringIO
import ElementSoup

tree = ElementSoup.parse(StringIO(input_str))

lxml自体とhtml5libはどちらも、実行するためにCコードをコンパイルする必要があります。それらを機能させるにはかなりの労力が必要です。環境が制限されている場合、または対象読者がそれを望まない場合は、それらを避けてください。

0
Michael