1. ワイルドカードの応用
| 記号 |
用途 |
| * |
任意の要素名を同階層でマッチ |
| @* |
任意の属性を同階層でマッチ |
| node() |
ノードタイプに関係なく同階層でマッチ |
| */ |
複数階層の任意要素をマッチ |
| // |
任意階層の要素を圧縮的にマッチ |
同階層での汎用マッチ
# 例: 2つのパスを統合
/html/body/div[*]/main/article/*/div
タグ名による条件指定
# h2とh4タグをOR条件で選択
/div/*[self::h2 or self::h4]/a
多階層マッチ
# 階層数が異なるパスを統一
/html/body/div/div/*//main/article/div/div
部分文字列マッチ
# class属性にitem-articleを含むdiv
//div[contains(@class, 'item-article')]
2. 要素の走査方法
| XPath式 |
動作 |
| ./* |
直下の子ノードのみ走査 |
| .//* |
すべての子孫ノードを再帰的に走査 |
| //* |
ルートからすべてのノードを走査 |
XML要素の操作例
from lxml import etree
xml_data = """
<div>
<child1>
<subchild1>Value1</subchild1>
<subchild2>Value2</subchild2>
</child1>
<child2 class="2">
<subchild3>Value3</subchild3>
</child2>
<a href="#"></a>
</div>
"""
div = etree.fromstring(xml_data)
elements = div.xpath('./*')
for element in elements:
if element.tag == 'a':
etree.strip_attributes(element, ["href"])
if element.tag == 'child2' and element.get('class') == "2":
element.getparent().remove(element)
content_html = etree.tostring(div, method='html', encoding='utf-8').decode('utf-8')
print(content_html)
3. 属性条件の指定
# ID属性で指定
div[@id="a123456"]
# 複数属性のAND条件
div[@class="article-content" and as="abc"]
4. 不要要素の削除
html = etree.HTML(resp.text)
[element.getparent().remove(element) for element in html.xpath("/html/body/div/div/div/main/article")]
5. 要素置換による削除
from lxml import etree
txt = '''
<div>
<div >兄弟1</div>
<div class="target"><p>子要素1</p><p>子要素2</p><p>子要素3</p></div>
<div >兄弟2</div>
</div>
'''
html = etree.HTML(txt)
target = html.xpath('/html/body/div/div[@class="target"]')[0]
[target.addprevious(child) for child in target]
target.getparent().remove(target)
print(etree.tostring(html,encoding='utf-8').decode('utf-8'))
6. 要素情報の取得
element = html.xpath("/html/body/div/div/div/main/article")
print(element.tag) # タグ名
print(element.get('href')) # 属性値
print(element.items()) # 全属性
print(element.text) # テキスト
print(element.xpath("//*")) # 子孫全要素
7. 属性の削除
from lxml import etree
etree.strip_attributes(element,["href"])
8. 要素のXPath取得
element_path = []
element_path_attr = []
element_path_index = []
while element:
attr = '['+' and '.join(["@"+str(i[0])+'="'+str(i[1])+'"' for i in element.items() if i[0] in ['class','id','name','type','title','target','rel']])+']'
element_path.insert(0,'/'+element.tag)
element_path_attr.insert(0,'/'+element.tag + attr.replace('[]',''))
element_path_index.insert(0, '/' + element.tag + ('['+str(element.getparent().index(element)+1)+']' if element.getparent() else ''))
element = element.getparent()
print(''.join(element_path))
print(''.join(element_path_attr))
print(''.join(element_path_index))
9. Xpath Helper拡張機能
ブラウザ拡張機能としてXPath Helperが非常に有効
10. HTML形式での出力
from lxml import etree
etree.tostring(element,encoding='unicode',method='html')