Django+requests京东比价系统实战:从爬虫到展示全链路拆解
简介这是一套基于Python与Django框架开发的京东商品比价系统完整项目源码面向计算机相关专业的毕业设计、课程设计及项目开发学习者帮助解决电商价格监控与比价分析类选题的实现难题。项目采用request爬虫抓取京东商品数据配合数据库存储已实现注册登录、商品收藏、十五天内价格折线图展示、按品类推荐降幅比最大商品以及跳转购买等核心功能逻辑完整、贴近真实业务场景。压缩包共2001个文件约16.2MB其中以1174个py源码文件为主体辅以368个pyc编译文件、128个html模板、82个js脚本及css样式、po/mo国际化语言包、sql建表脚本与json配置等前后端与数据层结构清晰。目前已有75人学习下载源码经过严格测试可直接运行参考并在此基础上进行功能扩展或二次开发适合作为毕业设计答辩与课程实践的可靠基础。1. 从零拆解一套京东商品比价系统Django requests 到底能跑多远电商比价这件事听起来像个小工具真动手才知道坑有多密。我最近把一套基于 Python Django 的京东商品比价系统完整跑了一遍从爬虫抓取、数据入库到前端展示链路不算长但每一环都有值得说道的地方。这套资源的核心价值在于它把爬取—清洗—存储—比价—展示这条完整链路用 Django 串了起来而不是丢给你一个孤零零的爬虫脚本。适合谁正在做毕业设计、课程设计或者想拿一个完整 Web 项目练手的同学。它不追求高并发工业级但胜在结构清晰、能跑通、方便二次改造。下面我按实际拆解顺序把选型理由、关键代码、参数设置和踩坑记录一条条摊开讲。2. 技术选型与项目骨架为什么是 Django 而不是 Flask2.1 比价系统的功能拆解与框架匹配先想清楚这个系统要干什么。比价系统的本质是定时或按需抓取目标商品的名称、价格、店铺、销量等字段存进数据库然后在前端按关键词搜索、按价格排序、展示历史价格走势。它天然需要 ORM、后台管理、模板渲染和路由这几样东西。Django 自带 admin 后台、ORM 和模板引擎等于开局就送了一套管理界面和数据层对毕业设计这种功能要全、时间要短的场景非常友好。Flask 更轻但你得自己拼 SQLAlchemy、自己写后台工作量反而更大。这套资源的技术栈是 Python Django requests MySQL常见做法也可换 SQLite。requests 负责发 HTTP 请求拿页面Django 负责业务逻辑和展示。选 requests 而不是 Scrapy是因为比价场景的抓取量不大、页面结构相对固定用 requests 解析库足够没必要上 Scrapy 那套重量级调度。2.2 目录结构与核心模块职责一个能跑的 Django 项目目录大致长这样jingdong_price/ ├── manage.py ├── jingdong_price/ # 项目配置 │ ├── settings.py │ ├── urls.py │ └── wsgi.py ├── spider/ # 爬虫应用 │ ├── models.py # 商品数据模型 │ ├── views.py # 抓取触发与比价逻辑 │ └── utils.py # 请求封装、解析函数 ├── templates/ # 前端模板 └── static/ # 静态资源models.py定义商品表utils.py放请求头和解析逻辑views.py把抓取和展示串起来。这种分层的好处是爬虫规则变了只改utils.py数据字段变了只改models.py互不干扰。2.3 数据模型设计字段怎么定才够用比价系统的数据模型直接决定后面能做什么分析。核心表至少要有这些字段字段名类型说明goods_idCharField商品唯一标识用于去重titleCharField商品标题priceDecimalField当前价格用 Decimal 避免浮点误差shop_nameCharField店铺名称comment_countIntegerField评论数可作热度参考crawl_timeDateTimeField抓取时间用于历史价格对比urlURLField商品链接价格字段一定要用DecimalField而不是FloatField。我见过太多人用 float 存价格结果 19.9 存进去变成 19.899999比价时排序全乱。这是血泪经验别省这一步。# spider/models.py from django.db import models class Goods(models.Model): goods_id models.CharField(max_length32, uniqueTrue, verbose_name商品ID) title models.CharField(max_length255, verbose_name商品标题) price models.DecimalField(max_digits10, decimal_places2, verbose_name价格) shop_name models.CharField(max_length128, blankTrue, verbose_name店铺) comment_count models.IntegerField(default0, verbose_name评论数) crawl_time models.DateTimeField(auto_now_addTrue, verbose_name抓取时间) url models.URLField(max_length500, blankTrue, verbose_name商品链接) class Meta: ordering [-crawl_time] verbose_name 商品goods_id加uniqueTrue是为了配合后面的update_or_create做去重避免同一商品反复入库。auto_now_addTrue让抓取时间自动填充省得手动传。3. requests 抓取实战请求头、分页与解析的完整链路3.1 请求封装请求头是能不能拿到数据的第一道关京东的搜索页对请求头比较敏感裸 requests 直接请求大概率拿到空数据或验证页。常见做法是伪装一套完整的浏览器请求头尤其是User-Agent、Referer和Cookie。# spider/utils.py import requests import time import random HEADERS { User-Agent: ( Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 ), Referer: https://search.jd.com/, Accept-Language: zh-CN,zh;q0.9, } def fetch_page(url, paramsNone, retry3): 带重试的页面抓取失败后随机延时再试 for i in range(retry): try: resp requests.get( url, headersHEADERS, paramsparams, timeout10 ) if resp.status_code 200: return resp.text except requests.RequestException as e: print(f第{i1}次请求失败: {e}) time.sleep(random.uniform(1, 3)) # 随机延时降低被封风险 return Nonetimeout10防止请求卡死retry3配合随机延时是应对偶发失败的标配。random.uniform(1, 3)让每次请求间隔不固定比固定 sleep 更不容易触发风控。注意这里的Cookie我没有硬编码因为 Cookie 会过期正确做法是从浏览器手动复制后放进配置或者用 session 维持。3.2 分页抓取page 参数与翻页逻辑京东搜索页的分页参数是page但它是奇数递增的1、3、5……每页大约 30 个商品。翻页逻辑要处理这个规律def crawl_search(keyword, max_page5): 按关键词抓取多页搜索结果 base_url https://search.jd.com/Search all_goods [] for p in range(1, max_page * 2, 2): # 1,3,5,7... params {keyword: keyword, enc: utf-8, page: p} html fetch_page(base_url, paramsparams) if not html: continue goods parse_goods(html) all_goods.extend(goods) time.sleep(random.uniform(2, 4)) # 页间延时拉长 return all_goodsrange(1, max_page * 2, 2)生成的就是 1、3、5 这样的奇数序列。页间延时比单次重试延时更长因为连续翻页更容易被识别。max_page控制抓取深度毕设演示抓 5 页足够抓太多既慢又容易触发限制。3.3 页面解析定位价格与标题的稳定写法解析是比价系统里最容易翻车的一环因为页面结构会变。常见做法是用 BeautifulSoup 配合 CSS 选择器把选择器集中管理方便页面改版时统一替换。from bs4 import BeautifulSoup def parse_goods(html): 从搜索页 HTML 中提取商品列表 soup BeautifulSoup(html, html.parser) results [] for item in soup.select(li.gl-item): try: goods_id item.get(data-sku, ) title item.select_one(div.p-name em).get_text(stripTrue) price item.select_one(div.p-price i).get_text(stripTrue) shop item.select_one(div.p-shop a) results.append({ goods_id: goods_id, title: title, price: price, shop_name: shop.get_text(stripTrue) if shop else , }) except AttributeError: continue # 单个商品解析失败不影响整体 return results>from decimal import Decimal, InvalidOperation from .models import Goods def save_goods(items): 批量入库按 goods_id 去重更新 for it in items: try: price Decimal(it[price].replace(¥, ).strip()) except (InvalidOperation, KeyError): continue # 价格解析失败就跳过 Goods.objects.update_or_create( goods_idit[goods_id], defaults{ title: it[title], price: price, shop_name: it.get(shop_name, ), }, )update_or_create以goods_id为键存在就更新defaults里的字段不存在就新建。这样同一商品的历史价格会被覆盖——如果你要做价格走势得另建一张历史价格表每次抓取都插一条而不是覆盖。这是设计上要提前想清楚的点。4. Django 比价逻辑与前端展示从查询到排序4.1 比价视图多条件查询与排序比价的核心视图要支持关键词搜索、价格区间过滤和排序。用 Django ORM 的filter和order_by组合即可# spider/views.py from django.shortcuts import render from .models import Goods def compare(request): keyword request.GET.get(kw, ).strip() min_price request.GET.get(min, ) max_price request.GET.get(max, ) order request.GET.get(order, price) qs Goods.objects.all() if keyword: qs qs.filter(title__icontainskeyword) if min_price: qs qs.filter(price__gtemin_price) if max_price: qs qs.filter(price__ltemax_price) if order in (price, -price, -comment_count): qs qs.order_by(order) return render(request, compare.html, {goods_list: qs[:50]})title__icontains做不区分大小写的模糊匹配price__gte/price__lte做区间过滤。order参数做了白名单校验只允许指定的排序字段防止用户传入非法字段导致报错。qs[:50]限制返回条数避免一次渲染太多拖慢页面。4.2 模板渲染与价格高亮前端模板把商品列表渲染成表格或卡片价格最低的做高亮这是比价系统最直观的价值点!-- templates/compare.html -- table thead trth商品/thth价格/thth店铺/thth评论数/th/tr /thead tbody {% for g in goods_list %} tr {% if forloop.first %}classcheapest{% endif %} tda href{{ g.url }}{{ g.title }}/a/td td¥{{ g.price }}/td td{{ g.shop_name }}/td td{{ g.comment_count }}/td /tr {% endfor %} /tbody /table因为视图里默认按价格升序forloop.first就是最便宜的那条给它加个cheapest类做高亮。这个思路简单但有效答辩时演示效果很直观。4.3 定时抓取的两种落地方式比价系统不能只靠手动点按钮抓取。常见做法有两种一是用 Django 的manage.py自定义命令配合系统定时任务二是用 Celery 做异步调度。毕设场景推荐第一种简单可控# spider/management/commands/crawl.py from django.core.management.base import BaseCommand from spider.utils import crawl_search, save_goods class Command(BaseCommand): help 按关键词抓取京东商品并入库 def add_arguments(self, parser): parser.add_argument(keyword, typestr) parser.add_argument(--pages, typeint, default3) def handle(self, *args, **options): items crawl_search(options[keyword], max_pageoptions[pages]) save_goods(items) self.stdout.write(f入库 {len(items)} 条)写好命令后python manage.py crawl 手机 --pages 5就能手动跑再挂到系统的定时任务里定时执行。add_arguments让关键词和页数可配置不用改代码。5. 避坑与排查这套系统最容易翻车的五个地方5.1 抓不到数据返回空列表或验证页现象fetch_page返回 200但parse_goods解析出来是空的。原因请求头不完整尤其是缺Cookie或Referer被识别为非浏览器请求。解决从浏览器开发者工具里复制完整的请求头重点补上Cookie和Referer并确保User-Agent是真实浏览器串。如果还是不行降低抓取频率加长页间延时。5.2 价格字段入库报错或精度丢失现象入库时抛InvalidOperation或者价格显示成 19.899999。原因一是价格字符串里带了¥或空格没清理干净二是模型用了FloatField。解决入库前用replace(¥, ).strip()清洗模型字段改成DecimalField转换时用Decimal()而不是float()。5.3 同一商品重复入库现象数据库里同一个商品出现多条记录。原因没用goods_id做唯一约束或者用了create而不是update_or_create。解决给goods_id加uniqueTrue入库统一走update_or_create。如果已经有一堆重复数据先写个脚本按goods_id分组去重。5.4 页面改版导致选择器失效现象之前能跑某天开始解析全空。原因目标页面结构调整CSS 选择器对不上了。解决把选择器集中写在utils.py顶部改版时只改一处解析时用try/except包住每个字段单个失败不影响整体定期手动跑一次验证。5.5 抓取频率过高触发限制现象跑着跑着请求全部失败或返回异常页面。原因请求间隔太短被判定为异常流量。解决页间延时拉到 2 到 4 秒单次重试延时 1 到 3 秒控制单次抓取页数别一次性抓几十页。毕设演示抓几页够用没必要贪多。6. 进阶技巧把比价数据用出花来跑通基础链路后这套系统还有不少可以深挖的地方。第一个是历史价格走势前面提到update_or_create会覆盖价格要做走势就得单独建一张PriceHistory表每次抓取插一条记录前端用折线图展示。这个改动不大但答辩时是个亮点。class PriceHistory(models.Model): goods models.ForeignKey(Goods, on_deletemodels.CASCADE) price models.DecimalField(max_digits10, decimal_places2) record_time models.DateTimeField(auto_now_addTrue)每次save_goods时顺手插一条历史记录查询时按goods分组按时间排序即可。第二个是抓取结果的校验。我一般会加一个简单的合理性检查价格大于 0 且小于某个上限比如 100000标题长度大于 5不符合的直接丢弃。这样能过滤掉解析错位产生的脏数据。校验项规则处理价格范围0 price 100000超出则丢弃标题长度len(title) 5过短则丢弃goods_id非空且为数字为空则丢弃第三个是给抓取加日志。别只用print用 Python 的logging模块把每次抓取的页数、成功条数、失败原因记下来出问题时翻日志比猜快得多。import logging logger logging.getLogger(spider) logger.info(抓取关键词%s 页数%s 入库%s, keyword, pages, len(items))从那以后我每次改完解析逻辑都会先手动跑一遍小批量抓取确认字段对得上再挂定时任务绝不直接上生产。这套系统本身不复杂难的是把每个环节的边界摸清楚。希望帮到你。本文还有配套的精品资源点击获取

