首页 / 资讯中心 / 文章详情

影刀RPA新手教程:XPath实战手册——六种写法在真实采集项目中的选择与避坑

影刀RPA新手教程:XPath实战手册——六种写法在真实采集项目中的选择与避坑 ★ FEATURED ARTICLE
影刀RPA新手教程XPath实战手册——六种写法在真实采集项目中的选择与避坑XPath是RPA元素定位的核心技能。上一篇文章讲了元素定位的基础这篇专攻XPath把六种写法讲透。我第一次写XPath的时候照着教程抄结果一个字符都不对。后来踩了几十个坑才总结出这套实战经验。这篇不讲理论直接给用法、给代码、给坑点。一、XPath六种写法详解1.1 写法一属性选择器适合稳定元素语法格式//标签[属性属性值]什么时候用元素的属性值是稳定的不会随机变化知道准确的属性名和属性值真实项目代码百度搜索框//input[idkw]代码解释//input找页面上所有的input标签[idkw]筛选出id等于kw的那个input另一个真实案例淘宝商品搜索框//input[idq]为什么用这个写法百度搜索框的id是kw淘宝商品搜索框的id是q这些都是前端开发固定的不会变。用属性选择器定位准确率接近100%。踩坑点1属性值写错一个字符就匹配不到。我第一次做的时候把[idkw]写成了[idkw ]多了个空格排查了一下午心态直接崩。解决方案F12打开开发者工具直接复制属性值不要手敲。踩坑点2属性值包含引号。比如value他说你好这种字符串里有引号XPath会报错。解决方案用单引号包裹比如[value他说你好]。踩坑点3属性值很长不想写全。比如classsubmit-btn btn-primary btn-large btn-hover写全了太麻烦。解决方案用contains函数见写法二。1.2 写法二模糊匹配contains适合只确定部分元素语法格式//标签[contains(属性,部分值)]什么时候用只知道属性值的一部分属性值太长不想写全属性值包含多个值比如class有多个类名真实项目代码小红书号//span[contains(text(),小红书号)]代码解释//span找页面上所有的span标签[contains(text(),小红书号)]筛选出文本内容包含小红书号的span为什么用这个写法小红书号的格式是小红书号xxxx冒号后面的数字是变化的但小红书号这五个字是固定的。用contains可以匹配到整个span然后再用正则表达式提取冒号后面的数字。具体操作流程在影刀中实现用【获取元素对象(web)】指令定位方式选择XPath选择器XPath填写//span[contains(text(),小红书号)]用【获取元素文本内容(web)】指令获取整个文本比如小红书号abc123用【从文本中提取内容】指令正则表达式填写小红书号(.*)提取出abc123另一个真实案例匹配class包含多个值的情况//div[contains(class,note-title)]这样可以匹配classnote-titleclassnote-title hotclasshot note-title如果用属性选择器[classnote-title]只能匹配第一种情况后两种都匹配不到。踩坑点1contains是模糊匹配可能匹配到多个元素。解决方案加上位置限制。(//div[contains(class,note-title)])[1]意思是取第一个匹配项。踩坑点2text()包含空白字符。比如页面源码是span小红书号 abc123 /span前后有空格用contains(text(),小红书号)可能匹配不到。解决方案用normalize-space函数去掉空白字符。//span[contains(normalize-space(text()),小红书号)]1.3 写法三参照物定位preceding-sibling/following-sibling适合通过上下文定位语法格式//标签[属性属性值]/preceding-sibling::标签 # 找前面的兄弟节点 //标签[属性属性值]/following-sibling::标签 # 找后面的兄弟节点什么时候用要定位的元素没有明确属性但它旁边有个有明确属性的元素元素之间的相对位置是固定的真实项目代码小红书笔记的点赞数//span[text()点赞]/following-sibling::span代码解释//span[text()点赞]找到文本是点赞的span这就是参照物/following-sibling::span找它后面的兄弟span就是点赞数为什么用这个写法小红书笔记详情页点赞数、收藏数、评论数这三个数据结构是一样的span点赞/spanspan1234/spanspan收藏/spanspan567/spanspan评论/spanspan89/span点赞数在点赞这个span的后面所以用following-sibling::span就能定位到。如果要定位收藏数//span[text()收藏]/following-sibling::span如果要定位评论数//span[text()评论]/following-sibling::span另一个真实案例找前面的兄弟节点//span[text()收藏数100]/preceding-sibling::span这样可以找到收藏数100前面的span比如可能是收藏的图标。踩坑点1preceding-sibling和following-sibling只能找同级节点。如果要找父节点用parent::。//span[text()点赞]/parent::div如果要找子节点用child::见写法四。踩坑点2兄弟节点有多个需要调整下标。比如点赞后面的第一个span是点赞数第二个span可能是其他内容。解决方案用下标精确控制。//span[text()点赞]/following-sibling::span[1] # 第一个兄弟节点 //span[text()点赞]/following-sibling::span[2] # 第二个兄弟节点1.4 写法四层级定位child::适合逐层精确提取语法格式//父标签/child::子标签简化写法child::可以省略//父标签/子标签什么时候用要精确定位某个父节点下的第几个子节点页面结构规律层级关系明确真实项目代码小红书笔记的点赞数、收藏数、评论数//div[classinteract-container]/div[1] # 点赞数 //div[classinteract-container]/div[2] # 收藏数 //div[classinteract-container]/div[3] # 评论数代码解释//div[classinteract-container]找到class是interact-container的div这是点赞、收藏、评论的容器/div[1]找它的第一个子div点赞数为什么用这个写法小红书笔记的互动数据点赞、收藏、评论都放在interact-container这个div里面而且是按顺序排列的。用child::可以精确控制取第几个。踩坑点1如果页面结构变了比如插入了一个新的div下标可能错位。我第一次做的时候写完流程测试没问题。过了一个星期再用发现采集到的点赞数和收藏数反了。排查了半天发现页面改版插入了一个新的div导致下标全乱了。解决方案优先用contains或preceding-sibling/following-sibling减少对下标的依赖如果必须用下标定期维护页面改版后及时更新XPath踩坑点2下标从1开始不是从0开始。这是XPath的语法规则和Python的列表索引不同。错误写法//div[classinteract-container]/div[0] # 这样写会报错正确写法//div[classinteract-container]/div[1] # 第一个子div1.5 写法五starts-with/ends-with适合属性值有规律的情况语法格式//标签[starts-with(属性,开头部分)] # 匹配以开头部分开始的属性值 //标签[ends-with(属性,结尾部分)] # 匹配以结尾部分结束的属性值什么时候用属性值有规律比如都是以某个前缀开头或以某个后缀结尾属性值的前缀或后缀是固定的但中间部分会变化真实项目代码电商商品列表的商品ID//div[starts-with(id,product-)]代码解释starts-with(id,product-)匹配id以product-开头的div比如idproduct-12345、idproduct-67890都能匹配到另一个真实案例匹配以.jpg结尾的图片//img[ends-with(src,.jpg)]这样可以匹配所有jpg格式的图片。踩坑点1ends-with在XPath 1.0中不支持。Chrome浏览器使用的是XPath 1.0所以ends-with会报错。解决方案用contains代替或者升级到支持XPath 2.0的浏览器。用contains代替ends-with//img[contains(src,.jpg)]注意这样也会匹配到.jpg.png这种文件名不够精确。更精确的解决方案用正则表达式。//img[matches(src,\.jpg$)]但matches函数也是XPath 2.0才支持的Chrome不支持。最终方案在影刀中用【从文本中提取内容】指令用正则表达式\.jpg$过滤。1.6 写法六组合写法实战中最灵活语法格式把前面的写法组合起来实现复杂定位。真实项目代码小红书笔记详情页提取发布时间//div[classnote-meta]/span[contains(text(),发布于)]/following-sibling::span[1]代码解释从右往左读following-sibling::span[1]找前面的span节点的后面第一个兄弟span/span[contains(text(),发布于)]这个span的文本内容包含发布于//div[classnote-meta]这个span在class是note-meta的div里面为什么用组合写法真实项目的页面结构通常很复杂单一写法可能搞不定。组合写法可以应对各种复杂情况。另一个真实案例电商商品列表提取商品名称但只限前两行//div[classproduct-list]/div[position()2]/div[classproduct-name]代码解释position()2限制只取前两个商品这样可以实现只采集前两行数据的需求position()函数返回当前节点的位置。更多组合写法的例子例1匹配class包含note-title且文本包含教程的div。//div[contains(class,note-title) and contains(text(),教程)]例2匹配class包含note-title或class包含article-title的div。//div[contains(class,note-title) or contains(class,article-title)]例3匹配class包含note-title但文本不包含广告的div。//div[contains(class,note-title) and not(contains(text(),广告))]二、XPath校验工具和常见语法报错2.1 XPath校验工具写好的XPath怎么验证对不对下面两个工具可以帮到你。工具一Chrome开发者工具最常用操作步骤F12打开开发者工具按CtrlFMac是CmdF打开搜索框输入XPath回车如果XPath正确匹配到的元素会高亮显示并且显示匹配数量我第一次做的时候不知道有这个功能的写完XPath就直接往影刀里填结果报错。现在都是先在开发者工具里验证确认无误再填到影刀里。工具二XPath HelperChrome插件这是一个Chrome插件可以实时验证XPath。安装方法在Chrome应用商店搜索XPath Helper点击添加至Chrome使用方法打开需要采集的网页点击浏览器右上角的XPath Helper图标在XPath输入框中填写XPath实时显示匹配结果踩坑XPath Helper在某些网站上无法使用比如有反爬机制的网站。解决方案用Chrome开发者工具代替。2.2 常见语法报错及解决方案报错一SyntaxError: Invalid XPath expression原因XPath语法写错了。常见错误引号不匹配。错误//div[classnote-title]正确//div[classnote-title]括号不匹配。错误//div[contains(class,note-title正确//div[contains(class,note-title)]使用了不存在的函数。错误//div[matches(class,note-title)]matches函数XPath 1.0不支持正确//div[contains(class,note-title)]解决方案仔细检查XPath语法确保引号、括号都匹配。报错二Unable to locate element with XPath原因XPath没有问题但页面上没有匹配的元素。常见原因页面还没加载完成。元素在iframe里面。元素在动态加载的内容里面。解决方案在【获取元素对象(web)】指令中设置等待元素存在(s)为5秒或更长。如果元素在iframe里面先用【切换到iframe(web)】指令切换到iframe再定位元素。如果元素是动态加载的用【循环相似元素(web)】指令等待元素出现。报错三XPath returned multiple elements, expected one原因XPath匹配到了多个元素但指令只接受一个元素。解决方案用下标限制只取第一个匹配项。(//div[classnote-title])[1]改用【获取相似元素列表(web)】指令获取所有匹配的元素。三、案例实战采集电商商品列表页下面用一个完整案例把XPath六种写法串起来。需求采集电商商品列表页的以下数据每个商品商品标题商品价格商品销量评价数实现方案对每个数据用不同的XPath写法为了演示不同写法在实际项目中的选择。3.1 采集商品标题用属性选择器商品标题通常有稳定的class或id用属性选择器最合适。XPath写法//div[classproduct-title]指令配置用【获取相似元素列表(web)】指令定位方式选择XPath选择器XPath填写上面的代码元素操作选择获取元素文本内容保存到变量商品标题列表3.2 采集商品价格用contains模糊匹配商品价格的class可能包含多个值比如classprice current-price用contains更稳妥。XPath写法//span[contains(class,price)]指令配置用【获取相似元素列表(web)】指令定位方式选择XPath选择器XPath填写上面的代码元素操作选择获取元素文本内容保存到变量商品价格列表3.3 采集商品销量用preceding-sibling/following-sibling参照物定位商品销量通常在销量这个文本后面用following-sibling定位。XPath写法//span[text()销量]/following-sibling::span指令配置用【获取相似元素列表(web)】指令定位方式选择XPath选择器XPath填写上面的代码元素操作选择获取元素文本内容保存到变量商品销量列表3.4 采集评价数用child::层级定位评价数在商品信息的某个子div里面用child::定位。XPath写法//div[classproduct-info]/div[classreview]指令配置用【获取相似元素列表(web)】指令定位方式选择XPath选择器XPath填写上面的代码元素操作选择获取元素文本内容保存到变量评价数列表3.5 数据整合用【ForEach列表循环】指令遍历商品标题列表同时取出对应位置的价格、销量、评价数写入Excel。具体操作流程用【获取相似元素列表(web)】指令分别获取商品标题列表、价格列表、销量列表、评价数列表用【ForEach列表循环】指令循环商品标题列表在循环体内用【获取列表项】指令按当前循环的下标取出对应位置的价格、销量、评价数用【写入Excel行】指令将标题、价格、销量、评价数写入Excel的一行四、总结XPath六种写法每种都有适用场景属性选择器适合稳定元素准确率最高contains模糊匹配适合只确定部分元素最常用preceding-sibling/following-sibling适合通过上下文定位灵活性强child::层级定位适合逐层精确提取下标控制要小心starts-with/ends-with适合属性值有规律的情况注意浏览器兼容性组合写法实战中最灵活可以应对各种复杂情况新手最重要的是多练。找个项目实战把六种写法都试一遍自然就掌握了。踩坑经验总结属性值写错一个字符就匹配不到用F12直接复制contains可能匹配到多个元素用下标限制child::的下标从1开始不是从0开始ends-with在Chrome中不支持用contains代替写好的XPath先在Chrome开发者工具中验证再填到影刀里更多案例在影刀RPA学习主页 home.linyan.cloud#影刀RPA #XPath #元素定位 #网页自动化 #新手入门作者林焱
阅读完成 · 觉得有帮助?
咨询建站