是一种结构化网页元素选择器,支持列表和单节点数据获取,他的好处可以支持规整网页数据抓取。
是一款Chrome浏览器的开发者插件,让开发者能轻松获取HTML元素的。整个抓取使用了xpath、正则表达式、消息中间件、多线程调度框架)。我们可以用它进行xpath的实践使用。
lxml 是提供了一个 Pythonic API,主要的功能是如何解析和提取 HTML/XML 数据。,lxml 下面还有很多的模块,有 etree 、html 、cssselect 等众多模块,它和BeautifulSoup之间可以相互调用。
我们搜索xpath或者lxml,他们两个总是成对出现,原因是很多时候,我们都是通过lxml将string转为标准的html标签格式,然后再去给xpath进行解析,所以经常一起使用
XPath 使用路径表达式来选取 XML 文档中的节点或者节点集。这些路径表达式和我们在常规的电脑文件系统中看到的表达式非常相似。
路劲查询
路径表达式:
表达式 | 描述 |
---|---|
nodename | 选取此节点的所有子节点。 |
/ | 从根节点选取。 |
// | 从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置。 |
. | 选取当前节点。 |
.. | 选取当前节点的父节点。 |
@ | 选取属性。 |
例子:
路径表达式 | 结果 | |
---|---|---|
bookstore | 选取 bookstore 元素的所有子节点。 | |
/bookstore | 选取根元素 bookstore。注释:假如路径起始于正斜杠( / ),则此路径始终代表到某元素的绝对路径! | |
bookstore/book | 选取属于 bookstore 的子元素的所有 book 元素。 | |
//book | 选取所有 book 子元素,而不管它们在文档中的位置。 | |
bookstore//book | 选择属于 bookstore 元素的后代的所有 book 元素,而不管它们位于 bookstore 之下的什么位置。 | |
//@lang | 选取名为 lang 的所有属性。 |
谓语(Predicates)
谓语用来查找某个特定的节点或者包含某个指定的值的节点,被嵌在方括号中。
路径表达式 | 结果 |
---|---|
/bookstore/book[1] | 选取属于 bookstore 子元素的第一个 book 元素。 |
/bookstore/book[last()] | 选取属于 bookstore 子元素的最后一个 book 元素。 |
/bookstore/book[last()-1] | 选取属于 bookstore 子元素的倒数第二个 book 元素。 |
/bookstore/book[position()<3] | 选取最前面的两个属于 bookstore 元素的子元素的 book 元素。 |
//title[@lang] | 选取所有拥有名为 lang 的属性的 title 元素。 |
//title[@lang=’eng’] | 选取所有 title 元素,且这些元素拥有值为 eng 的 lang 属性。 |
/bookstore/book[price>35.00] | 选取 bookstore 元素的所有 book 元素,且其中的 price 元素的值须大于 35.00。 |
/bookstore/book[price>35.00]/title | 选取 bookstore 元素中的 book 元素的所有 title 元素,且其中的 price 元素的值须大于 35.00。 |
选取节点
通配符 | 描述 |
---|---|
* | 匹配任何元素节点。 |
@* | 匹配任何属性节点。 |
node() | 匹配任何类型的节点。 |
例子:
路径表达式 | 结果 |
---|---|
/bookstore/* | 选取 bookstore 元素的所有子元素。 |
//* | 选取文档中的所有元素。 |
//title[@*] | 选取所有带有属性的 title 元素。 |
选取若干路径
使用“|”运算符,可以选取若干个路径。
路径表达式 | 结果 |
---|---|
//book/title | //book/price | 选取 book 元素的所有 title 和 price 元素。 |
//title | //price | 选取文档中的所有 title 和 price 元素。 |
/bookstore/book/title | //price | 选取属于 bookstore 元素的 book 元素的所有 title 元素,以及文档中所有的 price 元素。 |
XPath的运算符
实战示例
简单使用
from lxml import etree text = ''' ''' html = etree.HTML(text) #result1 = etree.tostring(html) #print(result1) #(1)提取class属性值为large的div标签中的id属性值 print("id属性值:",html.xpath('//div[@class="large"]/@id')[0]) #(2)提取第一个span标签中的文本信息 print("第一个span标签中的文本信息:",html.xpath('//span/text()')[0]) #(3)提取第二个span标签中的链接 print("第二个span标签中的链接:",html.xpath('//span/a/@href')[0])
常用操作
1、text()中包含某个字段
//a[contains(text(),"联系")]
2、多条件的筛选
选取a标签下text包含“联系”和“昆明”字段的a标签
//a [contains(text(),"联系") and contains(text(),"昆明")]
找去a标签下text包含“联系”和“昆明”字段并且title属性中包含化妆的a标签
//a[contains(text(),"联系") and contains(text(),"昆明") and contains(@title,"化妆")]
注意:
xpath = response.xpath('//span[@class="total"]/text()').extract()
通过xpath得到的数据是一个selector的数组:
]
通过.extract之后才能拿到比较正式的数据
['共50页']
lxml导入html文档内容
能将字符串或流读进来解析成 ElementTree ,又能将 ElementTree 转换为字符串或流。
etree.fromstring( string )
将 string 解析为 Element 或者 ElementTree 。
etree.parse( file )
将文件或者是 file_like 对象解析为 ElementTree (not an Element object)
etree.tostring(text)
按字符串序列化HTML文档
Element属性操作
属性简介:
ag:元素的名称
.attrib:一个包含元素属性的字典,key 是属性名,value 是对应的值。
.text:Element 的文本均为直接子文本,不包含子元素中的文本,这其中又包含两部分 .text 和 .tail 。.text 是第一个子元素标签之前的,如果没有则为 None 。
.tail:.tail 为 Element 的关闭标签之后的文本,并且是在下一个兄弟子标签之前的部分。没有则为 None 。
属性操作方法:
append( child )
添加一个新的子节点(可以是 Element 、Comment)到当前 Element 中。
insert( index, elt)
将子元素 elt 插入到指定位置,这个 index 的随意性比较大,如果是正数但是超过了最大值,那么 lxml 会直接将这个元素插到末尾,如果是负数,但是这个负数所指位置不存在,那么就插到末尾,这个负数的位置计算规则和列表的那个不太一样,不知道正确的规律是什么,但是经过测试,-n
所插的位置,后面有 n (以变化前计算)个元素。如果对 Element 中的子元素执行 insert() 操作,那么子元素位置会按 index 指定的变换。
clear()
调用该函数,将移除所有内容 .attrib 将被移除 .text 和 .tail 将被设置为 None 所有的子节点将被删除。
remove( child )
将子节点 child 从Element 中移除 ,如果child 不是 Element 的子节点,将会引发 ValueError 异常。
find( path )
从 Element 的子元素及后代元素中查找第一个符合 path 的 subelement 。如果没有返回 None 。
ElementPath 是 ElementTree 自带的一个 XPath-like 的路径语言,和 XPath 差不太多,主要区别是 ElementPath 能用 {namespace}tag
,但是 ElementPath 不能使用值比较和函数。
findall( path )
返回一个匹配的 Element 的列表。
findtext( path, default=None )
返回第一个匹配元素的 .text 内容,如果存在匹配,但是没有 .text 内容,那么将返回一个空字符串,如果没有一个匹配的元素,那么将会返回一个 None ,但是有 default 参数,返回 default 所指定的。
get( key, default=None )
返回字符串形式的 属性 key 的值,没有返回 None 或者 default 指定的。
getchildren()
返回一个包含 Element 子元素的列表。
getiterator( tag=None, *tags )
返回元素的一个生成器,返回元素类别取决于参数 tag ,生成顺序是in document order (depth first pre-order)
深度优先的先根遍历。如果没有参数的话,则第一个就是元素本身。如果想使用一个高效的生成器,可以使用 .iter() 。
getroottree()
返回该元素的 ElementTree 。
iter( tag=None, *tags )
过滤特定标签,生成迭代器。默认情况下,iter() 迭代所有的节点,包括PI(处理指令) 、Comment(注释) 等,如果只想迭代标签元素,可以使用 Element factory 做参数e.iter(tag = etree.Element)
。
iterfind( path )
迭代所有匹配 ElementPath 的 Element 。
itertext( tag=None, *tags, with_tail=True )
迭代 Element 元素的文本内容,with_tail 参数决定是否迭代子元素的 tail 。Element 的tail 不会进行迭代。
iterancestors( tag=None )
如果忽略参数,那么将会迭代所有先辈,加标签名可以只迭代该标签先辈。
iterchildren( reversed=False, tag=None )
通过设置 reversed=True 可以以反向的顺序迭代子元素。
itersiblings( preceding=False )
迭代 Element 之后的兄弟元素,可以通过设置 preceding=True 仅迭代 Element 之前的兄弟元素。
iterdescendants( tag=None )
同 iterancestors()
items()
返回由元素属性的键值所构成的( name, value)元组的列表。
keys()
返回一个没有特定顺序的元素属性名的列表。
set(A, V)
创建或者改变属性 A 的值为 V。
xpath()
实战:
将string转为html
# 使用 lxml 的 etree 库 from lxml import etree text = '''''' #利用etree.HTML,将字符串解析为HTML文档 html = etree.HTML(text) # 按字符串序列化HTML文档 result = etree.tostring(html) print(result)
- first item
- second item
- third item
- fourth item
- fifth item # 注意,此处缺少一个
闭合标签