尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

Python与Selenium实战:电商登录下单自动化完整指南

发布时间:2026/9/23 17:21:51

资讯中心
01
ARTICLE

Python与Selenium实战:电商登录下单自动化完整指南

Python与Selenium实战:电商登录下单自动化完整指南
1. 项目整体设计与技术选型1.1 这个项目到底能做什么直接说结论你可以用 Python Selenium 写一套脚本让它代替你打开浏览器输入账号密码登录某个网站然后自动完成搜索商品、选择规格、加入购物车、提交订单这一整套操作。手不用碰键盘鼠标脚本自己就把流程跑完了。我做这个项目的起因很实际自己在维护一个小电商系统的测试环境每次回归都要手动走一遍下单流程点来点去至少五六分钟一天跑好几轮手指头都麻了。后来就用 Selenium 写了这套自动化流程从登录到下单全链路自动跑配合定时任务早上到公司数据已经躺在报表里了。这个项目适合谁看三类人一是刚学完 Python 基础、想找个综合练手项目的同学二是做自动化测试的工程师想把登录下单这类高频重复场景沉淀成脚本三是有个人效率提升需求的人比如管理自己的店铺后台、定期检查商品库存、自动处理某些订阅流程。核心难度不在 Python 本身而在对浏览器自动化机制的理解以及对各种异常页面的处理能力。1.2 为什么选 Selenium而不是 requests 或 Playwright做这类模拟登录和下单脚本通常有三条技术路线我三条都用过说下真实感受。第一条是用 requests 直接模拟 HTTP 请求。它的优势是速度快、资源占用低但问题也很明显现在主流网站的前端交互越来越复杂登录接口往往有加密参数下单流程会有动态 token 校验你纯靠分析网络请求去逆向这些参数工作量非常大而且网站前端一改版逆向代码立刻作废。除非你是爬虫逆向老手否则不建议从这条路入门。第二条是 Playwright 或 Pyppeteer。Playwright 确实是后起之秀API 设计更现代自动等待机制更智能还能录制脚本。但考虑到生态成熟度和问题排查时的资料丰富程度Selenium 依然是目前社区积累最深、遇到问题最容易搜到解决方案的方案。而且 Selenium 4 之后支持了相对定位器、全新的等待 API用起来体验已经大幅改善。第三条就是 Selenium这也是本文主讲的方案。它本质上是模拟真实浏览器操作你在浏览器里能做的操作它基本都能做点击、输入、滚动、拖拽、切换标签页、处理弹窗。对登录和下单这种强交互场景来说Selenium 是最稳的。打个比方requests 是对着电话说密码你猜不到对方转接到哪里Selenium 是亲自走到柜台前办业务虽然慢一点但是每一步都看得见、查得到、改得动。1.3 环境准备Python、Selenium、浏览器驱动环境这块坑不少我按实操来列清单。首先安装 Python建议 3.8 以上版本太老的版本对 Selenium 4 支持不好。用 pip 安装依赖pip install seleniumSelenium 只是操作浏览器的库真正干活的是浏览器本身和对应的驱动。Chrome 用 chromedriverFirefox 用 geckodriverEdge 用 edgedriver。这里有个关键点驱动版本必须和浏览器版本严格对应差一个版本都可能启动报错。有人可能觉得 Selenium 4.6 版本之后引入了 Selenium Manager可以自动下载驱动不用手动管版本。确实如此但实际体验下来在国内网络环境下驱动自动下载经常失败而且下载慢吞吞的。我的建议是自己手动下载驱动放进系统 PATH 路径或者直接在代码里指定驱动位置from selenium import webdriver from selenium.webdriver.chrome.service import Service service Service(/path/to/chromedriver) driver webdriver.Chrome(serviceservice)初始化浏览器时建议做几个基础配置能让后面的操作顺畅很多from selenium.webdriver.chrome.options import Options options Options() # 防止页面加载过慢导致超时 options.page_load_strategy eager # 禁用自动化控制提示有些网站会检测这个特征 options.add_argument(--disable-blink-featuresAutomationControlled) # 窗口最大化避免某些元素因视口问题不可点击 driver.maximize_window()page_load_strategy 这个参数很有意思默认是 normal 表示等所有资源加载完改成 eager 表示只等 DOM 就绪就返回对下单这种操作来说体验提升非常明显。如果不改碰到图片特别多的商品页光是等待资源加载就可能卡住十几秒。2. 登录模块把账号密码这件小事写稳2.1 登录流程先拆解清楚自动登录听起来简单实际上拆开看是这么几步打开登录页、等待页面加载、定位账号输入框、定位密码输入框、输入内容、处理验证码、点击登录按钮、校验登录结果。每一步都可能有意外比如网络慢导致元素还没渲染出来、验证码挡住按钮、点击登录后页面跳转但无任何提示。我习惯用 Selenium 的显式等待来处理元素未加载的问题。举个例子from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.common.by import By # 打开登录页 driver.get(https://example.com/login) # 等待账号输入框可见最多等10秒 wait WebDriverWait(driver, 10) username_input wait.until( EC.visibility_of_element_located((By.ID, username)) )这里我用的是 visibility_of_element_located 而不是 presence_of_element_located。两者区别在于presence 只检查元素是否在 DOM 树里存在visibility 还要检查它是否可见、有宽高、没有被遮挡。登录输入框这种必须实际能看到能操作的控件用 visibility 更靠谱。而隐藏的输入框或者某些后端状态标记才考虑用 presence。2.2 登录状态持久化Cookie 才是核心每次跑脚本都重新登录一遍不仅慢而且验证码那道坎过不去。我的做法是第一次手动或者半自动登录成功后把 Cookie 序列化保存到本地以后每次启动脚本前先加载 Cookie直接跳过登录页。这是目前最稳定、最快的方式。import pickle # 登录成功后保存 Cookie with open(cookies.pkl, wb) as f: pickle.dump(driver.get_cookies(), f) # 下次启动时加载 Cookie with open(cookies.pkl, rb) as f: cookies pickle.load(f) for cookie in cookies: driver.add_cookie(cookie)注意一个细节必须先访问一次目标域名然后才能 add_cookie因为 Selenium 不允许在空白页添加 Cookie。通常我会先让浏览器打开主站首页再用 Cookie 刷新这样登录状态就生效了。# 先打开网站再注入 Cookie driver.get(https://example.com/) with open(cookies.pkl, rb) as f: cookies pickle.load(f) for cookie in cookies: driver.add_cookie(cookie) driver.refresh() # 刷新后登录态生效Cookie 持久化之后脚本几乎不用处理验证码了除非 Cookie 过期。Cookie 有效期根据平台来有些一周有效有些一个月有效。我会在脚本里加一个登录状态校验函数判断当前是否还在登录态不在就重新走登录流程。2.3 验证码的三种处理思路验证码是整个自动登录的拦路虎没人能保证 100% 自动过。我试过几种方案按推荐程度排序第一种是人工介入式脚本检测到验证码区域出现时暂停执行等待人工输入。这个方案虽然不够全自动但胜在简单可靠适合个人使用。实现起来就是在验证码出现后 sleep 固定时间等用户完成输入再继续。第二种是接第三方打码平台。这类平台通常提供 Python SDK把验证码图片传过去返回识别结果。识别率取决于验证码难度普通的图形验证码识别率能达到 90% 以上。但要花钱而且滑块的尤其是用了行为轨迹检测的稳定识别很难。第三种是本地 OCR 识别比如用 ddddocr 这种开源库去识别图形验证码。这个方案对纯文字、纯数字的简单验证码效果还行但一旦遇到扭曲变形严重的、带干扰线的识别率就会直线下降。滑块验证码加行为轨迹模拟属于另一个独立的深水区需要单独研究不在本文范围内。我给个中肯建议个人项目不要死磕纯自动过验证码能人工介入就人工介入把全自动改成半自动脚本价值已经很高了。2.4 登录状态校验不要闷着头往下走登录是否成功不能想当然。我见过很多脚本在登录后直接往下执行结果登录失败都不知道最后在下一页报一堆莫名其妙的定位错误。正确做法是登录后做一个显式的状态校验。三个信号至少确认一个页面 URL 是否发生变化从 /login 跳回首页或用户中心页面上是否出现用户头像、用户名等登录后特有元素Cookie 中是否出现了会话标识比如 sessionid 字段def is_logged_in(driver): try: wait WebDriverWait(driver, 5) wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, .user-avatar))) return True except Exception: return False登录状态确认通过后再继续执行下单逻辑。这一步能帮你节省大量排查问题的时间。3. 下单模块从搜索到提交订单的全链路3.1 先规划好点击路径下单流程比登录复杂得多因为页面跳转多、交互步骤多。我强烈建议在写代码之前先手动在浏览器里完整走一遍流程把每一步的页面路径、跳转关系、可能出现的弹窗都记录下来。没有这一步直接凭空写代码会非常痛苦。以我自己项目里的一套流程为例打开首页搜索商品关键词在搜索结果页点击目标商品进入商品详情页在详情页选择 SKU 规格颜色、尺码等点击加入购物车或立即购买进入购物车/结算页核对商品信息确认收货地址点击提交订单按钮这个流程涉及至少五个页面的连续跳转每一步都得等页面加载完成才能继续。我封装了一个通用的处理函数def safe_click(driver, locator, timeout10): 等待元素可点击并点击返回 True 表示点击成功 try: wait WebDriverWait(driver, timeout) element wait.until(EC.element_to_be_clickable(locator)) driver.execute_script(arguments[0].scrollIntoView();, element) element.click() return True except Exception as e: print(f点击失败: {locator}, 错误: {e}) return False3.2 搜索商品与列表页的处理搜索框一般都在页面顶部定位后直接 send_keys 输入关键词然后按下回车或者点击搜索按钮。这里有个小技巧有些网站的搜索建议是动态弹出的输入关键词后会自动展开联想列表如果联想列表遮挡了搜索按钮直接用回车提交会更稳。search_input wait.until(EC.visibility_of_element_located((By.ID, search-input))) search_input.send_keys(机械键盘) search_input.send_keys(Keys.ENTER)回车之后页面开始跳转搜索结果页通常是一个商品列表。我要在列表里定位目标商品优先用商品链接里的唯一标识。假设商品 ID 是 10086在搜索结果里找包含这个 ID 的链接# 等待商品链接出现并点击 target_link wait.until( EC.element_to_be_clickable((By.XPATH, //a[contains(href, product/10086)])) ) target_link.click()这里用 XPath 的 contains 匹配做模糊查找是因为很多网站的商品链接结构是 https://example.com/product/10086?refsearch链接里带了一堆跟踪参数精确匹配容易挂。3.3 详情页选规格一个常见的自动化老大难商品详情页最常见的问题就是 SKU 选择。有些网站的 SKU 选项是用 span 或 div 渲染的普通 click 可能点击不生效因为它们其实是做了事件委托真正的点击目标是更内层的元素。遇到这种情况我会改用 JavaScript 直接触发点击# 找到对应规格元素例如颜色为黑色的选项 sku_option wait.until( EC.element_to_be_clickable((By.XPATH, //div[contains(class, sku-item) and text()黑色])) ) driver.execute_script(arguments[0].click();, sku_option)用 execute_script 点击的好处是绕开了元素被其他浮层遮挡、元素不可见等导致普通 click 失败的问题。但要注意JS 点击不触发某些浏览器原生事件如果页面依赖特定事件监听器可能需要自行 dispatch 事件。实际使用中大多数网站的 SKU 选择用 JS click 都能搞定。另外有些物品种类的 SKU 是多个维度比如颜色、尺码、套餐得一个一个选每选一个还得做一次等待。这种我会封装成循环遍历维度列表for dimension, value in sku_map.items(): locator (By.XPATH, f//div[contains(class, {dimension})]//span[text(){value}]) safe_click(driver, locator) time.sleep(0.5) # 给点时间让页面响应time.sleep(0.5) 在这里不是偷懒而是 SKU 选择后页面需要重新计算价格和库存等待时间很短用显式等待反而要写更多逻辑。3.4 购物车与结算页的细节加购成功后页面上通常会出现一个侧边购物车浮层或者直接跳到购物车页面。这时候要特别注意浮层里的去结算按钮和购物车页面底部的去结算按钮是两个不同的元素定位的时候一定要确认选的是哪个。我通常的做法是先统一进入购物车页面再从比较稳定的入口往下走。购物车页面的结算按钮一般有个很显眼的 class 或者 ID例如 .checkout-btn直接等待它可点击checkout_btn wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, .checkout-btn))) checkout_btn.click()进入结算页之后大多数网站会自动带出默认收货地址。但有个别网站特别是需要用户手动确认地址的会弹窗提示。这时候要处理两种可能要么地址已经选中要么需要点击确认地址按钮。我建议在结算页统一做一次地址校验确认后再继续。还有一个容易忽略的点结算页里通常有提交订单按钮但按钮上方可能有必须勾选的协议复选框。我见过好些脚本在提交订单时被拦截就是因为没勾选协议。这个在写代码前手动走流程时一定要留意观察。3.5 提交订单前的临时检查机制在正式调用 submit 或者点击提交订单之前强烈建议加一道拦截检查。我自己会在下单脚本里做一个二次确认机制默认进入演练模式只跑到结算页就停下来截图保存不真实提交订单。if confirm_mode: driver.save_screenshot(f下订单前确认_{timestamp}.png) return这样反复调试流程的时候不会误下单产生真实订单等流程完全验证通过再把这个开关打开。这个习惯帮我避免了至少三次误下单。4. 稳定性优化与常见问题排查4.1 显式等待是核心别拿 time.sleep 撑场面很多新手习惯用 time.sleep(5) 来等页面加载这种做法在固定网络环境下偶尔能用但一换环境就崩。因为网络延迟、服务器响应时间都是波动的固定等待要么等不够、要么白白浪费时间。正确做法是显式等待指定某个条件满足后再继续执行。Selenium 4 的 expected_conditions 提供了非常丰富的条件除了 visibility_of_element_located 和 element_to_be_clickable 之外还有 staleness_of 等待元素被移除、text_to_be_present_in_element 等待文本出现等。我来举个例子下单完成后要等一个订单成功的提示直接等这个提示元素出现就是最稳的判定条件success_alert wait.until( EC.visibility_of_element_located((By.XPATH, //div[contains(text(), 订单提交成功)])) )4.2 常见异常速查表自动化跑得越久遇到的异常就越杂。我整理了一份自己踩坑最多的异常对照表先贴出来给各位参考。异常类型常见原因解决思路NoSuchElementException元素定位方式错误或元素未加载检查选择器是否正确配合显式等待使用不要直接 find_elementElementNotInteractableException元素存在但被遮挡、隐藏或禁用用 scrollIntoView 滚动到可视区域检查是否有遮罩层需要先关闭StaleElementReferenceException页面上元素被重新渲染旧引用失效重新定位元素不要复用同一个 WebElement 对象在循环里每次重新查询TimeoutException等待条件超时未满足扩大等待时间检查页面是否有弹窗阻断确认选择器在页面中出现ElementClickInterceptedException元素被其他元素遮挡点击失败用 JS 点击先关闭弹窗或广告浮层SessionNotCreatedException浏览器驱动版本和浏览器版本不匹配重新下载对应版本的驱动4.3 元素定位的优先级之争元素定位是自动化脚本里最需要认真对待的事情。很多脚本跑了两天就崩八成是定位写得太脆。我的定位优先级是ID 独立 CSS class 含唯一属性的 CSS 选择器 XPath 精确路径 XPath 文本模糊匹配。能优先用 ID 就用 IDID 在大多数网站里是唯一的。其次是稳定的 CSS class。最忌讳的是为了省事直接复制浏览器的绝对 XPath那种带着 /div[2]/div[3]/span[1] 的路径页面稍微改下 HTML 结构就废了。我见过一个项目测试脚本里全是这种绝对 XPath前端一改版几十条用例全红维护成本高到想让前端改代码。如果必须用 XPath优先考虑用文本匹配加上层级约束少用纯序号定位。Selenium 4 还引入了相对定位器可以用 with_tag_name、above、below、near 等语义描述元素位置可读性很友好但兼容性一般可以小范围尝试。4.4 日志、截图和失败恢复机制在脚本里加日志和异常截图不是小题大做。自动化脚本一跑就是几百步中间任何一步挂了如果没有日志你根本不知道挂在哪里。我的做法是每次关键操作前后都打一条日志出错时保存当时页面的截图和 HTML 源码方便离线分析。import logging from datetime import datetime logging.basicConfig( levellogging.INFO, format%(asctime)s %(levelname)s %(message)s, ) def log_step(msg): logging.info(f[步骤] {msg}) def screenshot_on_error(driver, tag): ts datetime.now().strftime(%Y%m%d_%H%M%S) driver.save_screenshot(ferror_{tag}_{ts}.png) with open(ferror_{tag}_{ts}.html, w, encodingutf-8) as f: f.write(driver.page_source)失败恢复这块最复杂的场景是断点续跑。我目前的方案是把整个流程按阶段拆分每个阶段开始时先检查当前页面 URL 和关键元素判断是应该重新执行本阶段还是可以直接进入下一阶段。比如已经进入购物车页就不需要重新搜索商品并加购了直接走结算流程省掉重复操作。4.5 反爬虫与 webdriver 检测的对抗不少网站会对 Selenium 做些常见特征检测比如检测 window.navigator.webdriver 是否为 true。如果你发现自己的脚本在访问某些网站时行为异常比如页面加载正常但点击无反应或者提示检测到自动化工具可能就是触发了这种检测。常规的处理手段是给浏览器加一些启动参数尽可能抹掉自动化痕迹。下面这段配置是我实测过有效的options Options() options.add_experimental_option(excludeSwitches, [enable-automation]) options.add_experimental_option(useAutomationExtension, False) options.add_argument(--disable-blink-featuresAutomationControlled)这组配置能让 navigator.webdriver 返回 undefined降低被识别的概率。但要注意网站的检测手段也一直在升级如果你遇到的反爬手段比较激进可能需要引入更复杂的浏览器指纹伪装方案这已经超出基础自动化的范畴了。而且我必须提醒一句别把这些技巧用在抢购、刷单、干扰正常电商运营的用途上写自动化脚本的初衷应该是提升个人效率或做系统自动化测试不是去薅系统羊毛。5. 扩展、调优与合理使用建议5.1 让脚本跑得更稳配置外置与定时任务脚本写得好不够关键还要跑得稳。我把账号密码、目标商品链接、下单数量这类经常变动的内容统一放到一个配置文件里而不是硬编码在代码中。这样要修改参数时不用改动代码逻辑也不容易误改关键代码。import json # config.json # { # username: your_account, # password: your_password, # product_url: https://example.com/product/10086, # quantity: 1, # headless: false # } with open(config.json, r, encodingutf-8) as f: config json.load(f)跑定时任务我的经验是Linux 用 crontabWindows 用任务计划程序非常简单可靠。比如每天早上 9 点跑一次补货下单检查crontab 写一行就够。0 9 * * * cd /path/to/project /usr/bin/python3 main.py run.log 215.2 接入消息通知掌握脚本实时状态脚本跑在服务器上如果中途挂了没人发现那和没跑没区别。我一般会给脚本加一个钉钉或者企业微信机器人的 Webhook 通知在关键节点登录成功、下单成功、脚本异常推送消息到手机上。现在这类群机器人的 Webhook 接口很简单一个 requests.post 就能搞定。import requests def send_notification(msg): webhook_url https://your-webhook-url data {msgtype: text, text: {content: msg}} requests.post(webhook_url, jsondata, timeout5)这样脚本跑到哪一步、有没有出错手机一目了然。我甚至会把订单号的最后四位也推送出来方便核对。5.3 关于自动下单的边界问题写到这里我得认真说几句经验之谈。自动下单脚本能力很强但一定要搞清楚使用边界。它适合用在你拥有账号或你负责维护的系统、需要高频重复操作的个人流程、接口不稳定但浏览器操作可靠的业务场景。在这些场景下自动化是实实在在的生产力工具。但它绝不适用于批量刷单、抢购倒卖、绕过平台规则扰乱正常交易秩序。这类行为不仅损害其他正常用户的利益还可能导致账号被封禁严重的甚至涉及法律风险。我在任何一个自动下单项目里都会明确画这条线。包括验证码处理也一样。我上面讲的人工介入和简单识别方案是为了处理你自己账号登录时偶尔出现的验证码。但如果一门心思想着怎么彻底破解各种验证码这个方向本身就值得重新审视。5.4 进一步优化的方向如果你的基本功已经比较扎实可以在现有项目上继续扩展。方向一对接 OCR API 自动识别简单的图形验证码减少人工介入频率。方向二引入代理 IP 池解决部分场景下 IP 被限流的问题。方向三把 Selenium 脚本打包成带 GUI 的小工具让不熟悉命令行的同事也能直接操作。方向四了解 Playwright 的现代 API作为备选自动化方案。从长期来看浏览器自动化技能的底层逻辑是通用的——掌握了一个工具换到另一个工具只是学习新语法。真正值钱的是你对怎么把现实世界的复杂流程规范成妥善的自动化步骤这项能力的理解。我在做完这套登录下单自动化之后最大的体会是很多看似自动化很难的问题其实只是因为你没有先把流程拆解到足够细。拆到每一步都是一个明确的输入、操作、输出剩下的就是用 Selenium 把每一步翻译成代码罢了。希望这篇文章能帮你少走点弯路把时间花在真正有意思的问题上。
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。