相关新闻

手把手拆解极大似然法.zip:从似然函数到模拟验证

手把手拆解极大似然法.zip:从似然函数到模拟验证

简介:面向系统辨识与参数估计学习者,资源以极大似然法(MLE)与递归极大似然法(RML)为核心,系统讲解如何依据系统输入输出数据构建和在线修正动态模型,解决实际工程中难以直接建模的参…

2026/10/9 13:24:11 阅读更多 →
Java继承与抽象类:super/this、接口选型及模板方法实战

Java继承与抽象类:super/this、接口选型及模板方法实战

如果你不是零基础,也建议别跳过这一天——至少花20分钟把这四个东西串成一条线再走。很多干了两年的人,写抽象类还是一脸懵,一问到"为什么这个类不能new",就开始支支吾吾。原因就是当初这一章迷迷糊糊过去的。1. 继承到…

2026/10/9 13:24:11 阅读更多 →
J2SE基础入门:面向对象、反射与Eclipse实战避坑指南

J2SE基础入门:面向对象、反射与Eclipse实战避坑指南

1. 为什么 J2SE 是 Java 工程师绕不开的第一道坎很多人刚接触 Java 的时候,第一反应是去搜“Java 怎么快速上手”“Java 面试题背哪些”,然后一头扎进框架里,结果连String和StringBuilder的区别都说不清楚。我见过太多这样的案例:…

