かなり無理やりなパッチ
回答もつきそうにないし、Beautiful Soup 4 で XPath を使う方法もわからないので、無理やり自己解決。
ダウンロード:bs4_plus_xpath.tgz
Beautiful Soup 4 + lxmlで無理やりXPath
from bs4 import BeautifulSoup from bs4_plus_xpath import Tag
Tag クラスに xpath という関数をくっつけている。
soup = BeautifulSoup(html, 'lxml')
elm_list = soup.xpath(<XPath式>)
みたいな感じで、XPath式を指定して要素を取得できる。これらは BeautifulSoup 要素(Tag等)なので、元の関数はそのまま使える。
例
#! /usr/bin/env python # -*- coding: utf-8 -*- from bs4 import BeautifulSoup, NavigableString from bs4_plus_xpath import Tag TEST_HTML=u""" <html> <head><title>TEST</title></head> <body> <div id="text"> 書き始め。 <p> 本文はここ。<br /> ここまでだけ残して、後は消したいの。 </p> <hr /> <!-- cutting line --> <p>ここから先は要らない</p> dust <b>ゴミ</b> 廃棄物<br /> unnecessary text </div> </body> </html> """ #{ // def remove_elm_list() def remove_elm_list(elm_list): for (ci, elm) in enumerate(elm_list): print u'No.%2d' % (ci+1) print elm if hasattr(elm, 'decompose'): # 通常のノード elm.decompose() else: # テキストノード elm.replace_with('') print u'='*50+u'\n' #} // end of remove_elm_list() if __name__ == '__main__': soup = BeautifulSoup(TEST_HTML, 'lxml') junk_elm_list = soup.xpath(u'//div[@id="text"]/hr/following-sibling::node()') remove_elm_list(junk_elm_list) print u'■結果' print unicode(soup) print u'\n' print u'■結果 (整形後)' print soup.prettify() # ■ end of file
実行結果
No. 1 cutting line ================================================== No. 2 <p>ここから先は要らない</p> ================================================== No. 3 dust ================================================== No. 4 <b>ゴミ</b> ================================================== No. 5 廃棄物 ================================================== No. 6 <br/> ================================================== No. 7 unnecessary text ================================================== ■結果 <html><head><title>TEST</title></head><body> <div id="text"> 書き始め。 <p> 本文はここ。<br/> ここまでだけ残して、後は消したいの。 </p> <hr/> </div> </body></html> ■結果 (整形後) <html> <head> <title> TEST </title> </head> <body> <div id="text"> 書き始め。 <p> 本文はここ。 <br/> ここまでだけ残して、後は消したいの。 </p> <hr/> </div> </body> </html>
言い訳
ソースを見ればわかりますが、かなり無理やりなことをやっており、ちゃんと動く保証は一切ありませんので、ご容赦を。
その作り上、速度も非常に遅くなります。
「俺は XPath 指定じゃないと使う気にならないんだっ!」という奇特な方は、ご参考までにということで。
それ以外の方は、素直に Beautiful Soup の普通の検索方法を使った方がよいです。