超详细!scrapy的xpath语法解释

BeautifulSoup 能查找 HTML 中的元素,而scrapy 中也有强大的查找 HTML 元素的功能。
那就是使用 xpath 方法。xpath 方法使用 XPath 语法,比BeautifulSoup 的 select 要灵活而且速度快。

举例:

from scrapy.selector import Selector
htmlText='''
<html><body>
<bookstore> 
<book>
 <title lang="eng">Harry Potter</title>
 <price>29.99</price>
</book> 
<book>
 <title lang="eng">Learning XML</title>
 <price>39.95</price>
</book>
</bookstore>
</body></html>
'''
selector=Selector(text=htmlText)
s=selector.xpath("//title")

selector=Selector(text=htmlText)
使用 htmlText 的文字建立 Selector 类,就是装载 HTML 文档,文档装载后就形成一个Selector 对象,就可以使用 xpath 查找元素。

语法

1、"//“与”/"的使用

使用"//“表示文档下面的所有节点元素,用”/"表示当前节点的下一级节点元素。

实例:
selector.xpath("//bookstore/book") 搜索<bookstore>下一级的<book>元素,找到 2 个;
selector.xpath("//body/book") 搜索<body>下一级的<book>元素,结果为空;
selector.xpath("//body//book") 搜索<body><book>元素,找到 2 个;
selector.xpath("/body//book") 搜索文档下一级的<body>下的<book>元素,找结果为空,因为文档的下一级是<html>元素,不是<body>元素;
selector.xpath("/html/body//book")或者 selector.xpath("/html//book") 搜索<book>元素,找到 2 个;
selector.xpah("//book/title") 搜索文档中所有<book>下一级的<title>元素,找到 2 个,结果与 selector.xpah("//title")selector.xpath("//bookstore//title")一样;
selector.xpath("//book//price")与 selector.xpath("//price")结果一样,都是找到 2 个元素;

2、"."的使用

使用"."表示当前节点元素,使用 xpath 可以连续调用,如果前一个 xpath 返回一个
Selector 的列表,那么这个列表可以继续调用 xpath,功能是为每个列表元素调用 xpath,
最后结果是全部元素调用 xpath 的汇总。

selector.xpath("//book").xpath("./title")是先搜索到文档中所有<book>元素,然后是从当前元素开始往下一级搜索<title>
selector.xpath("//book").xpath("/title")相比与上面少了 “.”,表示先搜索到文档中所有<book>元素,然后是从头开始搜索所有下一级节点<title>

3、extract()函数

xpath 返回的 Selector 对象列表,再次调用 extract()函数会得到这些对象的元素文本的列表,使用 extract_first()获取列表中第一个元素值,如果列表为空 extract_first()的值为 None。

对于单一的一个 Selector 对象,调用 extract()函数就可以得到 Selector 对象对应的元素的文本值。单一的 Selector 对象没有 extract_first()函数。

举例:

from scrapy.selector import Selector
htmlText='''<html> <body> <bookstore> <book id="b1">
 <title lang="english">Harry Potter</title>
 <price>29.99</price>
</book> <book id="b2">
 <title lang="chinese">学习 XML</title>
 <price>39.95</price>
</book>
</bookstore>
</body></html>'''

s=selector.xpath("//book/price") 得到的是 SelectorList 列表;
s=selector.xpath("//book/price").extract() 得到的是<price>元素的 Selector 对象对应的<price>元素的文本组成的列表,即:['<price>29.99</price>', '<price>39.95</price>']
s=selector.xpath("//book/price").extrac_first() 得到的是<price>元素的文本组成的列表的
第一个元素,是一个文本,即:<price>29.99</price>

4、@attrName

xpath 使用"/@attrName"得到一个 Selector 元素的 attrName 属性节点对象,属性节点对象也是一个 Selector 对象,通过 extract()获取属性值。

5、/text()

xpath 使用"/text()"得到一个 Selector 元素包含的文本值,文本值节点对象也是一个Selector 对象,通过 extract()获取文本值。

如:s=selector.xpath("//book/title/text()"); print(s)
查询结果:[<Selector xpath='//book/title/text()' data='Harry Potter'>, <Selector xpath='//book/title/text()' data='学习 XML'>]
s.extract():结果是文本节点的字符串值的列表,即[‘Harry Potter’, ‘学习 XML’]

是如果一个 element 的元素包含的文本不是单一的文本,那么可能会产生多个文本值。

6、tag[condition]

xpath 使用"tag[condition]"来限定一个 tag 元素,其中 condition 是由这个 tag 的属性、文本等计算出的一个逻辑值。

如果有多个条件,那么可以写成:“tag[condition1][condition2]…[conditionN]”
或者:“tag[condition1 and condition2 and … and conditionN]”

也可以使用and和or等符号构成复杂表达式

7、position()

xpath 可以使用 position()来确定其中一个元素的限制,这个选择序号是从 1 开始的,不是从 0 开始编号的,还可以通过 and、or 等构造复杂的表达式。

8、" * "

xpath 使用星号"*"代表任何 Element 节点,不包括 Text、Comment 的节点。

如:s=selector.xpath("//bookstore/*/title")表示搜索<bookstore>的孙子节点<title>,中间隔开一层任何元素。

9、 @*

xpath 使用"@*"代表任何属性

如:s=selector.xpath("//book[@*]/title")表示搜索任何包含属性<book>元素下面的<title>

10、父节点

xpath 使用element/parent::*选择 element 的父节点,这个节点只有一个。

如果写成 element/parent::tag,就指定 element 的 tag 父节点,除非 element 的父节点正好为><tag>节点,不然就为 None。

11、兄弟节点

11.1 following-sibling

xpath 使用"element/folllowing-sibling::*"搜索 element 后面的同级的所有兄弟节点,
使用"element/folllowing-sibling::*[position()=1]" 搜索 element 后面的同级的第一个兄弟节点。

如:s=selector.xpath("//b[position()=1]/following-sibling::*[position()=1]")
是搜索第一个<b>节点后面的第一个兄弟节点,即<c>C1</c>节点。

11.2 preceding-sibling

xpath 使用"element/preceding-sibling::*"搜索 element 前面的同级的所有兄弟节点,
使用"element/preceding-sibling::*[position()=1]" 搜索 element 前面的同级的第一个兄弟节点。

举例:

from scrapy.selector import Selector
htmlText="<a>A1</a><b>B1</b><c>C1</c><d>D<e>E</e></d><b>B2</b><c>C2</c>"
selector=Selector(text=htmlText)
s=selector.xpath("//b/preceding-sibling::*[position()=1]")

#搜索的是所有<b>前面的第一个兄弟节点,有 2 个<b>节点
#结果是['<a>A1</a>','<d>D<e>E</e></d>']

12、部分属性值匹配

lis = selector.xpath("//li['@ddt-pit'][starts-with(@class,'line')]")表示匹配属性class的以line开头的属性值的元素。
lis = selector.xpath("//li['@ddt-pit'][ends-with(@class,'line')]")表示匹配属性class的以line结尾的属性值的元素。
lis = selector.xpath("//li['@ddt-pit'][contains(@class,'line')]")表示匹配属性class的包含line的属性值的元素。

By.xpath("//input[@*=‘fuck’]"))//匹配所有input元素中含有属性的值为fuck的元素元素。

————————————
以上。

发布了70 篇原创文章 · 获赞 15 · 访问量 4295

猜你喜欢

转载自blog.csdn.net/Heart_for_Ling/article/details/103590220