1

BeautifulSoup から離れようとしています。これは大好きですが、(積極的に) サポートされていないようです。html5lib と lxml を使用しようとしていますが、"find" および "findall" 演算子の使用方法がわかりません。

html5lib のドキュメントを見て、テスト プログラムとして次のように思いつきました。

import cStringIO

f = cStringIO.StringIO()
f.write("""
  <html>
    <body>
      <table>
       <tr>
          <td>one</td>
          <td>1</td>
       </tr>
       <tr>
          <td>two</td>
          <td>2</td
       </tr>
      </table>
    </body>
  </html>
  """)
f.seek(0)

import html5lib
from html5lib import treebuilders
from lxml import etree  # why?

parser = html5lib.HTMLParser(tree=treebuilders.getTreeBuilder("lxml"))
etree_document = parser.parse(f)

root = etree_document.getroot()

root.find(".//tr")

しかし、これは None を返します。を実行すると、すべてのデータが返されることに気付きましたetree.tostring(root)が、すべてのタグはhtml(eg <html:table>) で始まります。しかしroot.find(".//html:tr")、KeyError をスローします。

誰かが私を正しい軌道に戻すことができますか?

4

5 に答える 5

6

次のコマンドでネームスペースをオフにできます。 etree_document = html5lib.parse(t, treebuilder="lxml", namespaceHTMLElements=False)

于 2011-05-17T22:17:57.350 に答える
5

一般に、lxml.htmlHTML に使用します。そうすれば、独自のパーサーの生成や名前空間について心配する必要はありません。

>>> import lxml.html as l
>>> doc = """
...    <html><body>
...    <table>
...      <tr>
...        <td>one</td>
...        <td>1</td>
...      </tr>
...      <tr>
...        <td>two</td>
...        <td>2</td
...      </tr>
...    </table>
...    </body></html>"""
>>> doc = l.document_fromstring(doc)
>>> doc.finall('.//tr')
[<Element tr at ...>, <Element tr at ...>] #doctest: +ELLIPSIS

参考までに、lxml.htmlCSS セレクターを使用することもできます。これは、より簡単な構文です。

>>> doc.cssselect('tr')
[<Element tr at ...>, <Element tr at ...>] #doctest: +ELLIPSIS
于 2010-09-12T23:06:38.030 に答える
3

「lxml」html5libを使用すると、html5libTreeBuilderがXHTML名前空間にツリーを構築するように見えます。lxmlはXMLライブラリであり、XHTMLはHTMLをXMLとして表す方法であるため、これは理にかなっています。lxmlのqname構文をfind()メソッドで使用して、次のようなことを行うことができます。

root.find('.//{http://www.w3.org/1999/xhtml}tr')

または、lxmlの完全なXPath関数を使用して、次のようなことを行うことができます。

root.xpath('.//html:tr', namespaces={'html': 'http://www.w3.org/1999/xhtml'})

lxmlのドキュメントには、XML名前空間の使用方法に関する詳細が記載されています。

于 2010-09-12T20:09:01.277 に答える
2

これは古い質問だと思いますが、他の場所では見つけられなかった情報を求めてここに来ました。私は BeautifulSoup で何かをこすり取ろうとしていましたが、分厚い html で窒息していました。デフォルトの html パーサーは、利用可能な他のいくつかのパーサーよりも緩いようです。よく好まれるパーサーの 1 つに lxml があります。これは、ブラウザーで期待されるのと同じ解析を行うと私は信じています。BeautifulSoup では lxml をソース パーサーとして指定できますが、これを使用するには少し作業が必要です。

まず、html5lib が必要であり、lxml もインストールする必要があります。html5lib は lxml (および他のいくつかのライブラリ) を使用する準備ができていますが、この 2 つは一緒にパッケージ化されていません。[Windows ユーザーの場合、通常、プロジェクトと同じディレクトリにコピーを作成してライブラリを取得するほど Win の依存関係に煩わされるのは好きではありませんが、これには pip を使用することを強くお勧めします。かなり痛みがありません。管理者アクセスが必要だと思います。]

次に、次のように記述する必要があります。

import urllib2
from bs4 import BeautifulSoup
import html5lib
from html5lib import sanitizer
from html5lib import treebuilders
from lxml import etree

url = 'http://...'

content = urllib2.urlopen(url)
parser = html5lib.HTMLParser(tokenizer=sanitizer.HTMLSanitizer,
                             tree=treebuilders.getTreeBuilder("lxml"),
                             namespaceHTMLElements=False)
htmlData = parser.parse(content)
htmlStr = etree.tostring(htmlData)

soup = BeautifulSoup(htmlStr, "lxml")

その後、あなたの美しいスープをお楽しみください!

パーサーの namespaceHTMLElements=false オプションに注意してください。lxml は単なる HTML ではなく XML を対象としているため、これは重要です。そのため、提供するすべてのタグに、HTML 名前空間に属するものとしてラベルを付けます。タグは次のようになります (例)

<html:li>

BeautifulSoup はうまく機能しません。

于 2015-07-13T03:59:23.203 に答える
0

試す:

root.find('.//{http://www.w3.org/1999/xhtml}tr')

名前空間プレフィックス ( ) ではなく、名前空間を指定する必要がありますhtml:tr。詳細については、lxml のドキュメント、特に次のセクションを参照してください。

于 2010-09-12T19:57:00.350 に答える