困っていること
_ElementStringResult や lxml.etree._ElementUnicodeResult といったobjectをドキュメントツリーから除去する方法がわからないので、ご存じの方、教えてください。
lxmlは2.3.3、2.3.5、3.0、3.1beta1といったもので試したが、結果は同様。
例
! /usr/bin/env python # -*- coding: utf-8 -*- import lxml.html 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 try: elm.drop_tree() except Exception, s: print u'[Error-1] %s' % (s) pelm = elm.getparent() try: pelm.remove(elm) except Exception, s: print u'[Error-2] %s' % (s) print u'='*50+u'\n' #} // end of remove_elm_list() if __name__ == '__main__': doc = lxml.html.fromstring(TEST_HTML) junk_elm_list = doc.xpath(u'//div[@id="text"]/hr/following-sibling::node()') remove_elm_list(junk_elm_list) print u'■結果' print lxml.html.tostring(doc, method='html', encoding=unicode) # ■ end of file
実行結果
No. 1 <!-- cutting line --> ================================================== No. 2 <Element p at 0xb78201ac> ================================================== No. 3 dust [Error-1] '_ElementStringResult' object has no attribute 'drop_tree' [Error-2] Argument 'element' has incorrect type (expected lxml.etree._Element, got _ElementStringResult) ================================================== No. 4 <Element b at 0x8565d4c> ================================================== No. 5 廃棄物 [Error-1] 'lxml.etree._ElementUnicodeResult' object has no attribute 'drop_tree' [Error-2] Argument 'element' has incorrect type (expected lxml.etree._Element, got lxml.etree._ElementUnicodeResult) ================================================== No. 6 <Element br at 0x8565d7c> ================================================== No. 7 unnecessary text [Error-1] '_ElementStringResult' object has no attribute 'drop_tree' [Error-2] Argument 'element' has incorrect type (expected lxml.etree._Element, got _ElementStringResult) ================================================== ■結果 <html><head><title>TEST</title></head><body> <div id="text"> 書き始め。 <p> 本文はここ。<br> ここまでだけ残して、後は消したいの。 </p> <hr> dust 廃棄物 unnecessary text </div> </body></html>
【2013/01/03追記】無理やりやってみる…
例
#! /usr/bin/env python # -*- coding: utf-8 -*- import lxml.html from lxml.html import Element 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> """ TAG_TEXTNODE = '__TextNode__' #{ // 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 try: elm.drop_tree() except Exception, s: print u'[Error-1] %s' % (s) print u'='*50+u'\n' #} // end of remove_elm_list() #{ // def add_textnode_marks() def add_textnode_marks(top_elm): for elm in top_elm.xpath(u'.//*'): etext = elm.text if etext: t_elm = Element(TAG_TEXTNODE) t_elm.text = etext elm.text = None elm.insert(0, t_elm) ttext = elm.tail if ttext: t_elm = Element(TAG_TEXTNODE) t_elm.text = ttext elm.tail = None elm.addnext(t_elm) #} // end of def add_textnode_marks() #{ // def remove_textnode_marks() def remove_textnode_marks(top_elm): for elm in top_elm.xpath('.//%s' % (TAG_TEXTNODE)): elm.drop_tag() #} // end of def remove_textnode_marks() if __name__ == '__main__': doc = lxml.html.fromstring(TEST_HTML) add_textnode_marks(doc) junk_elm_list = doc.xpath(u'//div[@id="text"]/hr/following-sibling::node()') remove_elm_list(junk_elm_list) remove_textnode_marks(doc) print u'■結果' print lxml.html.tostring(doc, method='html', encoding=unicode) # ■ end of file
実行結果
No. 1 <!-- cutting line --> ================================================== No. 2 <Element p at 0xb7821f8c> ================================================== No. 3 <Element __TextNode__ at 0xb74ceecc> ================================================== No. 4 <Element b at 0xb74cee9c> ================================================== No. 5 <Element __TextNode__ at 0xb74ced4c> ================================================== No. 6 <Element br at 0xb74ced7c> ================================================== No. 7 <Element __TextNode__ at 0xb74cedac> ================================================== ■結果 <html><head><title>TEST</title></head><body> <div id="text"> 書き始め。 <p> 本文はここ。<br> ここまでだけ残して、後は消したいの。 </p> <hr></div> </body></html>
テキスト部分を<__TextNode__>要素に変換、処理してのち元のテキストに戻している……効率悪いし、使いどころが限られるなぁ。
ポイントないので期待薄だけれど、一応人力検索でも質問してみた。