Selenium爬虫实战:5分钟搞定京东商品数据抓取(附完整代码)

张开发
2026/4/19 18:39:28 15 分钟阅读

分享文章

Selenium爬虫实战:5分钟搞定京东商品数据抓取(附完整代码)
Selenium电商数据抓取实战京东商品信息高效获取指南电商数据抓取已成为市场分析、价格监控和竞品研究的重要技术手段。面对动态加载、反爬机制日益完善的电商平台传统爬虫技术往往力不从心。本文将深入解析如何利用Selenium突破京东等电商平台的技术壁垒实现商品数据的高效抓取。1. 环境配置与基础准备工欲善其事必先利其器。在开始电商数据抓取前需要搭建稳定可靠的开发环境。以下是关键组件的安装与配置步骤Python环境配置# 创建虚拟环境推荐 python -m venv jd_crawler source jd_crawler/bin/activate # Linux/Mac jd_crawler\Scripts\activate # Windows # 安装核心依赖 pip install selenium webdriver-manager pandas浏览器驱动管理现代Selenium项目推荐使用webdriver-manager自动管理浏览器驱动避免手动下载和路径配置的麻烦from selenium import webdriver from webdriver_manager.chrome import ChromeDriverManager # 自动下载并配置Chrome驱动 driver webdriver.Chrome(ChromeDriverManager().install())常见问题排查表问题现象可能原因解决方案SSL证书错误系统时间不正确/安全软件拦截同步系统时间/临时关闭安全软件页面加载超时网络延迟/反爬机制增加隐式等待时间/更换IP地址元素定位失败页面结构变化/动态加载延迟更新XPath/添加显式等待提示京东等电商平台对高频访问敏感建议在开发阶段设置合理的操作间隔如3-5秒避免触发反爬机制。2. 京东页面结构与反爬策略解析深入理解目标网站的技术架构是设计高效爬虫的前提。京东作为国内头部电商平台其页面呈现具有典型动态特征动态加载机制分析商品列表采用异步加载AJAX价格信息可能通过独立接口获取图片资源采用懒加载技术分页逻辑包含时间戳参数关键XPath定位参考# 商品卡片容器 products driver.find_elements_by_xpath(//li[contains(class,gl-item)]) # 商品名称 name product.find_element_by_xpath(.//div[classp-name]/a/em).text # 价格元素注意动态class price product.find_element_by_xpath(.//div[contains(class,p-price)]).text # 店铺信息 shop product.find_element_by_xpath(.//a[classcurr-shop]).get_attribute(title)反爬应对策略请求频率控制使用time.sleep(random.uniform(1,3))模拟人工操作头部信息完善设置合理的User-Agent和Refereroptions webdriver.ChromeOptions() options.add_argument(user-agentMozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36)行为模式模拟滚动页面触发懒加载driver.execute_script(window.scrollTo(0, document.body.scrollHeight/3)) time.sleep(1) driver.execute_script(window.scrollTo(0, document.body.scrollHeight*2/3))3. 完整爬取流程实现下面我们构建一个完整的京东商品数据抓取方案包含搜索、翻页、数据提取和存储全流程。核心功能实现import csv import time import random from selenium import webdriver from selenium.webdriver.common.keys import Keys from webdriver_manager.chrome import ChromeDriverManager class JDCrawler: def __init__(self): self.driver webdriver.Chrome(ChromeDriverManager().install()) self.driver.maximize_window() def search_products(self, keyword, pages3): 执行商品搜索并返回结果 self.driver.get(https://www.jd.com) search_box self.driver.find_element_by_id(key) search_box.send_keys(keyword Keys.ENTER) time.sleep(3) # 等待页面跳转 results [] for page in range(pages): print(f正在抓取第 {page1} 页数据...) self._scroll_page() # 滚动加载完整页面 results.extend(self._parse_products()) if page pages - 1: self._next_page() time.sleep(random.uniform(2,4)) # 随机等待 return results def _scroll_page(self): 模拟页面滚动触发懒加载 for i in range(3): self.driver.execute_script( fwindow.scrollTo(0, document.body.scrollHeight*{i/2})) time.sleep(0.5) def _parse_products(self): 解析当前页商品信息 products [] items self.driver.find_elements_by_xpath(//li[contains(class,gl-item)]) for item in items: try: product { name: item.find_element_by_xpath(.//div[classp-name]/a/em).text, price: item.find_element_by_xpath(.//div[contains(class,p-price)]).text, shop: item.find_element_by_xpath(.//a[classcurr-shop]).get_attribute(title), comments: item.find_element_by_xpath(.//div[contains(class,p-commit)]).text } products.append(product) except Exception as e: print(f解析商品时出错: {str(e)}) continue return products def _next_page(self): 跳转到下一页 try: self.driver.find_element_by_class_name(pn-next).click() except: print(翻页失败尝试备用方案...) self.driver.execute_script(arguments[0].click();, self.driver.find_element_by_class_name(pn-next)) def save_to_csv(self, data, filename): 保存数据到CSV文件 with open(filename, w, newline, encodingutf-8-sig) as f: writer csv.DictWriter(f, fieldnamesdata[0].keys()) writer.writeheader() writer.writerows(data) def close(self): self.driver.quit() # 使用示例 if __name__ __main__: crawler JDCrawler() try: data crawler.search_products(Python编程, pages2) crawler.save_to_csv(data, jd_products.csv) print(f成功抓取 {len(data)} 条商品数据) finally: crawler.close()数据存储优化方案增量存储记录已抓取商品ID避免重复异常处理添加网络中断重试机制数据去重基于商品ID建立唯一索引分布式扩展结合Scrapy-Redis实现集群抓取4. 高级技巧与性能优化当基础爬虫功能实现后我们需要关注系统的稳定性和效率提升。智能等待策略from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC # 显式等待元素出现 element WebDriverWait(driver, 10).until( EC.presence_of_element_located((By.ID, search-result)) ) # 常用等待条件 visibility_of_element_located - 元素可见 element_to_be_clickable - 元素可点击 text_to_be_present_in_element - 元素包含特定文本 代理IP集成方案PROXY 123.123.123.123:8888 options webdriver.ChromeOptions() options.add_argument(f--proxy-serverhttp://{PROXY}) driver webdriver.Chrome(optionsoptions)1. 题目93. 复原 IP 地址难度中等830有效 IP 地址正好由四个整数每个整数位于0到255之间组成且不能含有前导0整数之间用.分隔。例如0.1.2.201和192.168.1.1是有效IP 地址但是0.011.255.245、192.168.1.312和192.1681.1是无效IP 地址。给定一个只包含数字的字符串s用以表示一个 IP 地址返回所有可能的有效 IP 地址这些地址可以通过在s中插入.来形成。你不能重新排序或删除s中的任何数字。你可以按任何顺序返回答案。示例 1输入s 25525511135 输出[255.255.11.135,255.255.111.35]示例 2输入s 0000 输出[0.0.0.0]示例 3输入s 101023 输出[1.0.10.23,1.0.102.3,10.1.0.23,10.10.2.3,101.0.2.3]提示1 s.length 20s仅由数字组成2. 题解3. codeclass Solution { public: vectorstring ans; bool isValid(const string s, int start, int end) { if (start end) return false; if (s[start] 0 start ! end) { return false; } int num 0; for (int i start; i end; i) { if (s[i] 9 || s[i] 0) { return false; } num num * 10 (s[i] - 0); if (num 255) { return false; } } return true; } void backtracking(string s, int startIdx, int pointNum) { if (pointNum 3) { if (isValid(s, startIdx, s.size() - 1)) { ans.push_back(s); } return; } for (int i startIdx; i s.size(); i) { if (isValid(s, startIdx, i)) { s.insert(s.begin() i 1, .); pointNum; backtracking(s, i 2, pointNum); pointNum--; s.erase(s.begin() i 1); } else { break; } } return; } vectorstring restoreIpAddresses(string s) { backtracking(s, 0, 0); return ans; } };4. 心得回溯法注意判断是否有效以及插入和删除的位置。

更多文章