Python で (不正な形式の可能性がある) HTML を解析し、一連の条件が満たされた場合、ドキュメントのその部分を位置 (行、列) で出力する方法を見つけようとしています。ここで私をつまずかせているのは位置情報です。明確にするために、オブジェクト ツリーを構築する必要はありません。元のドキュメント内の特定のデータとその位置を見つけたいだけです (スペル チェッカーを考えてみてください。たとえば、「x 行、y 列の単語 "foo" のスペルが間違っています)」
例として、( ElementTree のTarget APIを使用して) 次のようなものが必要です。
import xml.etree.ElementTree as ET
class EchoTarget:
def start(self, tag, attrib):
if somecondition():
print "start", tag, attrib, self.getpos()
def end(self, tag):
if somecondition():
print "end", tag, self.getpos()
def data(self, data):
if somecondition():
print "data", repr(data), self.getpos()
target = EchoTarget()
parser = ET.XMLParser(target=target)
parser.feed("<p>some text</p>")
parser.close()
ただし、私が知る限り、そのgetpos()
方法 (またはそのようなもの) は存在しません。そしてもちろん、それは XML パーサーを使用しています。不正な可能性のある HTML を解析したい。
興味深いことに、Python 標準ライブラリのHTMLParserクラスは (メソッドを使用して) 位置情報を取得するためのサポートを提供しますgetpos()
が、不正な形式の HTML を処理するのは恐ろしく、可能な解決策として削除されました。パーサーを壊すことなく、実際の単語に存在する HTML を解析する必要があります。
私は、不正な形式の HTML の解析に適した 2 つの HTML パーサー、つまりlxmlとhtml5libを認識しています。実際、Python で利用可能な他のオプションよりも、どちらかを使用することをお勧めします。
ただし、私が知る限り、html5lib はイベント API を提供しておらず、ドキュメントをツリー オブジェクトに解析する必要があります。次に、ツリーを反復処理する必要があります。もちろん、その時点までに、ソース ドキュメントとの関連付けはなく、すべての位置情報が失われます。そのため、html5lib がリリースされました。これは、不正な HTML を処理するのに最適なパーサーのように思われるため、残念です。
lxml ライブラリは、ElementTree のものをほぼミラーリングした Target API を提供しますが、ここでも、各イベントの位置情報にアクセスする方法を知りません。ソースコードを一瞥してもヒントはありませんでした。
lxml は、SAX イベントへの API も提供します。興味深いことに、Python の標準 lib は、SAX がLocator Objectsをサポートしていると述べていますが、それらの使用方法に関するドキュメントはほとんど提供していません。This SO Questionは (SAX パーサーを使用する場合) いくつかの情報を提供しますが、lxml が提供する SAX イベントの限定的なサポートにどのように関連するのかわかりません。
最後に、誰かがBeautiful Soupを提案する前に、ホームページに記載されているように、「Beautiful Soup は、lxml や html5lib などの一般的な Python パーサーの上にある」ことを指摘しておきます。それが私に与えるのは、元のソース文書に接続されていないデータを抽出するためのオブジェクトだけです。html5lib と同様に、データにアクセスできるようになるまでにすべての位置情報が失われます。パーサーに直接アクセスしたい/必要です。
冒頭で述べたスペル チェッカーの例を拡張すると、ドキュメント テキスト内の単語のスペルのみをチェックし (タグ名や属性はチェックしない)、特定のタグ (スクリプトなど) の内容のチェックをスキップしたい場合があります。またはコードタグ)。したがって、実際の HTML パーサーが必要です。ただし、スペル ミスの単語の報告に関しては、元のソース ドキュメント内のスペル ミスの単語の位置にのみ関心があり、ツリー オブジェクトを作成する必要はありません。明確にするために、これは潜在的な用途の 1 つの例にすぎません。私はそれをまったく別のものに使用するかもしれませんが、ニーズは本質的に同じです. 実際、HTMLParser を使用して非常によく似たものを作成したことがありますが、そのユース ケースではエラー処理が機能しないため、使用したことはありません。それは何年も前のことで、途中でそのファイルを失ったようです。今回は代わりに lxml または html5lib を使用したいと思います。
それで、私が見逃しているものはありますか?これらのパーサーのどれも (ほとんど役に立たない HTMLParser を除いて) 位置情報にアクセスする方法を持っていないとは信じがたいです。しかし、もしそうなら、それは文書化されていないに違いありません。これは私には奇妙に思えます。