私はこのような構造を使用しています:
doc = parse(url).getroot()
links = doc.xpath("//a[text()='some text']")
しかし、「some text」で始まるテキストを持つすべてのリンクを選択する必要があるため、ここで正規表現を使用する方法はあるのでしょうか? lxml ドキュメントに何も見つかりませんでした
これを行うことができます (ただし、この例では正規表現は必要ありません)。Lxml は、 EXSLT拡張関数からの正規表現をサポートしています。( XPath クラスの lxml ドキュメントを参照してください。ただし、メソッドでも機能しますxpath()
)
doc.xpath("//a[re:match(text(), 'some text')]",
namespaces={"re": "http://exslt.org/regular-expressions"})
xpath 式の "re" プレフィックスが何を表しているかを認識できるように、名前空間のマッピングを指定する必要があることに注意してください。
starts-with()
次の関数を使用できます。
doc.xpath("//a[starts-with(text(),'some text')]")
答えは:
doc.xpath("//a[starts-with(text(), 'some')]")
これは最も簡単です。通常、最も単純なものが高速で最適です。
次の xml があり、それをdocに読み込むとします。
from lxml import etree
s="""
<html>
<head><title>Page Title</title></head>
<body>
<a href="www.example.com">some text</a>
<a href="www.example.com">some text2</a>
<a href="www.example.com">ends with some text2</a>
<a href="www.example.com">other text1</a>
<a href="www.example.com">other text2</a>
</body>
</html>
"""
doc=etree.fromstring(s)
前の回答で述べた 3 つの方法の速度をテストします。
時間 | 声明 |
---|---|
39.8μs | doc.xpath("//a[re:match(text(), '^some')]", namespaces={'re': 'http://exslt.org/regular-expressions'}) |
29.3μs | doc.xpath("//a[re:test(text(), '^some')]", namespaces={'re': 'http://exslt.org/regular-expressions'}) |
16.7μs | doc.xpath("//a[starts-with(text(), 'some')]") |
公式ウェブサイトhereによると、re:matchはオブジェクトを返しますが、 re:testはブール値のみを返します。私の推測では、re:matchはre:testよりも複雑でなければなりません。また、戻り値がブール値ではなくオブジェクトの場合、より多くのスペース/メモリが必要になるため、メモリの割り当てに時間がかかります。そのため、re:testはre:matchよりも高速です。したがって、文字列がパターンに一致するかどうかを確認したいだけなら、re:testと考えています。で十分です。もう 1 つの正規表現関数は replace です。あなたが私のように xpath を仕事で大量に使用している場合は、同様にドキュメントをよく読む必要があります。これは、この質問のタイトル、lxml xpath で正規表現を使用する方法に答えます。
ただし、正規表現は単純な文字列関数では問題を解決できない場合にのみ使用してください。特定のケースでは、必要なのはstarts-with関数だけです。時間の共犯性は O(n) のみで、n は 2 番目の文字列の長さです。正規表現を使用している間、アルゴリズムはより複雑になります。したがって、より多くの時間が費やされます。
このトピックの詳細:
xpath 2.0から、exsltを使わなくても正規表現が使えるようになります。ただし、lxml は xpath 1.0 のみをサポートします。
ここにw3のウェブサイトがあります: