通过xpath实现if...else...逻辑

最近学习xpath(1.0)相关知识,在做数据抓取匹配的时候遇到一个问题,几经折腾解决了问题,记录下来分享给大家。

问题: 这是待匹配的数据,要抓取的数据在span标签class= ellipsis vip里面,【第一百一十二章 文章标题,该章节已被锁定】这两个文章标题,但是我们可以看到两个span标签里面的内容不一致,其中第二个span里面还有个span。

xml 复制代码
<dl class="Volume">
   <dt>
      <a class="folding" href="javascript:">- 收起</a>
      <span class="tit">正文</span><span class="info">已更新1111章</span>
   </dt>
   <dd>
         <a target="_blank"
            href="/chapter/1111/aaaa.html">
               <span class="ellipsis vip">
                     第一百一十二章 文章标题
               </span>
         </a>
         <a target="_blank"
            href="/chapter/2222/bbbb.html">
               <span class="ellipsis vip">
                     <span class="red">【锁】</span>
                     该章节已被锁定
               </span>
         </a>
   </dd>
</dl>

这就很麻烦了,我们写两个xpath去匹配这两种结构的数据

css 复制代码
//dl[@class="Volume"]//dd/a/span/text() //这个匹配第一个文章标题
//dl[@class="Volume"]//dd/a/span/span/following-sibling::text() //这个匹配第二个文章标题

而且代码还要加判断,选择哪种xpath匹配哪种数据,变得很繁琐。所以直接查找xpath语法是否有判断的逻辑,等于是说在xpath匹配的时候,就把判断加上了,直接写一个就行了。那究竟有没有呢?

解决问题: 通过谷歌搜索,在stackoverflow发现了这个回答: stackoverflow.com/questions/1... 里面的解决方法提出了一个这样的xpath表达式

bash 复制代码
concat(substring($stringA, 1 div $cond), substring($stringB, 1 div not($cond)))

这里有几个知识点要串联一下:

  • div 这是xpath的除法符号,1 div 1 ,就是1除以1的意思
  • not() 这个可以理解为取反,not(1)的结果就是0
  • substring 用来截取字符串,参数为substring(string,number,length),string用于指定要截取的字符串;number用于指定开始位置;length用于指定截取字符串的长度。如果缺少length参数将从开始位置number一直到截取字符串的长度。这个很重要,这个知识点要注意,比如substring("12345",1),取到的值就是12345,从第一位开始取值,substring("12345",2),取到的值就是2345,从第二位开始取值。但是如果number是个无穷大的值呢,我们的字符串都是有长度的,不可能无穷大,所以这时候就没有值可以返回了,这个是上面那个表达式实现的重点。
  • concat 用于串连多个字符串

好了,知识点讲完,我们回头来分析这个表达式,stringA,stringB我们可以理解为我们要返回的字符串,cond可以理解为我们的条件,如果cond为1,那前面的1 div 1就是1除以1等于1,后面的1 div not($cond)就变成1 div not(1),1 div 0就是1除以0,结果是个无穷大的值,这时候表达式就变成这样

bash 复制代码
concat(substring($stringA, 1), substring($stringB, 无穷大))
//substring($stringA, 1) 从第一位开始取值,等于直接返回了$stringA
//substring($stringB, 无穷大) 这个值就等于取值不了了,所以就是空,就变成了下面的表达式
concat($stringA) 
//其实就等于直接返回了$stringA这个字符串

那我们就尝试修改,看看是否能修改成上面的表达式,直接上成果

less 复制代码
//这里我把路径改短了,后面有完整代码
concat(substring(./span/span/following-sibling::text(), 1 div boolean(./span/span/following-sibling::text())),substring(./span/text(), 1 div not(./span/span/following-sibling::text())))

这个修改后整个表达式非常长,先解释逻辑,这里我们加上了个boolean,用来判断进行第一次匹配时是否满足./span/span/following-sibling::text(),也就是要匹配【该章节已被锁定】这个结果的,但是第一次其实是不满足的,所以第一个boolean(./span/span/following-sibling::text())就是返回0,第一个substring返回了空,第二个substring返回了匹配到的字符串。

接下来第二次匹配,./span/span/following-sibling::text()满足匹配,boolean(./span/span/following-sibling::text())返回1,第一个substring返回字符串。第二个substring的not(./span/span/following-sibling::text())取反返回了0,所以第二个substring没有返回字符串。

完整代码:

ini 复制代码
with open("test.html", encoding="utf-8") as f:
    data = f.read()

selector = etree.HTML(data)
lists = selector.xpath('//dl[@class="Volume"]//dd/a')

for bookList in lists:
    name = bookList.xpath('concat(substring(./span/span/following-sibling::text(), 1 div boolean(./span/span/following-sibling::text())),substring(./span/text(), 1 div not(./span/span/following-sibling::text())))').strip()
    print(name)
相关推荐
FlDmr4i2814 小时前
网络爬虫是自动从互联网上采集数据的程序
爬虫
源码之家16 小时前
计算机毕业设计:Python股票交易管理可视化系统 Django框架 requests爬虫 数据分析 可视化 大数据 大模型(建议收藏)✅
爬虫·python·深度学习·信息可视化·数据分析·django·课程设计
篮子里的玫瑰17 小时前
Python与网络爬虫——列表与元组
开发语言·爬虫·python
电商API_1800790524719 小时前
如何实现批量化自动化获取淘宝商品详情数据?爬虫orAPI?
大数据·c++·爬虫·自动化
源码之屋20 小时前
计算机毕业设计:Python天天基金数据采集与智能分析平台 Django框架 数据分析 可视化 爬虫 大数据 大模型(建议收藏)✅
人工智能·爬虫·python·数据分析·django·flask·课程设计
源码之家21 小时前
计算机毕业设计:Python基金股票数据分析与可视化平台 Django框架 数据分析 可视化 爬虫 大数据 大模型(建议收藏)✅
爬虫·python·信息可视化·数据分析·django·flask·课程设计
小花皮猪2 天前
2026 SERP + LLM 训练数据采集指南(Bright Data MCP + Dify)
人工智能·爬虫·工作流·dify·serp
小白学大数据2 天前
企业精准数据分析双路径对比:运营商大数据与 Python 爬虫技术选型与实践
大数据·开发语言·爬虫·python·数据分析
袁袁袁袁满2 天前
亮数据SERP API实现搜索引擎实时数据采集
爬虫·python·网络爬虫·爬山算法
源码之家2 天前
计算机毕业设计源码:京东商品数据采集分析可视化系统python Django Selenium爬虫 人工智能 大数据(建议收藏)✅
人工智能·爬虫·python·信息可视化·数据分析·django·课程设计