Selenium实战:5分钟抓取京东商品数据的完整教程

发布时间:2026/10/21 6:57:43
Selenium实战:5分钟抓取京东商品数据的完整教程 看到这个标题你可能觉得我在开玩笑都什么年代了还用Selenium去抓电商数据现在的技术圈随便一搜都是requests加逆向签名又快又省资源。但我不反驳因为我自己在大多数情况下也是这种组合。可Selenium这种浏览器自动化方案在临时性、快速验证、不想碰逆向的场景里依然是最稳的保底选项。京东商品数据抓取这个需求几乎是我被问得最多的爬虫问题之一竞品比价、市场调研、库存监控甚至有人单纯想看看某个关键词下大家都在卖什么价格。这篇文章我尽量把从环境配置到完整代码再到踩过的坑一次性讲清楚让你照着就能跑起来而不是只看个热闹。1. 抓京东商品数据为什么绕不开Selenium1.1 京东的页面不是请求一下就能拿到的如果你只用requests去请求京东搜索页拿到手的HTML里通常根本没有商品列表。京东的前端页面大量依赖JavaScript异步渲染你看到的商品标题、价格、店铺信息很多是页面加载后由脚本再发接口动态填充的。也就是说你拿到的是骨架肉都在后面的XHR请求里。有的朋友会说那就抓它的异步接口呗。对理论上可以但京东的接口签名逻辑一直在变你可能今天把参数逆向通了明天前端升级又失灵。对于只想要几个关键词搜索结果的普通用户来说这个学习成本太高了。Selenium的思路不同我直接驱动一个真浏览器让页面像普通用户一样加载完所有异步渲染的逻辑都由网站自己执行我只要等内容出现在DOM里再把它拿下来就行。所以Selenium解决的核心问题是把页面最终长什么样这件事交给网站自己搞定我只负责观察和提取。这在你只需要抓个一两百条数据做分析的时候比逆向接口靠谱得多。1.2 5分钟的前提条件先把期望管理做好标题说5分钟搞定我不骗你但得把丑话说在前面。如果你已经安装了Python、Chrome浏览器并且能把Selenium的浏览器驱动配好登录态也准备好了那从启动浏览器到跑出第一份CSV确实能控制在几分钟内。真正费时间的其实是第一次配置驱动、处理登录验证、摸清页面结构这三个环节。京东现在有比较强的反爬意识直接无头浏览器访问搜索页很容易被识别需要做一点浏览器指纹上的伪装搜索关键词如果比较热门还可能触发滑块验证码。这些我都放在后面的章节里处理但你要心里有数5分钟跑通指的是启动代码到拿到数据不是从零安装环境到彻底稳定。这篇文章的核心价值就是帮你把那些最容易被卡住的前置坑提前填平。2. 环境准备把地基打牢后面才不慌2.1 安装Selenium与浏览器选择环境上我默认你用的是Python 3.8以上版本。命令行里一条命令就能装好Selenium库pip install selenium浏览器这块我建议用Chrome因为它的驱动兼容生态最好遇到问题网上资料也最多。微软的Edge也可以因为新版Edge本质是Chromium内核驱动获取方式和Chrome几乎一样。Firefox也能用但某些伪装参数的写法要改没必要一开始就跟自己过不去。Selenium从4.6版本开始内置了Selenium Manager理论上它会根据你本机的Chrome版本自动下载对应驱动省去了手动下载的麻烦。但在某些网络环境里自动下载也可能失败到时候还是得回到手动方案。手动方案的逻辑很简单看浏览器版本号去驱动网站下载对应版本的驱动把可执行文件放到PATH路径下或者直接在初始化代码里用executable_path参数指定。版本号必须在主版本上对齐比如Chrome 126就尽量找126开头的驱动差的太远会被拒。2.2 我用到的Python依赖清单除了Selenium本身我还建议顺手装上下面几个库它们不是必选的但能让你省很多事pandas数据最终要存成Excel或做去重分析pandas处理起来最顺手。lxmlSelenium拿到的页面源码如果需要用XPath二次解析lxml效率高。retrying或tenacity做请求重试遇到超时或临时反爬的时候自动等几秒再试。这些库不影响主流程但建议一起装上pip install pandas lxml tenacity装完之后先写一个最简单的脚本验证环境是否正常打开浏览器访问一个空白页面打印当前URL。这一步能排除90%的驱动不匹配问题。环境这东西看起来琐碎但如果你连浏览器都启动不了后面代码再正确也跑不起来。3. 完整代码与关键拆解手把手跑起来3.1 初始化浏览器先做基础伪装京东的反爬虽然不像某些网站那么丧心病狂但Selenium的自动化特征在它面前很容易暴露。最典型的特征是navigator.webdriver这个属性会变成true网站脚本一判断就能把你识别成机器人。所以我们要在浏览器启动后第一时间通过Chrome DevTools协议注入一段脚本把这个属性改掉。另外两个可以顺手做的优化一是关掉图片加载商品搜索结果里图片占了很大带宽关掉之后页面加载速度明显提升反正我们也不抓图片二是把enable-automation开关去掉避免浏览器顶部出现正在受自动测试软件控制的提示条这个提示条本身就是一个明显的机器人信号。import time from selenium import webdriver from selenium.webdriver.chrome.options import Options from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC def init_driver(headlessFalse): options Options() # 关闭自动化控制提示条 options.add_experimental_option(excludeSwitches, [enable-automation]) options.add_experimental_option(useAutomationExtension, False) # 禁用图片加速页面加载 prefs {profile.managed_default_content_settings.images: 2} options.add_experimental_option(prefs, prefs) # 隐藏自动化特征 options.add_argument(--disable-blink-featuresAutomationControlled) if headless: options.add_argument(--headlessnew) # 指定窗口大小避免某些页面在无头模式下布局异常 options.add_argument(--window-size1920,1080) driver webdriver.Chrome(optionsoptions) # 覆盖 navigator.webdriver 属性 driver.execute_cdp_cmd(Page.addScriptToEvaluateOnNewDocument, { source: Object.defineProperty(navigator, webdriver, { get: () undefined }); }) return driver driver init_driver(headlessFalse)这段代码里最值得关注的是Page.addScriptToEvaluateOnNewDocument这个API。它在浏览器加载任何新页面之前提前执行脚本从而把webdriver属性覆盖掉。如果只在新页面加载之后再执行那就来不及了因为网站的检测脚本可能先跑完了。这个顺序细节很多人会忽略实测下来影响挺大的。3.2 登录态处理扫码和Cookie两条路京东搜索页不加登录态也能访问但很容易被重定向到登录页或者商品价格显示不全。更稳妥的做法是先登录一次拿到登录凭证后续请求都带着这个凭证。方案一是手动扫码登录。这个适合你本地临时跑一次代码里打个断点浏览器弹出登录二维码你拿手机扫完再让脚本继续往下走。好处是几乎不会触发异常风控坏处是需要人工介入没法全自动。方案二是使用Cookie。你先在正常浏览器里登录京东打开开发者工具的Application面板找到Cookie列表把pt_key和pt_token这两个字段的值复制出来。这两个是京东登录态的核心票据。然后我们在代码里把它们拼成一个Cookie字符串注入到Selenium的浏览器里这样就能模拟已登录状态。COOKIE_STR pt_keyxxx; pt_tokenyyy def inject_cookie(driver, cookie_str): # 先打开一个京东页面才能设置 Cookie driver.get(https://www.jd.com) driver.delete_all_cookies() for item in cookie_str.split(; ): key, value item.split(, 1) cookie { name: key, value: value, domain: .jd.com } driver.add_cookie(cookie) driver.refresh() cookies COOKIE_STR inject_cookie(driver, cookies)注意pt_key和pt_token这两个Cookie的有效期不短但也用不了一辈子。如果哪天脚本突然跳到登录页或者需要验证第一时间去原浏览器里看看Cookie是否过期重新复制一份就好。千万不要在代码里硬编码一个已经失效的Cookie然后怀疑自己的人生。3.3 搜索、解析与翻页核心主流程京东搜索页的URL参数比想象中简单keyword是关键词enc是编码。如果想指定排序方式还可以加psort参数比如psort3是按销量排序psort1是按综合排序。商品列表的DOM结构在正常情况下是这样的外层容器是id为J_goodsList的div里面是一个ul列表每个商品是li标签CSS类名是gl-item。商品标题在.p-name a里面价格在.p-price i里面店铺名在.p-shop a里面。但京东的页面结构并不是永远不变前端改版是常态。好在思路是通用的只要列表容器还是#J_goodsList定位逻辑基本不用推翻重写。下面我给出完整主流程import csv import random from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.common.by import By def parse_page(driver, writer, page_no): # 等待商品列表加载完成 WebDriverWait(driver, 20).until( EC.presence_of_element_located((By.CSS_SELECTOR, #J_goodsList li.gl-item)) ) items driver.find_elements(By.CSS_SELECTOR, #J_goodsList li.gl-item) for item in items: try: title_el item.find_element(By.CSS_SELECTOR, .p-name a) title title_el.text.strip().replace(\n, ) link title_el.get_attribute(href) except Exception: title, link , try: price item.find_element(By.CSS_SELECTOR, .p-price i).text.strip() except Exception: price try: shop item.find_element(By.CSS_SELECTOR, .p-shop a).text.strip() except Exception: shop writer.writerow([page_no, title, price, shop, link]) def scroll_to_bottom(driver): 模拟用户缓慢向下滚动触发懒加载 driver.execute_script(window.scrollTo(0, document.body.scrollHeight);) time.sleep(1.5) def main(): keyword 机械键盘 max_pages 3 driver init_driver(headlessFalse) inject_cookie(driver, COOKIE_STR) f open(fjd_{keyword}.csv, w, newline, encodingutf-8-sig) writer csv.writer(f) writer.writerow([页码, 标题, 价格, 店铺, 链接]) for page in range(1, max_pages 1): url fhttps://search.jd.com/Search?keyword{keyword}encutf-8page{page} driver.get(url) time.sleep(random.uniform(2, 4)) scroll_to_bottom(driver) parse_page(driver, writer, page) print(f第{page}页完成已抓取商品) f.close() driver.quit() if __name__ __main__: main()这里有两个细节值得展开。第一为什么翻页用URL里的page参数而不是点击页面上的下一页按钮因为直接用URL跳转更稳定点击按钮有时候会因为页面异步加载缓慢而失效。第二为什么每页之间加随机等待不是为了装模作样而是为了降低被风控系统识别的概率。脚本行为如果太规律比如每3秒固定翻一页从服务端日志看就是典型的机器人特征。3.4 数据落盘CSV编码和去重CSV看起来简单但坑不少。我建议写入时指定encodingutf-8-sig因为如果用纯utf-8编码Excel打开中文会乱码。utf-8-sig会在文件开头加一个BOM标记Excel能正确识别。如果你打算用pandas分析那utf-8-sig同样没问题。去重方面京东搜索页每个关键词下可能会有少量重复商品特别是翻页抓取的时候偶尔会遇到猜你喜欢推荐位插入的商品列表。可以给CSV加一个简单去重逻辑把商品链接当作唯一键写之前判断一下这个链接是否已经在已抓取的集合里。seen set() with open(jd_goods.csv, w, newline, encodingutf-8-sig) as f: writer csv.writer(f) writer.writerow([页码, 标题, 价格, 店铺, 链接]) for row in fetch_rows(): url row[4] if url in seen: continue seen.add(url) writer.writerow(row)如果你要抓的数据量不大内存里放一个set完全没压力。如果跑到几万条那就可以考虑改成SQLite存储了。这篇文章以Demo为主CSV就够用。4. 实操中常见的几个坑我替你踩过的4.1 元素定位失败页面还在加载你就急着拿数据这是Selenium新手最常遇到的问题。find_elements是即时操作如果页面还没加载出商品列表返回的就是空列表你以为抓到了零条数据其实只是太快了。解决方案就是显式等待。我在主流程里用了WebDriverWait(driver, 20).until(...)意思是最多等20秒只要商品列表的li元素出现了就继续往下走。如果20秒还没出现就抛出异常。这里的等待时间和网络环境有关如果你网速慢或访问频繁被限速可以调到30秒甚至更长。定位元素这一块我的建议是优先用CSS选择器少用XPath里那种冗长的绝对路径。CSS选择器简洁、解析快而且京东页面的结构调整时相对结构比绝对路径稳定得多。只要记住容器固定、item固定、关键属性固定这三个原则页面改版后通常只需要微调选择器就能继续用。4.2 验证码和风控拦截别硬刚想办法绕京东的搜索页偶尔会弹出滑块验证码。实测经验是搜索关键词越热门、翻页越多、请求频率越高越容易触发。一旦弹了滑块Selenium硬拖动也能拖但成功率不稳定而且会让风控系统对你更加关注。我的做法是三层规避。第一控制抓取规模单个关键词只抓前几页拿到有代表性的数据就够了别贪心。第二每次抓取之前随机等待3到5秒模拟人的浏览节奏。第三保留一个手动兜底如果验证码出现代码暂停并提示你人工处理你手动把滑块拖过去然后继续跑。这个兜底逻辑很简单if 验证 in driver.page_source: input(出现验证码请手动处理处理完按回车继续...)有些朋友会纠结如何完全自动过滑块从我的经验看这种投入产出比不高。你是在抓公开数据做分析不是在攻击某个高价值目标没必要把自己锻炼成验证码对抗专家。人工点一下滑块成本其实很低。4.3 价格、店铺抓取为空异步加载和结构差异价格为空的情况特别常见原因是京东的价格是在商品列表加载后再通过异步接口单独填充的。li元素已经渲染出来了但价格位置还是空的。所以你不能只等li出现还要等价格文本不是空字符串。更好的做法是针对价格字段再做一次显式等待或者干脆加入一个简单的重试逻辑如果.p-price i取出来为空等2秒再取一次。店铺为空则是另一个原因搜索结果里部分商品是京东自营的店铺区域结构和其他第三方店铺不一样选择器抓不到。这种情况就判断一下DOM里有没有.p-shop没有就记为自营。另外要提醒一点京东展示给普通用户的价格通常是经过促销计算后的到手价或者PLUS会员价和真实结算时你可能享受的价格并不完全一致。所以价格字段适合做趋势分析别把它当作精确报价来用。5. 合规意识与工程化改造建议5.1 爬虫的技术边界京东在其用户协议里对爬虫采集行为有明确限制所以这类脚本只适合个人学习、接口研究或者小规模数据分析不宜用于商业牟利更不要高频、大规模地去采集。技术上你当然可以控制请求频率但合规与道德的底线得自己掌握。我的建议很简单每次抓取量控制在一个合理范围采集频率远低于正常用户浏览频率抓到的数据不要二次公开传播。这一点很多技术教程不会提但我觉得有必要说透。我有一次帮一个朋友做商品价格调研只是跑了不到100条数据依然在一个小时之后触发了风控拦截整个IP段被暂时限制。不要觉得我就抓几十条没事电商平台的反爬监控是全天候的配合随机延迟能降低风险但无法保证万无一失。5.2 从跑通Demo到可用的工具如果这篇代码你跑通了恭喜你你已经掌握了一个非常实用的技能。但如果想让这个脚本长期用下去我强烈建议你做几个方向性的改造。第一把关键词和页数配置到外部文件里。一个需求列表用JSON或者YAML管理脚本启动时读取配置而不是改代码里的变量。第二加上异常通知。抓取过程中经常会出现各种未知异常抛一个try...except把异常信息通过企业微信机器人或者钉钉机器人发到手机上这样脚本挂了你第一时间知道。第三数据入库。量小用CSV量大了换SQLite再大了上MySQL或PostgreSQL。入库之后你可以直接用SQL做聚合分析比反复读CSV高效得多。{ keywords: [机械键盘, 无线鼠标, 显示器支架], pages: 2, sort: 3, delay_range: [3, 6] }配置化之后你换关键词不用改代码维护成本会明显下降。这个脚本我已经在几个模拟项目中翻来覆去用过稳定性完全可以接受。最后再分享一个我自己常用的技巧我平时抓完数据以后不会直接拿CSV去Excel里看而是用pandas做一次简单清洗把价格列转成数值型去掉明显异常的空值再做一次按价格区间的分组统计。这一步能让你在30秒内看到这个关键词下不同价格档位的商品分布比肉眼一行行扫Excel高效很多。import pandas as pd df pd.read_csv(jd_机械键盘.csv) df[价格] pd.to_numeric(df[价格], errorscoerce) print(df[价格].describe()) print(df[价格].groupby(pd.cut(df[价格], bins[0, 100, 300, 500, 1000, 5000])).size())按理说爬虫教程到代码部分就可以结束了但我觉得多写两句工具链终归没坏处。毕竟抓数据只是第一步把数据变成能用的信息才是你做这件事的最终目标。这套流程看起来简单真能从头到尾跑通的人已经比大部分只会对着教程敲代码的读者强出一截了。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询