2026/10/9 13:24:11 阅读更多 →

最新新闻

计算机毕设项目4:基于springboot+uniapp自习室预约小程序(含AI智能预约+候补转正+座位AI协商)

计算机毕设项目4:基于springboot+uniapp自习室预约小程序(含AI智能预约+候补转正+座位AI协商)

所有项目已经整理完毕,后续的还在整理。更多项目,请联系我。 更多项目可以看:2026全新计算机毕设选题(小众,含创新点)-CSDN博客 所有成品和定制,均先免费部署,不需要定jin&#xff…

2026/10/9 14:04:07 阅读更多 →
高中数学集合与函数:定义域优先与分类讨论核心指南

高中数学集合与函数:定义域优先与分类讨论核心指南

1. 为什么“集合与函数”是高中数学的第一道分水岭如果你问一个刚带完高三毕业班的数学老师,高中数学哪一章最容易让学生“翻车”,十有八九会告诉你:不是导数,不是圆锥曲线,而是开学第一个月学的集合与函数。这听起来有…

2026/10/9 14:04:06 阅读更多 →
MyDAC 源码包实战:Delphi 连接 MySQL 的编译、分层与避坑指南

MyDAC 源码包实战:Delphi 连接 MySQL 的编译、分层与避坑指南

简介:这份资源是 MyDAC v5.00.1.7 的完整源码包,面向使用 Delphi、CBuilder 或 Kylix 开发 MySQL 数据库应用的工程师。MyDAC 组件库支持直连 MySQL 服务器或通过客户端库通信,可作为标准 MySQL 连接方案与 BDE 的高效替代,帮助开…

