web-dev-qa-db-ja.com

lxml xpathで正規表現を使用する方法は?

私はこのような構造を使用しています:

doc = parse(url).getroot()
links = doc.xpath("//a[text()='some text']")

しかし、「いくつかのテキスト」で始まるテキストを持つすべてのリンクを選択する必要があるので、ここで正規表現を使用する方法はありますか? lxmlドキュメントに何も見つかりませんでした

23
Arty

これを行うことができます(ただし、例では正規表現は必要ありません)。 Lxmlは、 [〜#〜] exslt [〜#〜] 拡張関数からの正規表現をサポートします。 ( XPathクラス についてはlxmlドキュメントを参照してくださいが、xpath()メソッドでも機能します)

doc.xpath("//a[re:match(text(), 'some text')]", 
        namespaces={"re": "http://exslt.org/regular-expressions"})

Xpath式の「re」プレフィックスが何を表すかがわかるように、名前空間マッピングを指定する必要があることに注意してください。

38
Steven

starts-with() 関数を使用できます:

doc.xpath("//a[starts-with(text(),'some text')]")
15
John Kugelman

名前空間に対するlxmlのアプローチに耐えられないため、HtmlElementクラスにカムバインドする小さなメソッドを作成しました。

HtmlElementをインポートするだけです:

from lxml.etree import HtmlElement

次に、これをファイルに入れます。

# Patch the HtmlElement class to add a function that can handle regular
# expressions within XPath queries.
def re_xpath(self, path):
    return self.xpath(path, namespaces={
        're': 'http://exslt.org/regular-expressions'})
HtmlElement.re_xpath = re_xpath

そして、正規表現クエリを作成する場合は、次のようにします。

my_node.re_xpath("//a[re:match(text(), 'some text')]")

そして、あなたはレースに出かけています。もう少し作業をすれば、おそらくこれを変更してxpathメソッド自体を置き換えることができますが、これは十分に機能しているので、私は気にしませんでした。

0
mlissner