xpath中两个冒号_爬虫学习(5)—XPath

xpath中两个冒号_爬虫学习(5)—XPath

2023年6月29日发(作者:)

xpath中两个冒号_爬⾍学习(5)—XPath之前我们写了⼀个简单的爬⾍,在提取页⾯信息时我们使⽤正则表达式来匹配内容,但是正则表达式的书写⽐较繁琐,⽽且⼀旦错误就可能导致匹配失败。对于⽹页的节点来说,它可以定义id,class或其他的属性,⽽且节点之间还有层次关系,在⽹页中可以通过xpath后css选择器来定位⼀个或多个节点。那么,我们在解析页⾯时,利⽤CSS和XPath选择器来定位节点,再调⽤相关⽅法来获取其正⽂内容或属性。本⽂介绍XPath。概述XPath的选择功能⼗分强⼤,提供了100多个内建函数,⽤于字符串、数值、时间的匹配和节点、序列的处理。常⽤规则nodename 选取此节点的所有⼦节点/ 从当前节点选取直接⼦节点// 从当前节点选取⼦孙节点. 选取当前节点.. 选取当前节点的⽗节点@ 选取属性这⾥就是XPath的常⽤匹配规则,⽰例如下://title[@lang='eng']这个就表⽰选择所有名称为title,同时属性lang的值为eng的节点。3.准备⼯作安装好lxml库。4.实例引⼊我们来通过实例来感受⼀下使⽤XPath来对⽹页进⾏解析的过程。from lxml import etreetext = '''

  • first item
  • second item
  • third item
  • fourth item
  • fifth item