2026/10/9 14:04:06 阅读更多 →
从压缩包到可运行项目:解压、依赖与启动的完整指南

从压缩包到可运行项目:解压、依赖与启动的完整指南

简介:一套基于Spring Boot实现的企业微信对接示例,面向需要接入企业微信消息接口的后端开发人员,重点解决消息接收与自动回复场景中的接口验签、XML解析和响应封装问题。资源共152个文件,其中以99个xml配置与样例文件为主&#xf…

2026/10/9 14:04:06 阅读更多 →
DependenciesGui 在 Windows 10 上的依赖分析与排查实战

DependenciesGui 在 Windows 10 上的依赖分析与排查实战

简介:DependenciesGui-windows10-depends 是一款面向 Windows 10 用户的依赖关系分析工具,适合需要排查程序加载失败、DLL 缺失或版本冲突问题的普通用户与开发者。解压后得到 Releasex64 目录,双击 DependenciesGui.exe 即可启动图形界面&am…

2026/10/9 14:04:06 阅读更多 →
Python二手车价格预测实战:从数据清洗到LightGBM模型调参完整链路

Python二手车价格预测实战:从数据清洗到LightGBM模型调参完整链路

简介:这份资源面向Python课程设计、期末大作业及数据挖掘入门学习者,围绕二手车价格预测这一典型回归任务,提供从数据清洗、特征工程到模型训练与评估的完整实现方案,帮助读者快速理解数据挖掘项目的整体流程与落地方式。压缩包共…

