资讯详情

资讯详情

京东商品数据采集分析可视化平台:Python+Django+Selenium+Echarts全流程实战

每年到课程设计和毕业设计的时候后台私信里问得最多的就是一句话有没有那种“一整套、能直接跑、还能讲清楚原理”的项目。今天把这个京东商品数据采集分析可视化平台拿出来说说它几乎把毕设和课设里常见的考核点全占了——Python 爬虫、Django 后端、数据库建模、Echarts 可视化一条链路走完。你可以把它当模板也可以直接在上面改造出自己的项目。这个项目核心做的事很简单用 Selenium 驱动浏览器去京东搜索页抓取指定商品的公开信息把标题、价格、店铺、评论数、链接这些字段落库再用 Django 写几个统计接口最终用 Echarts 在前端展示出价格分布、销量排行、价格区间占比这些图表。对你交作业来说它是一份完整的“数据采集-数据存储-数据分析-可视化展示”闭环对你学技术来说它又是理解爬虫和 Web 开发边界的好样本。最关键的是整套方案我已经跑通很多次了下面会把每一步怎么选型、怎么落地、会踩什么坑全部摊开写清楚。1. 项目先搞清楚要做什么技术组合与整体架构很多同学拿到一个题目就急着敲代码其实第一步应该先想清楚这个项目做完之后要能展示什么要支撑哪些知识点。我当初选这个题目就是看中它“麻雀虽小五脏俱全”它能同时覆盖四件事动态页面数据怎么抓、抓来的数据怎么存、存好的数据怎么查、查出来的数据怎么可视化。1.1 这门课程设计到底值不值得选先说结论非常值得。你要知道计算机课程的课设或毕设评委最看重的往往不是功能多花哨而是你有没有把一个完整流程跑通并且能讲清楚每一步为什么这么做。这个项目恰好是一条完整链路数据源是真实网站不是 mock 数据说服力强爬虫用的是 Selenium能应对动态渲染页面技术上有亮点Django 自带 ORM 和 Admin 后台不用额外写一堆 SQL开发效率高Echarts 出图快视觉效果也好答辩演示非常加分。它不像纯算法题那样理论深也不像纯管理系统那样平淡属于“有点技术难度但可控”的中间档。Python 基础入门水平就能驾驭哪怕你是第一次做项目按我下面的步骤走也能在几天内跑通。1.2 为什么是 Python Django Selenium Echarts 这个组合我知道有人会问爬虫为什么不用 Scrapy为什么不用 requests BeautifulSoup页面分析为什么不用 requests 直接拿 HTML这里有个很现实的原因京东的搜索列表页是动态渲染的很多商品数据是在页面加载过程中通过脚本写入 DOM 的。你用 requests 去请求拿到的 HTML 里可能只有框架商品卡片得靠浏览器执行完 JavaScript 之后才出现。除非你能精确分析出背后的异步接口并模拟参数工作量和稳定性成本都很高否则用 Selenium 驱动真实浏览器反而是最稳的。Django 在这里也不是随便选的。相比 FlaskDjango 自带 Admin 后台让数据管理页面“白送”自带 ORM 让建表和查询都很方便自带模板引擎又能直接对接 Echarts 的 JSON 数据。课程设计往往要求一个“系统”的观感Django 天然有这个味道。Flask 当然也能做但你需要自己拼的东西太多对新手不友好。Echarts 就更不用说了百度开源之后由 Apache 基金会维护中文文档非常全图表类型丰富社区案例一搜一大把。相比 Highcharts 需要商业授权顾虑、D3 上手曲线陡Echarts 是课程设计里性价比最高的方案。2. 环境准备把一台干净电脑变成开发机这个项目对环境的要求不复杂但有一个地方特别容易翻车——ChromeDriver 版本不匹配。我一次一次给大家排掉这些坑先说安装再说版本最后给目录规划。2.1 Python、Django、Selenium 的安装细节Python 版本建议用 3.10 或 3.11别追最新。最新的 Python 版本发布后第三方库的兼容性往往还没完全跟上课程设计的节点等不起。装完 Python 之后强烈建议在当前项目目录创建虚拟环境python -m venv venvWindows 下激活venv\Scripts\activateMac/Linux 下激活source venv/bin/activate然后安装依赖pip install django selenium pandas这里我把 pandas 也加进来了主要用途不是分析数据而是做清洗和临时 Dataframe 过渡后面入库会非常方便。Django 装 4.x 版本就可以Selenium 装 4.x这两个版本配套稳定。装完可以检查一下版本python -c import django, selenium; print(django.__version__, selenium.__version__)能正常输出版本号环境这一步就算过了。2.2 ChromeDriver 版本匹配的坑Selenium 本身只是控制浏览器的工具真正干活的其实是你本机安装的 Chrome 浏览器而 Selenium 和浏览器之间需要通过一个驱动文件来沟通这个文件就是 ChromeDriver。版本匹配非常重要ChromeDriver 的主版本号必须和 Chrome 浏览器的主版本号一致否则会直接报SessionNotCreatedException大概意思是“会话无法创建驱动版本与浏览器不匹配”。规避方法很简单打开浏览器看“关于 Chrome”里的版本号比如是 120.x就去下载 120 版本的 ChromeDriver。下载之后建议统一放到项目的 drivers 目录下方便管理。Windows 下初始化时这样指定路径from selenium.webdriver.chrome.service import Service service Service(./drivers/chromedriver.exe) driver webdriver.Chrome(serviceservice, optionsoptions)很多新手喜欢把 chromedriver.exe 随便扔桌面然后发现代码里找不到文件报错这种低级问题在答辩现场出现就尴尬了。2.3 工程目录的规划虽然是个课程设计但目录尽量规整对你自己写代码有好处对答辩加分也更明显。我常用的结构如下jd_project/ ├── manage.py ├── jd_analysis/ # Django 项目配置目录 │ ├── settings.py │ ├── urls.py │ └── wsgi.py ├── analysis_app/ # Django 应用目录 │ ├── models.py │ ├── views.py │ ├── admin.py │ ├── migrations/ │ └── management/ │ └── commands/ # 自定义 Django 命令 │ └── run_spider.py ├── spider/ # 独立爬虫模块不归 Django 管 │ ├── jd_spider.py │ └── chromedriver.exe ├── templates/ │ └── index.html └── static/ ├── css/ └── js/这里有一个设计思路爬虫单独放 spider/ 目录不直接塞进 Django 应用里。这样爬虫模块可以被独立测试也可以在需要的时候通过 Django 命令调用。后面我会讲两种调用方式都试过都可行。3. 爬虫模块实战Selenium 采集京东商品数据这整个项目里最容易出问题的就是爬虫模块它的核心难点不全在编码而在于页面元素能不能稳定地找到、页面加载够不够快、会不会触发平台的验证机制。下面按“页面分析 → 主流程 → 反爬底线 → 数据清洗”的顺序说。3.1 先看页面结构再写代码打开京东搜索页用开发者工具F12选中任意一个商品卡片你会发现每个商品都包在一个li标签里class 为gl-item。这个卡片里标题对应.p-name里面的链接和文字价格对应.p-price里的i标签店铺名对应.p-shop评论数对应.p-commit。强烈建议写爬虫之前先做一次“手动探测”。也就是只启动浏览器访问一次页面然后在浏览器控制台里测试一下选择器是否生效例如document.querySelectorAll(.gl-item)如果返回了一堆节点说明选择器没问题如果返回空说明页面还没加载完或者结构变了。这一步花五分钟能省后面调试的两小时。京东搜索页的翻页比较特殊第一页 URL 的 page 参数是 1第二页是 3第三页是 5也就是奇数页码依次递增。实际写代码时可以直接按规则拼接 URL减少点击翻页按钮的等待时间。3.2 采集主流程搜索、翻页、解析初始化浏览器时有几个配置是必须加的不加很容易被识别或浪费资源from selenium import webdriver from selenium.webdriver.chrome.options import Options options Options() options.add_argument(--disable-gpu) options.add_argument(--window-size1400,900) options.add_argument(--user-agentMozilla/5.0 ... Chrome/120.0 Safari/537.36) driver webdriver.Chrome(serviceservice, optionsoptions) # 隐式等待让元素查找在指定时间内轮询 driver.implicitly_wait(5)这里--disable-gpu是为了避免部分电脑上 GPU 进程导致白屏window-size影响页面渲染布局有些元素在窄屏下会被折叠。加 User-Agent 是为了让服务端尽量认为你是一个正常浏览器。然后就是打开搜索页、等待商品卡片加载、循环翻页、解析数据。核心逻辑如下import time import random from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC def fetch_keyword(keyword, pages3): results [] for page in range(1, pages * 2 1, 2): url fhttps://search.jd.com/Search?keyword{keyword}page{page} driver.get(url) # 等待商品卡片出现 WebDriverWait(driver, 10).until( EC.presence_of_element_located((By.CSS_SELECTOR, .gl-item)) ) items driver.find_elements(By.CSS_SELECTOR, .gl-item) for item in items: title item.find_element(By.CSS_SELECTOR, .p-name em).text price item.find_element(By.CSS_SELECTOR, .p-price i).text shop item.find_element(By.CSS_SELECTOR, .p-shop a).text link item.find_element(By.CSS_SELECTOR, .p-name a).get_attribute(href) comment item.find_element(By.CSS_SELECTOR, .p-commit strong).text results.append({ keyword: keyword, title: title, price: price, shop: shop, comment: comment, link: link }) time.sleep(random.uniform(2, 4)) return results注意几个细节用WebDriverWait等待核心元素出现比直接用time.sleep更稳。页面加载快的时候它不浪费时间加载慢的时候它也不会因为固定等待时间太短而失败。翻页后元素引用会失效所以每次翻页之后要重新find_elements不要用之前保存的列表继续操作否则报StaleElementReferenceException这个非常常见。循环之间加随机延时模拟人的操作节奏。3.3 关于反爬与请求频率的底线这个部分我必须单独拎出来说。很多教程喜欢教你各种绕过验证的方式但我希望你把一条主线记在心里这个项目是课程设计和毕业设计用途是学习和演示不是商业采集。做类似项目时要注意几点控制采集频率。我建议每翻一页之后随机等待 2~4 秒不要毫无间隔地连发请求。等待既是为了稳定也是最基本的礼貌。遇到验证码或滑块类的交互不要硬绕。非法绕过验证机制可能给你带来麻烦正确做法是退出浏览器、过一段时间再继续或者干脆减少采集页数。只采集页面展示的公开信息不采集用户隐私数据也不把数据用于商业用途。你的代码里最好写一个MAX_PAGES参数默认只抓 2~3 页。演示的时候够用也安全。如果你做到这些项目既能顺利完成也能让你理直气壮地在答辩时说清楚自己的边界意识。面试官和评委都听过太多“爬虫灰产”的传闻你能讲出合规意识反而是加分项。3.4 数据清洗与入库前的处理直接抓下来的数据是不能直接入库的需要先清洗几处标题里经常有多余空格、换行符用re.sub(r\s, , title)压缩价格是字符串可能是“100.00”这种带符号的要提取数字并转成 float用正则re.findall(r\d\.?\d*, price)评论数常见格式是“15.2万”要么原样存字符串要么统一转成可比较的数字例如 15.2*10000店铺名可能为空需要给个默认值比如“未知店铺”。清洗完之后如果在项目里引入了 pandas可以先把所有商品记录装进一个 DataFrame统一再遍历入库。这不仅让代码看起来干净在你想做进一步分析的时候也方便。我实际测试中抓 3 页大约 60~90 条数据足够撑起所有图表的展示效果。偶尔一两条字段为空是完全正常的入库前做好兜底即可。4. Django 后端设计数据模型与业务接口爬虫抓完数据只是上半场下半场要把数据接进 Django。这里我讲讲数据表怎么建、爬虫怎么和工程打通、后台怎么配置三个关键点最后补充查询统计的写法。4.1 数据表怎么设计最省事课程设计的数据模型不用设计得过度复杂但也不能就一张表摆在那里。我建议建一张核心表用来存商品信息字段如下from django.db import models class GoodsInfo(models.Model): keyword models.CharField(max_length32, verbose_name搜索关键词) title models.CharField(max_length512, verbose_name商品标题) price models.FloatField(verbose_name商品价格) shop models.CharField(max_length128, verbose_name店铺名称) comment models.CharField(max_length32, verbose_name评论数) link models.URLField(verbose_name商品链接) sku_id models.CharField(max_length32, verbose_name商品SKU) collect_time models.DateTimeField(auto_now_addTrue, verbose_name采集时间) class Meta: verbose_name 商品信息 verbose_name_plural 商品信息 def __str__(self): return self.titlesku_id是从链接里提取的商品唯一编号。为什么要加它因为重复采集时可以用sku_id keyword做唯一约束避免一次课设还没做完数据就已经重复堆了几百条。用update_or_create也可以总之“同一个商品不要重复出现”是需求里很合理的点。补充一个小技巧comment字段我用的 CharField而不是 IntegerField因为“万”这种后缀在京东很常见如果转数字会丢失原始展示形式。你可以保留字符串展示时原样输出。4.2 爬虫程序怎么和 Django 工程打通这里有两种方式我都实际操作过给你对比一下。第一种爬虫独立运行时手动设置 Django 环境变量。在 spider/jd_spider.py 文件顶部加几行import os import django os.environ.setdefault(DJANGO_SETTINGS_MODULE, jd_analysis.settings) django.setup() from analysis_app.models import GoodsInfo这样你直接运行python jd_spider.py就能用 Django 的 ORM 入库。好处是逻辑简单适合爬虫和后端分开调试。第二种把爬虫封装成 Django 自定义命令。在 application 下创建 management/commands/run_spider.py然后写一个 Command 类。之后就能用python manage.py run_spider 关键词来触发采集。这种方式更优雅答辩演示时直接在终端敲命令比双击脚本显得专业很多。我个人的课程设计推荐用第二种因为它和 Django 的联系更紧密评委问起来也更好讲。无论哪种方式采集入库的示例逻辑都差不多obj, created GoodsInfo.objects.update_or_create( sku_idsku_id, keywordkeyword, defaults{ title: title, price: price, shop: shop, comment: comment, link: link, } )4.3 用 Django Admin 做后台管理Django 自带的 Admin 后台是这个项目非常实用的加分功能。在 admin.py 里做一点配置from django.contrib import admin from .models import GoodsInfo admin.register(GoodsInfo) class GoodsInfoAdmin(admin.ModelAdmin): list_display [title, keyword, price, shop, comment, collect_time] list_filter [keyword, collect_time] search_fields [title, shop] list_per_page 20配置完之后访问/admin登录管理后台就能看到商品数据的列表还能按关键词筛选、按标题搜索。答辩的时候把这个界面展示一下然后说一句“平台提供了后台管理功能方便查看和维护数据”效果比干讲代码好得多。4.4 查询与统计接口可视化页面需要的数据不能直接从数据库裸奔要经过统计接口。Django ORM 提供了一批很方便的聚合方法。比如计算某一关键词商品的平均价格和价格区间from django.db.models import Avg, Max, Min, Count stats (GoodsInfo.objects .filter(keyword洗衣机) .aggregate(avg_priceAvg(price), max_priceMax(price), min_priceMin(price), totalCount(id)))比如评论数 TOP10 商品top GoodsInfo.objects.filter(keyword洗衣机).order_by(-comment_value)[:10]如果你真的把评论数存成了字符串这里会有点麻烦所以也可以在入库时额外加一个comment_value整数字段专门存转换后的数字。这里算是一个扩展建议展示用comment排序用comment_value两不误。5. 可视化页面Echarts 让数据说话数据有了、接口有了最后一步是把它画出来。这一部分我按“模板怎么搭 → 图表怎么配 → 数据怎么传”三段来讲。5.1 前端模板和图表容器怎么搭在 templates/index.html 里引入 Echarts 的 CDN 文件然后放几个固定高度和宽度的 div 容器。一个容易踩的细节是Echarts 的图表容器必须有显式的高度否则图表会渲染成空白。!DOCTYPE html html head meta charsetUTF-8 title京东商品数据分析平台/title script srchttps://cdn.jsdelivr.net/npm/echarts5/dist/echarts.min.js/script /head body div h2商品价格分析/h2 div idpriceDist stylewidth: 100%; height: 400px;/div /div div h2评论数 TOP10/h2 div idcommentTop stylewidth: 100%; height: 400px;/div /div /body /html如果你不想依赖 CDN也可以把 echarts.min.js 下载下来放到 static/js 下答辩现场如果真的没网就靠本地文件兜底。我一般两种都会准备不丢人。5.2 核心图表的配置思路最常见的几个图表我直接给你配置的骨架。价格分布柱状图思路是把数据按价格区间分组比如 0-1000、1000-2000、2000-3000统计每档的数量。Echarts 的配置核心option { xAxis: { type: category, data: [0-1000, 1000-2000, 2000-3000] }, yAxis: { type: value }, series: [{ type: bar, data: [23, 15, 8], itemStyle: { color: #5470c6 } }], tooltip: {} };评论数 TOP10 条形图把数据倒过来更直观用 yAxis 显示商品简称xAxis 显示评论数option { xAxis: { type: value }, yAxis: { type: category, data: [...商品标题...] }, series: [{ type: bar, data: [...评论数...] }], tooltip: {} };价格区间占比饼图把所有商品按价格切片算比例option { series: [{ type: pie, data: [ { name: 0-1000, value: 23 }, { name: 1000-2000, value: 15 } ] }], tooltip: { trigger: item } };配置本身并不复杂真正要注意的是数据的映射。很多同学把后端数据拿过来之后不会组装成 option 需要的结构这一步我建议在视图函数里就把 JSON 整理好而不是在前端做复杂的转换。5.3 数据从 Django 到 Echarts 的 JSON 传递在 views.py 里写一个接口返回统计好的 JSON。最简单的方式是直接渲染模板时把数据塞到上下文里import json from django.shortcuts import render from .models import GoodsInfo from django.db.models import Count def dashboard(request): keyword request.GET.get(keyword, 洗衣机) goods_list GoodsInfo.objects.filter(keywordkeyword) price_buckets {0-1000: 0, 1000-2000: 0, 2000-3000: 0, 3000: 0} for g in goods_list: if g.price 1000: price_buckets[0-1000] 1 elif g.price 2000: price_buckets[1000-2000] 1 # ... 以此类推 top10 goods_list.order_by(-comment_value)[:10] context { price_buckets_json: json.dumps(list(price_buckets.values()), ensure_asciiFalse), price_labels_json: json.dumps(list(price_buckets.keys()), ensure_asciiFalse), top_names_json: json.dumps([p.title[:12] for p in top10], ensure_asciiFalse), top_comments_json: json.dumps([p.comment_value for p in top10], ensure_asciiFalse), } return render(request, index.html, context)在模板里正常使用var priceLabels {{ price_labels_json | safe }}; var priceValues {{ price_buckets_json | safe }};用json.dumps(ensure_asciiFalse)是为了避免中文被转成 Unicode 转义序列加上| safe是为了告诉 Django 这个数据可以直接输出。这一步很多人漏掉结果发现图表里中文变成了一堆\uXXXX。6. 我实际踩过的坑与排查实录下面这些问题是你在开发过程中大概率会遇到的我按类型整理成速查方便你卡住的时候直接翻。6.1 Selenium 最常见的四个报错第一个是NoSuchElementException。原因一般是元素还没加载出来或者选择器写错了。解决办法把隐式等待时间调高一点或者改用WebDriverWait等待元素出现。如果元素确实存在但报错建议打开浏览器开发者工具重新确认选择器。第二个是ElementClickInterceptedException。翻译成人话就是你想点的东西被别的元素挡住了。常见于页面上飘出弹窗、浮层、推荐位。解决办法是改用 JS 直接点击driver.execute_script(arguments[0].click();, element)第三个是StaleElementReferenceException。翻页后之前定位到的元素已经不在当前 DOM 里了。解决办法很粗暴每次翻页后重新定位不要复用旧的对象。第四个是SessionNotCreatedException。这个九成是 ChromeDriver 版本和浏览器版本不一致。先去对照版本重新下载驱动再来。6.2 Django 数据入库的编码与更新问题中文乱码问题在 Python 3 Django 4 下很少见了但还是建议在 settings.py 里确认LANGUAGE_CODE zh-hans TIME_ZONE Asia/Shanghai USE_I18N True USE_TZ True如果你决定用 MySQL要额外注意 charset要在数据库连接里指定 utf8mb4。但我真心建议课程设计直接用 SQLite零配置、单文件、和 Django 完美配合答辩时直接把项目压缩包拷走都不会有数据库连接问题。还有一个比较隐蔽的问题重复采集导致数据越攒越多。所以我在前面强调唯一约束和update_or_create。你可以在模型层加上联合约束class Meta: constraints [ models.UniqueConstraint(fields[sku_id, keyword], nameunique_sku_per_keyword) ]这样重复采集同一关键词同一商品时不会生成新记录。6.3 Echarts 图表不显示的几类原因我测试时遇到过三种情况基本覆盖了你可能遇见的九成问题。第一种是容器高度为 0导致图表画布什么都看不到。上文已经说过给 div 一个固定高度比如height: 400px。第二种是数据格式不对。Echarts 的 series.data 需要的是数组如果你传入的是对象或者字符串控制台会报错。前端拿到数据后可以用console.log打印一下看看是不是你预期的数组结构。第三种是 CDN 加载失败。如果你的网络环境不稳定页面白屏且控制台报echarts is not defined解决办法就是下载本地 echarts.min.js 并引入。演示之前一定要提前测试一次离线打开页面防止现场没有外网导致图表全灭。6.4 课程设计答辩时的演示技巧最后分享一点答辩经验。演示的时候千万不要现场从零开始爬取大量数据网络波动、验证码、页面结构变化任何一个因素都可能让你当场翻车。正确做法是提前把数据跑好入库演示时只针对新加的某个关键词抓少量数据等几秒刷新图表展示一个“增量采集”的效果即可。我习惯准备三张截图一张数据库表的数据截图一张运行爬虫命令的终端日志截图一张可视化页面的完整截图。答辩时先讲架构再演示系统最后展示截图评委问细节时直接打开代码对照讲。7. 关于这个项目的几点个人心得这个项目做完之后我自己最大的感受是它非常适合作为“第一个完整项目”来练手。你不需要同时啃下很多新技术只要把 Python 基础语法、简单的 HTML/JavaScript 知识、以及一点点数据库概念就能把整个链路串起来。串起来之后你对 Django 的 MTV 模式、ORM 的用法、Selenium 驱动浏览器的原理都会有比看书深刻得多的理解。做完基础版之后值得扩展的方向我列一下你可以根据兴趣挑一个给项目加定时任务每天自动采集一次并更新价格趋势加词云分析把商品标题里的高频词画出来加评论区情感分析对商品评价做正负面判断把数据源从京东换成其他公开的新闻站点或公开数据集整个架构基本不需要动只改爬虫解析部分。最后再说一个小技巧。你在把项目交上去或者写进简历的时候不要只写“用 Django 和 Selenium 做了一个可视化平台”而是把你做深的那一点写出来。比如你解决了动态页面数据抓取中的等待策略问题比如你做了数据唯一约束和增量更新设计比如你做价格区间分布的时候考虑了采集时间对价格的影响。把一个点讲透永远比罗列一堆名词更有说服力。
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →