为何原正常运行的Jsoup解析代码无法获取目标价格数据?
Jsoup解析商品价格失效的原因及修复方案
问题背景
此前用Jsoup解析网站商品价格的代码曾正常运行数周,但现在无法获取目标£22,508.13数据,反而得到无关内容(如“Relative”)。原代码依赖固定位置截取字符串获取价格,核心逻辑如下:
val parseId : Elements = doc2.select("#PriceSection") val spanSelected : Elements = parseId.select("span") stringBuilder2.append(spanSelected) val spanToString = stringBuilder2.toString() for(char in spanToString){ list2.add(char) } val newList2 = list2.toString() val cutString2 = newList2.substring(75,105)
失效原因
- 硬编码截取位置的脆弱性:原代码通过
substring(75,105)固定截取范围,一旦网站HTML结构(新增元素、调整标签顺序)变动,截取范围就会偏离目标内容,导致获取到无关文本。 - 选择器过于宽泛:直接选择
#PriceSection下所有span元素,没有精准定位价格所在节点。页面中#PriceSection包含多个功能按钮(1H/1D/1W等)的span,当页面更新后,这些非目标span的数量或顺序改变,会打乱最终的字符串拼接结果。 - DOM结构或类名更新:网站可能调整了价格元素的父容器类名或DOM层级,原有的宽泛选择无法过滤出目标价格节点。
修复方案
根据提供的HTML结构,目标价格£22,508.13位于带有cds-display3-doujgnf类的div下的span中,可通过精准CSS选择器直接定位:
改进后的Kotlin代码
// 直接定位价格所在的span元素 val priceSpan = doc2.select("#PriceSection .cds-display3-doujgnf span").first() // 提取价格文本,增加空值判断避免异常 val priceText = priceSpan?.text() ?: "无法获取价格" println(priceText) // 输出 £22,508.13
备选方案(基于文本特征)
如果类名可能变动,也可结合文本特征筛选,匹配包含英镑符号£的span:
val priceSpans = doc2.select("#PriceSection span:contains(£)") // 通常价格是唯一包含£的元素,取第一个即可 val priceText = priceSpans.first()?.text() ?: "无法获取价格"
关键优化点
- 避免硬编码截取位置,改用语义化CSS选择器直接定位目标元素
- 增加空值判断,防止因元素不存在导致的空指针异常
- 优先使用稳定标识(如唯一类名、文本特征)作为选择器依据,降低对DOM结构变动的敏感度
内容的提问来源于stack exchange,提问作者KotlinRookie
相关产品推荐
相关产品推荐