'''html = (text)result = ng(html)print(('utf-8'))这⾥我们先导⼊lxml库的etree模块,然后声明⼀段HTML⽂本,在调⽤HTML类进⾏初始化,这样就成功构造了⼀个XPath解析对象。我们可以注意到HTML⽂本中最后⼀个li节点是没有闭合的,但是etree模块可以⾃动修正HTML ⽂本。我们调⽤tostring()⽅法即可输出修正后的HTML代码,但是结果是bytes类型。这⾥利⽤decode()⽅法将其转换为str类型。我们也可以通过直接读取⽂件来进⾏解析。from lxml import etreehtml = ('./', rser())result = ng(html)print(('utf-8'))其中的内容就是上⾯的HTML代码。5.所有节点我们⼀般会⽤//开头的XPath规则来选取所有符合要求的节点。result = ('//*')print(result)这⾥使⽤*来匹配所有节点,也就是整个HTML⽂本中的所有节点都会被获取,返回形式是⼀个列表,每个元素都是Element类型,后⾯跟着节点的名称。当然,此处匹配也可以指定节点名称。如果想获取所有li节点,如下:result = ('//li')print(result)print(result[0])如果我们要取出其中⼀个对象,可以直接⽤中括号加索引,如[0]。6.⼦节点我们通过/或//即可查找元素的⼦节点或⼦孙节点。假设我们现在想选择li节点的所有直接a节点,可以这样实现:result = ('//li/a')如果想获得所有⼦孙节点,则可使⽤//。例如,要获取ul节点下的所有⼦孙a节点,可以这样实现:result = ('//ul//a')/⽤于获取直接⼦节点,//⽤于获取⼦孙节点。7.⽗节点我们在上⾯讲了如何查找⼦节点或⼦孙节点,那么加⼊我们知道了⼦节点,怎么来查找⽗节点呢?可以⽤..来实现。⽐如,我们选中属性为的a节点,然后获取其⽗节点,然后再获取其class属性。result = ('//a[@href=""]/../@class')同时也可以使⽤parent::来获取⽗节点。result = ('//a[@href=""]/parent::*/@class')8.属性匹配在选取时,我们还可以使⽤@符号进⾏属性过滤。⽐如,这⾥如果要选取class为item-0的li节点,可以这样实现:result = ('//li[@class="item-0"]')这⾥我们通过加⼊[@class="item-0"],限制了节点的class属性为item-0,⽽HTML ⽂本中符合的li节点有两个,所以结果应该返回两个匹配到的元素。9.⽂本获取我们使⽤XPath中的text()⽅法获取节点中的⽂本,接下来尝试获取前⾯li节点中的⽂本。result = ('//li[@class="item-0"]/text()')我们运⾏之后没有获取任何⽂本。这是为什么呢?因为XPath中text()前⾯是/,代表选取直接⼦节点,很明显li节点的直接⼦节点都是a节点,⽂本都是在a节点内部的,所以只匹配到被修正的li节点内部的换⾏符。因为⾃动修正的li节点的尾标签换⾏了。即选中的是这两个节点:
  • first item
  • fifth item
  • 因此,如果想获取li节点内部的⽂本,就有两种⽅式:⼀种是先选取a节点再获取⽂本,另⼀种是使⽤//。result = ('//li[@class="item-0"]/a/text()')运⾏结果为:['first item', 'fifth item']这⾥我们是逐层选取,先选取了li节点,⼜利⽤/选取了其直接⼦节点a。result = ('//li[@class="item-0"]//text()')运⾏结果为:['first item', 'fifth item', 'n ']这⾥是选取所有⼦孙节点的⽂本,其中两个是li的⼦节点a节点内部的⽂本,另外⼀个就是最后⼀个li节点内部的⽂本,即换⾏符。10.属性获取我们使⽤text()⽅法获取⽂本内容,我们也可以⽤@href来获取节点的href属性。result = ('//li/a/@href')11.属性多值匹配有时候,某些节点的某个属性有多个值,例如:from lxml import etreetext = '''
  • first item
  • '''html = (text)result = ('//li[@class="li"]/a/text()')print(result)这⾥返回的结果是[],因为li的class属性有两个值li和li-first,此时还想⽤之前的属性匹配获取就⽆法匹配了。这时就需要⽤contains()函数了,代码如下:result = ('//li[contains(@class, "li")]/a/text()')这样就会得到结果['first item']。12.多属性匹配另外,我们还会碰到另⼀种情况,那就是依据多个属性来确定⼀个节点,这时就需要同时匹配多个属性,此时我们可以使⽤运算符and来连接。from lxml import etreetext = '''
  • first item
  • '''html = (text)result = ('//li[contains(@class, "li") and @name="item"]/a/text()')print(result)这⾥的li节点⼜增加了⼀个属性name。要确定这个节点,需要⽤时根据class和name来选择,中间⽤and相连,相连之后置于中括号内进⾏条件筛选。除了and之外还有其他的运算符可以使⽤。13.顺序选择我们在选择的时候某些属性可能已经匹配了多个节点,但是我们只想要其中的某个节点,如第⼆个节点或者最后⼀个节点。from lxml import etreetext = '''
    • first item
    • second item
    • third item
    • fourth item
    • fifth item
    '''html = (text)result = ('//li[1]/a/text()')print(result)result = ('//li[last()]/a/text()')print(result)result = ('//li[position()<3]/a/text()')print(result)result = ('//li[last()-2]/a/text()')print(result)第⼀次选择时,我们选取了第⼀个li节点,这⾥在中括号中传⼊1就可。第⼆次选择时,我们选取最后⼀个li节点,中括号中传⼊last()即可。第三次选择时,我们选取了位置⼩于3的li节点,运⽤了position()函数。第四次选择时,我们选择了都输第三个li节点,中括号中传⼊last()-2即可。在Xpath中,提供了100多个函数,包括存取、数值、字符串、逻辑、节点、序列等的处理功能。14.节点轴选择XPath提供了许多节点轴选择⽅法,包括获取⼦元素、兄弟元素、⽗元素、祖先元素等,⽰例如下:from lxml import etreetext = '''
    • first item
    • second item
    • third item
    • fourth item
    • fifth item
    '''html = (text)result = ('//li[1]/ancestor::*')print(result)result = ('//li[1]/ancestor::div')print(result)result = ('//li[1]/attribute::*')print(result)result = ('//li[1]/child::a[@href=""]')print(result)result = ('//li[1]/descendant::span')print(result)result = ('//li[1]/following::*[2]')print(result)result = ('//li[1]/following-sibling::*')print(result)第⼀次选择时,我们调⽤了ancestor轴,可以获取所有的祖先节点。之后需要跟两个冒号,然后是节点的选择器,这⾥我们使⽤*,表⽰匹配所有节点。第⼆次选择时,我们⼜加了限定条件div,这时得到的结果就只有div这个祖先节点了。第三次选择时,我们调⽤了attribute轴,可以获取所有属性值,其建瓯跟的选择器还是*,代表获取节点的所有属性。第四次选择时,我们调⽤了child轴,可以获取所有直接⼦节点。这⾥我们⼜加⼊了限定条件,选取href属性为的a节点。第五次选择时,我们调⽤了descendant轴,可以获取所有的⼦孙节点。这⾥我们⼜加⼊了限制条件获取span节点。所以返回的结果只包含span节点⽽不包括a节点。第六次选择时,我们调⽤了following轴,可以获取当前节点之后的所有节点。这⾥我们使⽤*匹配,但⼜加⼊了索引选择,所以只获取了第⼆个后续节点。第七次选择时,我们调⽤了following-sibling轴,可以获取当前节点之后的所有同级节点。这⾥我们使⽤*匹配,获取所有后续同级节点。参考书⽬:《Python 3 ⽹络爬⾍开发实战》

    发布者:admin,转转请注明出处:http://www.yc00.com/news/1687983017a63584.html

    相关推荐

    发表回复

    评论列表(0条)

    • 暂无评论

    联系我们

    400-800-8888

    在线咨询: QQ交谈

    邮件:admin@example.com

    工作时间:周一至周五,9:30-18:30,节假日休息

    关注微信