ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

JAVA爬取亚马逊的商品信息

JAVA爬取亚马逊的商品信息 一、项目概述本文介绍一个基于 Java 的亚马逊商品信息爬虫工具。用户只需输入商品名称程序即可自动爬取亚马逊搜索结果中所有相关商品的信息包括商品名称和价格并解决爬取过程中常见的反爬虫限制问题。二、核心功能与效果展示1. 主要功能商品搜索爬取输入商品名称自动爬取亚马逊搜索结果中的所有相关商品信息提取准确提取商品名称和价格信息去重处理自动识别并过滤重复商品反爬虫绕过采用多种策略应对亚马逊的反爬虫机制2. 效果展示商品搜索页面爬取结果页面已去重数据准确性验证第31行商品三、技术实现思路1. 核心算法流程初始化搜索根据输入的商品名构造亚马逊搜索URL页面类型判断区分列表页和商品详情页列表页处理提取所有商品页URL和下一页URL加入爬取队列商品页处理提取商品名称和价格保存到文件队列循环持续处理队列中的URL直到队列为空2. 技术特点纯Java实现仅使用Java标准库无需第三方依赖正则表达式提取通过正则匹配从混乱的HTML中提取关键信息广度优先搜索使用队列实现URL的广度优先遍历四、关键技术问题与解决方案1. 反爬虫限制503错误问题现象亚马逊会识别爬虫行为频繁访问会返回503错误导致只能爬取少量页面。解决方案User-Agent随机化预置15个不同浏览器的User-Agent每次请求随机选择请求降速适当延长两次请求之间的时间间隔URL去重避免重复请求相同页面请求头完善设置完整的HTTP请求头模拟真实浏览器2. 页面结构复杂问题描述亚马逊页面HTML结构复杂信息提取困难。解决方案通过仔细分析页面源码找到关键信息的规律使用正则表达式精准提取商品名称匹配meta namedescription content商品名称,模式商品价格匹配classa-size-medium a-color-price价格/span模式商品URL匹配hrefhttp://www.amazon.cn/.../dp/商品编号模式3. 商品重复问题问题描述同一商品在搜索结果中可能有3-4个不同URL名称页、图文页、评论页等。解决方案通过商品编号dp后面的字符串进行去重。例如http://www.amazon.cn/手机-通讯/dp/B00OB5T26S...... 商品编号B00OB5T26S五、代码实现详解1. 核心类结构import java.io.*; import java.net.*; import java.util.*; import java.util.regex.*; public class AmazonCrawler { // 用于存储上一个商品编号用于去重 public static String lastProductId |; // 匹配商品URL的正则表达式 public static Pattern p_goods Pattern.compile(href(http://www\.amazon\.cn/.?/dp/(.?))); // 存放待爬取的URL队列 public static Queuelt;Stringgt; urlQueue new LinkedListlt;Stringgt;(); // 输出文件 public static File outputFile; public static BufferedWriter writer; // 15个User-Agent随机使用降低被识别为爬虫的概率 public static String[] userAgents { Mozilla/5.0 (Windows NT 6.1; rv:2.0.1) Gecko/20100101 Firefox/4.0.1, Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.16 Safari/537.36, Mozilla/5.0 (Windows NT 6.1; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1, Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.63 Safari/537.36 OPR/18.0.1284.68, Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0), Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0), Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Trident/6.0), Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.63 Safari/537.36, Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:2.0.1) Gecko/20100101 Firefox/4.0.1, Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1, Opera/9.80 (Macintosh; Intel Mac OS X 10.9.1) Presto/2.12.388 Version/12.16, Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.63 Safari/537.36 OPR/18.0.1284.68, Mozilla/5.0 (iPad; CPU OS 7_0 like Mac OS X) AppleWebKit/537.51.1 (KHTML, like Gecko) CriOS/30.0.1599.12 Mobile/11A465 Safari/8536.25, Mozilla/5.0 (iPad; CPU OS 8_0 like Mac OS X) AppleWebKit/600.1.3 (KHTML, like Gecko) Version/8.0 Mobile/12A4345d Safari/600.1.4, Mozilla/5.0 (iPad; CPU OS 7_0_2 like Mac OS X) AppleWebKit/537.51.1 (KHTML, like Gecko) Version/7.0 Mobile/11A501 Safari/9537.53 }; // 核心爬取方法 public static void action(String target) throws IOException, InterruptedException { // 方法实现见下文 } // 主方法 public static void main(String[] args) throws IOException, InterruptedException { // 程序入口见下文 } }2. action 方法完整实现/** * 核心爬取方法 * param target 商品搜索关键词 */ public static void action(String target) throws IOException, InterruptedException { // 1. 构造搜索URL String searchUrl http://www.amazon.cn/s/refnb_sb_noss?__mk_zh_CN%E4%BA%9A%E9%A9%AC%E9%80%8A%E7%BD%91%E7%AB%99field-keywords URLEncoder.encode(target, UTF-8); // 2. 初始化队列和文件 urlQueue.clear(); urlQueue.add(searchUrl); outputFile new File(amazon_products_ System.currentTimeMillis() .txt); writer new BufferedWriter(new FileWriter(outputFile)); writer.write(商品名称\t价格\t商品URL\n); writer.write(----------------------------------------\n); // 3. 已访问URL集合避免重复爬取 Setlt;Stringgt; visitedUrls new HashSetlt;gt;(); // 4. 主循环处理队列中的URL while (!urlQueue.isEmpty()) { String currentUrl urlQueue.poll(); // 检查URL是否已访问过避免重复爬取 if (visitedUrls.contains(currentUrl)) { continue; } visitedUrls.add(currentUrl); // 5. 发送HTTP请求 URL url new URL(currentUrl); HttpURLConnection conn (HttpURLConnection) url.openConnection(); conn.setRequestMethod(GET); conn.setConnectTimeout(10000); conn.setReadTimeout(10000); // 随机选择User-Agent模拟不同浏览器 Random rand new Random(); String userAgent userAgents[Math.abs(rand.nextInt()) % userAgents.length]; conn.setRequestProperty(User-Agent, userAgent); // 设置其他请求头模拟浏览器 conn.setRequestProperty(Accept, text/html,application/xhtmlxml,application/xml;q0.9,/;q0.8); conn.setRequestProperty(Accept-Language, zh-CN,zh;q0.9,en;q0.8); conn.setRequestProperty(Connection, keep-alive); // 6. 获取响应内容 int responseCode conn.getResponseCode(); // 处理503反爬虫错误等待后重试 if (responseCode 503) { System.out.println(遇到503错误等待5秒后重试...); Thread.sleep(5000); urlQueue.add(currentUrl); // 重新加入队列 continue; } if (responseCode ! 200) { System.out.println(请求失败状态码: responseCode - currentUrl); continue; } // 读取页面内容 BufferedReader reader new BufferedReader(new InputStreamReader(conn.getInputStream(), UTF-8)); StringBuilder contentBuilder new StringBuilder(); String line; while ((line reader.readLine()) ! null) { contentBuilder.append(line).append(\n); } reader.close(); conn.disconnect(); String content contentBuilder.toString(); // 7. 判断页面类型并处理 if (currentUrl.contains(/dp/)) { // 商品详情页提取商品信息 processProductPage(content, currentUrl); } else { // 搜索结果页提取商品链接和下一页链接 processSearchPage(content); } // 8. 请求降速避免触发反爬虫 Thread.sleep(2000 rand.nextInt(3000)); System.out.println(已处理: currentUrl); } // 9. 关闭文件 writer.close(); System.out.println(爬取完成结果已保存到: outputFile.getAbsolutePath()); } /** 处理商品详情页提取商品信息 / private static void processProductPage(String content, String url) throws IOException { // 提取商品名称 Pattern pName Pattern.compile(meta namedescription content([^]?),); Matcher mName pName.matcher(content); // 提取商品价格 Pattern pPrice Pattern.compile(classa-size-medium a-color-price([^]?)/span); Matcher mPrice pPrice.matcher(content); String productName 未找到; String price 未找到; if (mName.find()) { productName mName.group(1).trim(); } if (mPrice.find()) { price mPrice.group(1).trim(); } // 写入文件 writer.write(productName \t price \t url \n); writer.flush(); System.out.println(提取商品: productName | 价格: price); } /* 处理搜索结果页提取商品链接 */ private static void processSearchPage(String content) { // 提取商品链接 Matcher goodsMatcher p_goods.matcher(content); while (goodsMatcher.find()) { String productUrl goodsMatcher.group(1); String productId goodsMatcher.group(2); // 去重逻辑如果商品编号与上一个不同则加入队列 if (!productId.equals(lastProductId)) { urlQueue.add(productUrl); lastProductId productId; System.out.println(发现新商品: productId); } } // 提取下一页链接简化处理实际可能需要更复杂的逻辑 Pattern pNextPage Pattern.compile(href([^]?page2[^]?)); Matcher mNextPage pNextPage.matcher(content); if (mNextPage.find()) { String nextPageUrl http://www.amazon.cn mNextPage.group(1); urlQueue.add(nextPageUrl); } }3. main 方法完整实现/** * 程序主入口 */ public static void main(String[] args) throws IOException, InterruptedException { System.out.println( 亚马逊商品爬虫启动 ); System.out.println(作者: CSDN博客); System.out.println(功能: 自动爬取亚马逊商品信息); System.out.println(\n); // 1. 获取用户输入 BufferedReader consoleReader new BufferedReader(new InputStreamReader(System.in)); System.out.print(请输入要搜索的商品名称: ); String keyword consoleReader.readLine().trim(); if (keyword.isEmpty()) { System.out.println(错误: 搜索关键词不能为空); System.out.println(使用示例: java AmazonCrawler); System.out.println(然后输入: iPhone 手机); return; } System.out.println(\n开始爬取商品: keyword); System.out.println(正在构造搜索URL...); // 2. 执行爬取 long startTime System.currentTimeMillis(); try { action(keyword); } catch (Exception e) { System.err.println(爬取过程中发生错误: e.getMessage()); e.printStackTrace(); // 确保文件被关闭 if (writer ! null) { try { writer.close(); } catch (IOException ex) { // 忽略关闭异常 } } } // 3. 统计信息 long endTime System.currentTimeMillis(); long duration (endTime - startTime) / 1000; System.out.println(\n 爬取统计 ); System.out.println(搜索关键词: keyword); System.out.println(爬取时长: duration 秒); if (outputFile ! null amp;amp; outputFile.exists()) { // 统计行数 BufferedReader fileReader new BufferedReader(new FileReader(outputFile)); int lineCount 0; while (fileReader.readLine() ! null) { lineCount; } fileReader.close(); int productCount Math.max(0, lineCount - 2); // 减去标题行和分隔行 System.out.println(爬取商品数量: productCount 个); System.out.println(结果文件: outputFile.getAbsolutePath()); // 显示前几条结果 if (productCount amp;gt; 0) { System.out.println(\n前5条商品信息:); fileReader new BufferedReader(new FileReader(outputFile)); String displayLine; int displayCount 0; while ((displayLine fileReader.readLine()) ! null amp;amp;amp;amp; displayCount amp;lt; 7) { // 包括标题 System.out.println(displayLine); displayCount; } fileReader.close(); } } System.out.println(\n 爬取完成 ); System.out.println(按回车键退出...); consoleReader.readLine(); }4. 关键代码解析搜索URL构造String searchUrl http://www.amazon.cn/s/refnb_sb_noss?__mk_zh_CN%E4%BA%9A%E9%A9%AC%E9%80%8A%E7%BD%91%E7%AB%99field-keywords URLEncoder.encode(target, UTF-8);User-Agent随机选择Random rand new Random(); String userAgent userAgents[Math.abs(rand.nextInt()) % userAgents.length]; conn.setRequestProperty(User-Agent, userAgent);商品信息提取// 提取商品名称 Pattern pName Pattern.compile(meta name\description\ content\([^\]?),); Matcher mName pName.matcher(content); // 提取商品价格 Pattern pPrice Pattern.compile(classa-size-medium a-color-price([^]?)/span); Matcher mPrice pPrice.matcher(content);商品去重逻辑// 提取商品编号 Matcher goodsMatcher p_goods.matcher(content); while (goodsMatcher.find()) { String productUrl goodsMatcher.group(1); String productId goodsMatcher.group(2); // 去重如果不等于上一个商品编号才加入队列 if (!productId.equals(lastProductId)) { urlQueue.add(productUrl); lastProductId productId; } }反爬虫处理// 503错误重试机制 if (responseCode 503) { System.out.println(遇到503错误等待5秒后重试...); Thread.sleep(5000); urlQueue.add(currentUrl); // 重新加入队列 continue; } // 请求降速 Thread.sleep(2000 rand.nextInt(3000));文件写入// 初始化文件 outputFile new File(amazon_products_ System.currentTimeMillis() .txt); writer new BufferedWriter(new FileWriter(outputFile)); writer.write(商品名称\t价格\t商品URL\n); writer.write(----------------------------------------\n); // 写入商品信息 writer.write(productName \t price \t url \n); writer.flush();六、优化建议与总结1. 当前实现特点搜索范围目前只爬取搜索结果第一页因为第一页商品最相关后续页面重复或不相关商品较多适用场景搜索具体商品时效果最佳搜索品牌时可能需要爬取多页最终爬取效果2. 可优化方向多线程爬取提高爬取效率更智能的去重除了商品编号还可考虑商品名称相似度异常处理增强增加重试机制和更完善的错误处理数据存储优化考虑使用数据库而非文本文件存储代理IP支持应对更严格的反爬虫限制3. 总结本项目展示了一个基础的亚马逊商品爬虫实现重点解决了反爬虫限制和页面信息提取两个核心问题。虽然实现相对简单但包含了爬虫开发的关键技术点适合作为学习Java网络爬虫的入门案例。对于实际生产环境建议在此基础上增加多线程、代理池、分布式等高级特性。
返回列表