python之lxml快速上手_Element(二)
来源:互联网 发布:js动态添加tr td 编辑:程序博客网 时间:2024/06/07 03:57
使用XPath查找文本(Using XPath to find text)
另一个在树状结构文档中抽取文本的方式是:XPath,它同样允许你抽取单独的文本块并放到list中。
>>> print(html.xpath("string()")) # lxml.etree only!TEXTTAIL>>> print(html.xpath("//text()")) # lxml.etree only!['TEXT', 'TAIL']
如果你想重复利用上述代码,你可以把它封装到一个函数中:
# 注意,此处使用text(),而不是string()、concat(),后续有说明>>> build_text_list = etree.XPath("//text()") # lxml.etree only!>>> print(build_text_list(html))['TEXT', 'TAIL']
注意,由XPath返回的文本结果是一个非常“智能”的对象,它知道自己的出身。你可以使用getparent()来了解它来自哪里(即获取它的父节点),就像你对Element对象所做的那样。
>>> texts = build_text_list(html)>>> print(texts[0])TEXT>>> parent = texts[0].getparent()>>> print(parent.tag)body>>> print(texts[1])TAIL>>> print(texts[1].getparent().tag)br
你还可以知道它到底是普通的文本内容,还是尾部文本(tail text):
>>> print(texts[0].is_text)True>>> print(texts[1].is_text)False>>> print(texts[1].is_tail)True
既然text()函数返回的文本对象可以告诉你它的“归属”(即获取它的父节点),当你使用XPath函数string()、concat()时,它将不再告诉你它的“归属”。
>>> stringify = etree.XPath("string()")>>> print(stringify(html))TEXTTAIL>>> print(stringify(html).getparent())None
树的迭代(Tree iteration)
为了应对上面的问题,你可能需要递归遍历树并使用对它拥有的节点做一些事情,而树的迭代恰好是一个很方便的解决方案。为实现这一目的,Elements提供了树迭代器。就像生成器一样,在有序的文档(document order)返回(yield)节点。
>>> root = etree.Element("root")>>> etree.SubElement(root, "child").text = "Child 1">>> etree.SubElement(root, "child").text = "Child 2">>> etree.SubElement(root, "another").text = "Child 3">>> print(etree.tostring(root, pretty_print=True))<root> <child>Child 1</child> <child>Child 2</child> <another>Child 3</another></root>>>> for element in root.iter():... print("%s - %s" % (element.tag, element.text))root - Nonechild - Child 1child - Child 2another - Child 3
如果你仅仅对某一些标签感兴趣,你可以把它的标签名传递给iter()来为你过滤掉不需要的标签。从lxml 3.0开始,你也可以同时传递多个标签名:
>>> for element in root.iter("child"):... print("%s - %s" % (element.tag, element.text))child - Child 1child - Child 2>>> for element in root.iter("another", "child"):... print("%s - %s" % (element.tag, element.text))child - Child 1child - Child 2another - Child 3
默认情况下,迭代器会返回树的所有节点,包括ProcessingInstructions(处理指令),Comments(注释)、Entity instances(实体实例)。如果你想确认只有元素节点(Elements)返回,你可以把Element工厂函数作为tag关键字参数传递给iter():
>>> root.append(etree.Entity("#234"))>>> root.append(etree.Comment("some comment"))>>> for element in root.iter():... if isinstance(element.tag, basestring):... print("%s - %s" % (element.tag, element.text))... else:... print("SPECIAL: %s - %s" % (element, element.text))root - Nonechild - Child 1child - Child 2another - Child 3SPECIAL: ê - êSPECIAL: <!--some comment--> - some comment>>> for element in root.iter(tag=etree.Element):... print("%s - %s" % (element.tag, element.text))root - Nonechild - Child 1child - Child 2another - Child 3>>> for element in root.iter(tag=etree.Entity):... print(element.text)ê
注意,传递通配符“*”仍具会返回所有元素节点(仅包含Element)。
序列化(Serialisation)
序列化通常使用tostring()函数,它会返回一个字符串,或者你也可以使用ElementTree.write()方法将其写入到一个文件、类文件对象、一个URL。两种调用方式都接收同样的关键字参数,比如pretty_print(格式化输出),encoding(编码格式)可以指定除ASCII之外的输出编码格式,以及xml_declaration(是否加入XML声明):
>>> root = etree.XML('<root><a><b/></a></root>')>>> etree.tostring(root)b'<root><a><b/></a></root>'>>> print(etree.tostring(root, xml_declaration=True))<?xml version='1.0' encoding='ASCII'?><root><a><b/></a></root>>>> print(etree.tostring(root, encoding='iso-8859-1'))<?xml version='1.0' encoding='iso-8859-1'?><root><a><b/></a></root>>>> print(etree.tostring(root, pretty_print=True))<root> <a> <b/> </a></root>
注意,美化输出(指定pretty_print=True时)会在文件最末位加一空白行。
在lxml 2.0及之后的版本,序列化函数能做的不仅局限于XML序列化。你也可以将其序列化成HTML,或者抽取文本,只需要通过method关键字参数:
>>> root = etree.XML(... '<html><head/><body><p>Hello<br/>World</p></body></html>')>>> etree.tostring(root) # default: method = 'xml'b'<html><head/><body><p>Hello<br/>World</p></body></html>'>>> etree.tostring(root, method='xml') # same as aboveb'<html><head/><body><p>Hello<br/>World</p></body></html>'>>> etree.tostring(root, method='html')b'<html><head></head><body><p>Hello<br>World</p></body></html>'>>> print(etree.tostring(root, method='html', pretty_print=True))<html><head></head><body><p>Hello<br>World</p></body></html>>>> etree.tostring(root, method='text')b'HelloWorld'
与XML序列化一样,简单文本的序列化的默认编码格式也是ASCII:
>>> br = next(root.iter('br')) # get first result of iteration>>> br.tail = u'W\xf6rld'>>> etree.tostring(root, method='text') # doctest: +ELLIPSISTraceback (most recent call last): ...UnicodeEncodeError: 'ascii' codec can't encode character u'\xf6' ...>>> etree.tostring(root, method='text', encoding="UTF-8")b'HelloW\xc3\xb6rld'
在下面的例子中,序列化成一个python Unicode字符串,比字节串(byte strings)更加易于处理。只需指定encoding为unicode即可:
>>> etree.tostring(root, encoding='unicode', method='text')u'HelloW\xf6rld'
- python之lxml快速上手_Element(二)
- python之lxml快速上手_Element(一)
- python之lxml快速上手_ElementTree(三)
- Python快速上手(二)
- Python快速上手(一)
- Python快速上手(三)
- 【openCV入门之二】 快速上手
- Python之lxml
- Python之lxml
- python爬虫之lxml
- F# 20分钟快速上手(二)
- 快速上手RaphaelJS--RaphaelJS_Starter翻译(二)
- UnityShader快速上手指南(二)
- swift 3.1 快速上手系列(二)
- Python 编程快速上手
- python request快速上手
- python request快速上手
- Python requests快速上手
- MySQL基础
- Ice自学第一步——Windows下安装Ice和设置Ice的环境变量
- shell实现ftp命令示例
- IOS 的NSSet,NSHashMap,NSHashTable,NSPointerArray集合类
- iOS内存管理、NSString类创建的几种方式类存情况
- python之lxml快速上手_Element(二)
- 关于shell中常见功能的实现方式总结
- PHP的json_encode不兼容JSON_UNESCAPED_UNICODE的解决方案
- SHELL十三问[转载自CU论坛]
- Ansible自动化运维工具使用
- awk中RS,ORS,FS,OFS区别与联系
- 配置伪分布式Hadoop
- java 多态
- CU论坛常用知识点汇总