2026/10/9 14:03:05 阅读更多 →

日新闻

Java时间API实战:LocalDate、Date与ZonedDateTime的转换与避坑指南

Java时间API实战:LocalDate、Date与ZonedDateTime的转换与避坑指南

Java时间API这个话题,隔三差五就会在群里被翻出来讨论一次。上周还有个同事线上处理一个订单超时问题,排查到最后发现是ZonedDateTime序列化后时区丢了,用户在下单当天晚上看到的时间整整差了8个小时。这类问题几乎每个做Java开发的人都遇到过…

2026/10/9 0:00:49 阅读更多 →
EasyTier实践:从NAT穿透到子网代理的异地组网部署与排错

EasyTier实践:从NAT穿透到子网代理的异地组网部署与排错

前几个月我手头有好几台机器需要互相访问:办公室台式机、家里 NAS、还有一台云主机。如果只是偶尔传个文件倒还好,问题是工作场景经常要在几处环境之间来回切换,每次都先登录跳板机再层层代理,实在折腾。我先后试过端口映射、自建…

2026/10/9 0:00:49 阅读更多 →
AI Agent工程实战:从七要素到七个决策点的系统设计指南

AI Agent工程实战:从七要素到七个决策点的系统设计指南

AI Agent 这个词在过去一年里被反复提及,但真正动手搭过一套能跑起来的 Agent 系统的人都知道,从"知道它是什么"到"让它稳定干活"之间隔着一整套工程决策。我前后参与过几个 Agent 项目的落地,从最初用现成框架拼装&…

2026/10/9 0:01:50 阅读更多 →

周新闻

KT148A语音芯片外挂8002D功放的工程实践指南

KT148A语音芯片外挂8002D功放的工程实践指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:32 阅读更多 →
LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:40 阅读更多 →
ARM架构深度解析:从RISC设计理念到交叉编译实战

ARM架构深度解析:从RISC设计理念到交叉编译实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 10:11:06 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 21:13:17 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:17 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 6:17:20 阅读更多 →