影刀RPA XPath模糊匹配实战:文本包含与动态内容定位
影刀RPA XPath模糊匹配实战文本包含与动态内容定位作者林焱 | 适合人群已经会基本XPath但遇到动态内容就束手无策的新手什么情况用什么上一篇文章讲了属性选择器适合属性值固定的情况。但现实中更多遇到的是元素文本是动态的今天显示共找到123条结果明天变成共找到456条结果元素属性是动态的class里有随机字符串每次刷新都变你只知道元素文本的一部分比如小红书号abc123但你只知道要找包含小红书号的元素这些情况下精确匹配属性固定值就不好使了。XPath模糊匹配就是解决这个问题的——不需要知道完整内容只要知道一部分就能定位到元素。怎么做contains()最常用文本包含某字符串语法//标签名[contains(属性或文本,部分字符串)]实战1定位包含小红书号的元素小红书个人主页上有一行显示小红书号abc123。这个元素的完整文本是小红书号abc123但你不需要知道具体的号是多少只要定位到包含小红书号这个文字的元素就行。XPath写法//*[contains(text(),小红书号)]解释//*— 搜索页面上所有元素[contains(text(),小红书号)]— 筛选条件元素的文本内容包含小红书号这几个字实战2定位class包含特定关键词的元素有些网站的class是会变的但中间某一部分不变。比如divclassitem-card-12345divclassitem-card-67890class的前缀item-card-是固定的后面跟着的是动态数字。店群矩阵自动化突破运营极限XPath写法//div[contains(class,item-card-)]实战3结合两个contains做精确筛选如果你想找包含A并且包含B的元素//div[contains(class,item) and contains(text(),价格)]starts-with()和ends-with()以某字符串开头或结尾starts-with()以某字符串开头适合定位那些有固定前缀的元素。比如按钮的id是btn-submit-123、btn-submit-456前缀btn-submit-是固定的。XPath写法//button[starts-with(id,btn-submit-)]ends-with()以某字符串结尾注意ends-with()在有些浏览器里不支持主要是旧版Chrome但影刀内置的Chromium是支持的。适合定位有固定后缀的元素//script[ends-with(src,.min.js)]text()精确匹配元素文本如果你知道元素的完整文本用text()完整文本比contains(text(),部分文本)更精确。比如页面上有两个按钮一个显示确定一个显示取消//button[text()确定]参照物定位先找到一个已知元素再找它旁边元素这是XPath里最强大的技巧之一。场景知道小红书号这个标签要找它旁边的具体号码HTML结构可能是这样的divclassinfo-rowspanclasslabel小红书号/spanspanclassvalueabc123/span/div你要找的是abc123但它没有固定的id或class。解决方法先定位到小红书号这个标签然后找它的下一个兄弟元素。XPath写法//span[contains(text(),小红书号)]/following-sibling::*[1]解释//span[contains(text(),小红书号)]— 先找到小红书号这个span/following-sibling::*— 找它后面的所有兄弟元素[1]— 取第一个也就是紧挨着它的那个span内容是abc123preceding-sibling找前面的兄弟元素如果目标元素在已知元素的前面//span[contains(text(),小红书号)]/preceding-sibling::*[1]实战案例自动提取小红书笔记的互动数据这是手册里提到的真实场景。小红书笔记详情页上有点赞数、收藏数、评论数但它们的class是动态生成的。通过观察发现这些数字都在一个class为interact-container的div里面并且按固定顺序排列点赞、收藏、评论。XPath写法//div[classinteract-container]//child::*[1] ← 点赞数 //div[classinteract-container]//child::*[2] ← 收藏数 //div[classinteract-container]//child::*[3] ← 评论数有什么坑坑1contains()匹配到了多个元素//div[contains(class,item)]可能会匹配到十几个元素因为很多div的class里都包含item这个词。temu店群自动化报活动案例解决方案加更多限制条件//div[contains(class,item) and data-typeproduct]用索引取指定位置(//div[contains(class,item)])[3]坑2文本里有看不见的空格或换行网页上的文本在HTML源码里可能是这样的span小红书号/span看起来文本是小红书号但实际上前后有换行和空格。contains(text(),小红书号)可能匹配不到。解决方案用normalize-space()函数去掉多余空格//span[contains(normalize-space(text()),小红书号)]坑3following-sibling在影刀里语法要写对影刀的XPath解析器对following-sibling和preceding-sibling的支持是完整的但语法要写对正确//span[text()小红书号]/following-sibling::span[1]错误少了最后的索引//span[text()小红书号]/following-sibling::*这种写法在有些情况下会报错因为following-sibling::*返回的是所有后面的兄弟元素不是一个确定的元素。坑4页面是动态加载的元素还没出现XPath能定位到已经存在于DOM树里的元素但如果元素是滚动到可视区域才加载的懒加载直接写XPath会失败。解决方案先用「模拟滚动」指令把页面滚到目标区域加「等待元素出现」指令再用XPath定位总结模糊匹配的核心就是三个函数contains()、starts-with()、ends-with()。记住一个原则能精确就别模糊但遇到动态内容模糊匹配是你的好朋友。下一篇讲参照物定位的深度用法解决那些没有id、没有固定class、文本也是动态的硬骨头元素。作者林焱