使用Jsoup爬取商品名称与价格后如何配对存入MySQL数据库
问题核心原因
你现有代码的核心问题有两个:
- 分别遍历商品名、价格集合,会重复覆盖PreparedStatement的第1、2个参数,最终执行时只会插入最后一个商品名和最后一个价格的组合,完全没有实现一一配对的效果
- 直接全局提取两个类名的元素集合,没有和商品维度绑定,一旦页面存在多余的
product-name或price标签(如广告位、页脚的同类标签),就会出现两个集合长度不一致、配对错位的问题
修复方案
优先推荐第一种方案,稳定性更高:
方案1:按商品维度遍历
先找到每个商品的外层父容器,再从单个父容器内提取对应商品的名称和价格,从根源避免配对错位:
Document document = Jsoup.connect("http://www.winwin.rs/").timeout(6000).get(); // 需替换为实际页面中包裹单个商品卡片的父容器class,可通过浏览器F12查看元素获取 Elements productItems = document.getElementsByClass("product-item"); String query = "insert into product (name, price) values (?, ?)"; Connection conn = mysqlconnect.ConnectDb(); PreparedStatement preparedStmt = conn.prepareStatement(query); for (Element product : productItems) { // 从当前商品容器内单独提取名称、价格,不会和其他商品混淆 String name = product.getElementsByClass("product-name").get(0).text(); String price = product.getElementsByClass("price").get(0).text(); preparedStmt.setString(1, name); preparedStmt.setString(2, price); // 将当前配对数据加入批量执行队列 preparedStmt.addBatch(); } // 批量执行所有插入操作 preparedStmt.executeBatch(); conn.close();
方案2:索引配对
仅适合确认页面中product-name和price元素数量完全一一对应的场景:
Document document = Jsoup.connect("http://www.winwin.rs/").timeout(6000).get(); Elements names = document.getElementsByClass("product-name"); Elements prices = document.getElementsByClass("price"); // 先校验两个集合长度是否一致,避免下标越界或配对错位 if (names.size() != prices.size()) { throw new RuntimeException("商品名与价格数量不匹配,无法完成配对"); } String query = "insert into product (name, price) values (?, ?)"; Connection conn = mysqlconnect.ConnectDb(); PreparedStatement preparedStmt = conn.prepareStatement(query); for (int i = 0; i < names.size(); i++) { preparedStmt.setString(1, names.get(i).text()); preparedStmt.setString(2, prices.get(i).text()); preparedStmt.addBatch(); } preparedStmt.executeBatch(); conn.close();
优化建议
- 插入操作建议增加事务控制,避免插入中途报错导致数据不一致
- 提取元素时增加判空逻辑,避免单个商品缺少名称/价格时抛出数组越界异常
- 请求时增加模拟浏览器的请求头,降低被网站反爬拦截的概率
内容的提问来源于stack exchange,提问作者lukavi026026
相关产品推荐
相关产品推荐

