ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

基于Python+Django的京东商品比价系统:从爬虫到Web应用的全栈实践

基于Python+Django的京东商品比价系统:从爬虫到Web应用的全栈实践 简介网络爬虫作为自动化数据采集的核心技术其原理在于模拟浏览器行为向目标网站发送HTTP请求并解析返回的HTML文档从而高效提取结构化信息。这项技术在现代数据驱动决策中价值显著尤其在电商领域通过实时抓取商品价格、库存及评价数据为消费者提供精准的比价服务辅助其做出更经济的购物选择。Django框架以其“开箱即用”的特性为快速构建此类数据驱动的Web应用提供了强大支持其内置的ORM、Admin后台和MTV模式极大地简化了从数据处理到前端展示的开发流程。本系统正是这一技术组合的典型应用它利用Python爬虫抓取京东商品信息通过Django构建比价平台实现了商品搜索、价格对比与历史追踪等功能为开发者提供了一个涵盖数据采集、处理与可视化展示的完整全栈项目范例。1. 项目概述一个能帮你省钱的毕业设计最近几年带“毕业设计”字眼的项目源码在网上特别火尤其是那些结合了热门技术栈和实用场景的。今天要聊的这个“基于PythonDjango的京东商品比价系统”就是一个典型代表。乍一看标题你可能觉得这又是一个学生为了应付毕设搞出来的“玩具”。但说实话这个选题背后藏着不少真东西它巧妙地串联了Python爬虫、Web开发、数据分析和一个几乎人人都有的痛点——怎么买东西更便宜。简单来说这个系统就是一个自动化的“价格侦察兵”。它的核心工作流程是你输入一个想买的商品名称比如“iPhone 15”系统会模拟用户行为去京东网站上搜索这个商品把不同店铺、不同规格颜色、内存版本的商品信息包括价格、店铺名称、促销活动、评价数量等一股脑儿抓取下来。然后它把这些数据清洗、整理在一个简洁的网页上展示出来让你一眼就能看出哪个链接卖得最便宜哪个店铺有优惠券哪个是自营店。对于学生而言这是一个绝佳的练手项目因为它覆盖了软件工程从数据获取、处理到展示的全流程对于普通用户这甚至是一个可以自己部署、为自己服务的实用工具。为什么这个选题值得深挖首先技术栈选得准。Python是当下数据处理和自动化脚本的“头号语言”生态丰富学习资料遍地都是。Django作为Python界最负盛名的“全家桶”式Web框架以功能全面、文档清晰、开发效率高著称非常适合用来快速构建一个结构清晰、带后台管理的数据驱动型网站。用它们俩来做一个比价系统技术路径非常成熟。其次需求真实。在电商促销套路层出不穷的今天“货比三家”是刚需。最后作为毕业设计它难度适中但“五脏俱全”涉及前端展示、后端逻辑、数据库设计、网络爬虫、定时任务等多个模块能充分体现学生的综合能力。接下来我就以一个过来人的视角拆解一下这个系统的里里外外聊聊怎么把它从一份源码变成一个真正能跑起来、甚至有优化空间的个人项目。2. 核心需求与功能模块拆解拿到一个项目源码包第一步不是急着运行而是先理解它到底要干什么以及是怎么分块干的。这个比价系统我们可以从用户和开发者两个角度来拆解它的核心需求。2.1 用户视角我需要一个什么样的比价工具站在使用者的角度这个系统的需求非常直观搜索商品我需要一个搜索框输入我想买的东西比如“华为MateBook 14”。查看结果搜索后我希望看到一个清晰的列表列出京东上所有相关的商品。每条信息至少应该包括商品主图、标题、价格、店铺名称、是否是京东自营、商品详情页链接。排序与筛选面对几十上百个结果我需要能按价格从低到高排序这样最便宜的就排在最前面。最好还能筛选“仅看自营”或者“仅看有货”。价格追踪对于我特别关注的商品比如准备等降价再买的显卡我希望系统能定期比如每天自动刷新它的价格并记录历史价格变化生成一个价格走势图让我知道现在是不是入手的好时机。这些需求映射到产品功能上就构成了系统的前端界面和核心交互。2.2 开发者视角系统由哪些技术模块构成为了实现上述功能从开发实现层面系统需要分解成以下几个关键模块数据采集模块爬虫这是系统的“眼睛”和“手”。它负责模拟浏览器访问京东网站发送搜索请求解析返回的网页HTML代码从中提取出我们需要的商品信息价格、标题等。这个模块的技术核心是网络请求库如requests和HTML解析库如BeautifulSoup、lxml或parsel。考虑到京东的反爬机制如请求头校验、IP频率限制一个健壮的爬虫还需要处理User-Agent轮换、IP代理、请求延时等问题。数据处理与存储模块爬虫抓回来的是原始、杂乱的文本数据。这个模块负责清洗数据比如去除价格字符串中的“”符号将其转为浮点数统一标题格式并将结构化后的数据保存起来。这里就会用到数据库。Django默认集成了SQLite对于毕业设计或小规模使用完全足够。我们需要设计数据库模型Model比如Product表存商品基本信息PriceHistory表存每个商品的历史价格记录。Web应用模块Django核心这是系统的大脑和面孔。它负责处理用户的HTTP请求。视图Views接收用户搜索请求调用爬虫模块获取数据或者从数据库查询数据然后渲染模板返回给用户。模板TemplatesHTML页面用于展示商品列表、价格走势图。可能会用到简单的JavaScript如jQuery来实现前端排序或图表渲染用ECharts或Chart.js。路由URLs定义哪个URL由哪个视图函数来处理。后台管理AdminDjango自带的神器可以让你通过一个Web界面轻松管理数据库里的商品和价格数据非常适合项目演示和日常维护。任务调度模块可选但推荐为了实现价格追踪我们需要定期执行爬虫任务。这不能靠手动刷新网页。成熟的方案是引入定时任务。在Django中可以借助django-crontab或更强大的CeleryRedis来实现。比如设置一个每天凌晨2点运行的任务自动爬取已关注商品的最新价格并存入PriceHistory表。注意在动手写爬虫之前务必深入研究目标网站京东的robots.txt文件和相关服务条款。对于个人学习、小规模、低频次的抓取通常风险较低但一定要遵守规则设置合理的请求间隔如每请求一次休眠2-5秒避免对对方服务器造成压力。这是做爬虫项目必须有的伦理和法律意识。3. 技术栈深度解析与工具选型一个项目的骨架是它的功能模块而血肉则是具体的技术选型。为什么这个项目用PythonDjango是黄金组合我们来看看每个技术点的选型理由和实操要点。3.1 为什么是Python不仅仅是“简单”Python成为这个项目首选绝不仅仅因为它语法简洁。其核心优势在于庞大的生态系统为每一个环节都提供了现成的、好用的“轮子”。爬虫环节requests库让发送HTTP请求变得像访问字典一样简单。BeautifulSoup或lxml提供了强大的HTML/XML解析能力可以用类似CSS选择器的方式精准定位页面元素提取价格和标题。对于更复杂的、动态加载Ajax的页面可能需要Selenium或Playwright来模拟真实浏览器操作但京东的商品搜索列表页通常是静态或服务端渲染用requestsBeautifulSoup组合大多能搞定。数据处理环节pandas虽然在这个小项目中可能用不上但如果你需要对历史价格数据进行复杂分析比如计算平均降价周期它就是神器。Python内建的json、re正则表达式模块对于处理API返回数据或清洗文本不可或缺。环境与依赖管理pip是Python的包管理器。使用requirements.txt文件来记录项目所有依赖包及其版本是项目可复现的基石。一个规范的源码包根目录下一定会有一个这个文件。3.2 Django框架快速搭建Web应用的“瑞士军刀”Django遵循“MTV”Model-Template-View模式与经典的MVC异曲同工。它的“开箱即用”特性能让你省去大量造轮子的时间。ORM对象关系映射这是Django的一大亮点。你不需要写复杂的SQL语句用Python类就能定义数据表Model用类方法就能进行增删改查。例如定义商品模型# models.py from django.db import models class Product(models.Model): name models.CharField(max_length255, verbose_name商品名称) price models.DecimalField(max_digits10, decimal_places2, verbose_name当前价格) shop models.CharField(max_length100, verbose_name店铺名称) is_self_operated models.BooleanField(defaultFalse, verbose_name是否自营) product_url models.URLField(verbose_name商品链接) created_at models.DateTimeField(auto_now_addTrue) updated_at models.DateTimeField(auto_nowTrue) def __str__(self): return self.name这样在视图里你就可以用Product.objects.filter(name__contains“手机”).order_by(‘price’)这样的语句来查询和排序Django会自动帮你生成并执行对应的SQL。Admin后台只需在admin.py中简单注册你的模型一个功能完备的数据管理后台就生成了。这对于毕业设计演示和项目初期数据维护来说效率极高。表单与验证Django提供了强大的表单类能轻松处理用户输入的搜索关键词并进行安全验证和清洗。安全性Django内置了CSRF防护、SQL注入防护、XSS防护等众多安全机制对于新手开发者而言这意味着很多安全坑已经被默认填上了。3.3 前端展示轻量级与实用性的平衡作为毕业设计前端通常不是重点但良好的展示能极大提升项目质感。模板语言Django有自己的模板语言DTL它允许你在HTML中嵌入动态变量和简单的逻辑。比如在商品列表页循环展示商品!-- product_list.html -- {% for product in products %} div classproduct-item h3a href{{ product.product_url }} target_blank{{ product.name }}/a/h3 p价格span classprice¥{{ product.price }}/span/p p店铺{{ product.shop }} {% if product.is_self_operated %}span classbadge自营/span{% endif %}/p /div {% endfor %}CSS框架为了快速得到一个美观的界面强烈推荐使用Bootstrap。它提供了现成的网格系统、按钮、卡片、表格样式你只需要给HTML元素加上对应的class就能获得一个响应式、看起来挺专业的页面。把Bootstrap的CSS和JS文件通过CDN引入几乎零成本。简单交互对于排序、筛选这类操作有两种实现方式。一是提交表单后端处理后再刷新页面简单但体验一般。二是用jQuery发起Ajax请求后端返回JSON数据前端JavaScript动态更新页面体验更流畅。对于毕设第一种方式完全足够且更易于理解和实现。3.4 数据持久化SQLite还是MySQLDjango默认使用SQLite它是一个文件数据库无需安装单独的服务非常适合开发、测试和小型应用。对于毕业设计这个量级SQLite是首选因为它让项目部署变得极其简单——你只需要把整个项目文件夹拷贝到服务器上就行。 但是如果你预计要爬取和存储海量商品的历史价格数据比如数万条记录或者需要进行更复杂的联表查询那么可以考虑换用MySQL或PostgreSQL。它们性能更强更适合生产环境。在Django中切换数据库基本上只需要修改settings.py中的DATABASES配置即可ORM层的代码几乎不用动这就是Django ORM的威力。4. 核心实现步骤与代码剖析理解了架构和选型我们进入实战环节看看一个最简化的比价系统是如何一步步构建起来的。我会以关键代码片段为例解释其背后的逻辑。4.1 第一步搭建Django项目骨架首先确保你的环境已安装Python3.8以上版本和pip。然后通过pip安装Django。# 安装Django pip install django # 创建项目项目名假设为 jd_price_comparison django-admin startproject jd_price_comparison cd jd_price_comparison # 创建应用一个应用代表一个功能模块比如叫 price_crawler python manage.py startapp price_crawler创建应用后别忘了在项目settings.py文件的INSTALLED_APPS列表里添加‘price_crawler’。4.2 第二步设计数据模型Models在price_crawler/models.py中定义我们的核心模型。除了之前提到的Product我们还需要一个PriceHistory来记录价格变化。from django.db import models class Product(models.Model): # 商品唯一标识可以用京东的商品IDSKU sku_id models.CharField(max_length50, uniqueTrue, verbose_name商品ID) name models.CharField(max_length500, verbose_name商品名称) # 京东商品标题可能很长 image_url models.URLField(blankTrue, verbose_name图片链接) detail_url models.URLField(verbose_name详情页链接) shop_name models.CharField(max_length200, verbose_name店铺名称) is_self_operated models.BooleanField(defaultFalse, verbose_name京东自营) # 当前价格用于快速展示 current_price models.DecimalField(max_digits10, decimal_places2, verbose_name当前价格) # 其他可能需要的字段好评率、评论数、促销信息等 created_at models.DateTimeField(auto_now_addTrue) updated_at models.DateTimeField(auto_nowTrue) class Meta: ordering [‘-updated_at’] # 默认按更新时间倒序排列 def __str__(self): return f{self.name} ({self.sku_id}) class PriceHistory(models.Model): product models.ForeignKey(Product, on_deletemodels.CASCADE, related_name‘price_history’) price models.DecimalField(max_digits10, decimal_places2, verbose_name价格) created_at models.DateTimeField(auto_now_addTrue) # 记录价格的时间点 class Meta: ordering [‘created_at’] verbose_name_plural ‘价格历史’ def __str__(self): return f{self.product.name} - ¥{self.price} at {self.created_at}定义好模型后运行python manage.py makemigrations和python manage.py migrate命令Django就会在SQLite数据库中创建对应的数据表。4.3 第三步编写爬虫核心逻辑在price_crawler目录下新建一个文件crawler.py这里封装爬取逻辑。import requests import re from bs4 import BeautifulSoup import time import random from .models import Product, PriceHistory class JDCrawler: def __init__(self): self.headers { ‘User-Agent’: ‘Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 ...‘, ‘Referer’: ‘https://www.jd.com/‘, } self.search_url_template “https://search.jd.com/Search?keyword{}encutf-8” def get_search_page(self, keyword, page1): 获取搜索页HTML内容 url self.search_url_template.format(keyword) # 添加分页参数京东搜索页分页逻辑较复杂有时需要结合‘page‘和‘s‘参数这里做简化 if page 1: url f“page{page}” try: # 添加随机延时模拟真人操作避免被封IP time.sleep(random.uniform(1, 3)) resp requests.get(url, headersself.headers, timeout10) resp.raise_for_status() # 检查请求是否成功 resp.encoding ‘utf-8’ return resp.text except requests.RequestException as e: print(f“请求失败: {e}”) return None def parse_search_page(self, html): 解析搜索页提取商品列表 if not html: return [] soup BeautifulSoup(html, ‘lxml’) # 京东搜索页的商品列表通常放在id为‘J_goodsList’的ul标签里li的class包含‘gl-item’ items soup.select(‘#J_goodsList .gl-item’) product_list [] for item in items: try: # 提取商品ID (SKU) sku item.get(‘data-sku’) or item.get(‘sku’) if not sku: continue # 提取商品名称 name_elem item.select_one(‘.p-name em’) name name_elem.get_text(stripTrue) if name_elem else ‘’ # 提取价格 - 注意京东搜索页的价格可能是动态加载的这里可能抓不到。 # 更可靠的方法是抓取后再通过商品ID去请求价格接口。 price_elem item.select_one(‘.p-price i’) price float(price_elem.get_text(stripTrue)) if price_elem else 0.0 # 提取店铺 shop_elem item.select_one(‘.p-shop’) shop shop_elem.get_text(stripTrue) if shop_elem else ‘’ # 判断是否自营通常店铺名包含‘京东自营’或有一个特殊标识 is_self ‘京东自营’ in shop or item.select_one(‘.p-icons .J-im-icon’) is not None # 商品详情页链接 link_elem item.select_one(‘.p-img a’) detail_url ‘https:’ link_elem[‘href’] if link_elem and link_elem.get(‘href’) else ‘’ # 图片链接 img_elem item.select_one(‘.p-img img’) img_url img_elem.get(‘data-lazy-img’) or img_elem.get(‘src’) if img_elem else ‘’ if img_url and not img_url.startswith(‘http’): img_url ‘https:’ img_url product_list.append({ ‘sku_id’: sku, ‘name’: name, ‘current_price’: price, ‘shop_name’: shop, ‘is_self_operated’: is_self, ‘detail_url’: detail_url, ‘image_url’: img_url, }) except Exception as e: print(f“解析商品条目时出错: {e}”) continue return product_list def crawl_and_save(self, keyword): 主爬取函数爬取关键词并保存到数据库 print(f“开始爬取关键词: {keyword}”) html self.get_search_page(keyword) products_data self.parse_search_page(html) for p_data in products_data: # 使用update_or_create如果商品已存在则更新价格否则创建新记录 product, created Product.objects.update_or_create( sku_idp_data[‘sku_id’], defaults{ ‘name’: p_data[‘name’], ‘current_price’: p_data[‘current_price’], ‘shop_name’: p_data[‘shop_name’], ‘is_self_operated’: p_data[‘is_self_operated’], ‘detail_url’: p_data[‘detail_url’], ‘image_url’: p_data[‘image_url’], } ) # 无论新旧都创建一条价格历史记录 PriceHistory.objects.create(productproduct, pricep_data[‘current_price’]) status “新增” if created else “更新” print(f“{status}商品: {product.name}价格: ¥{product.current_price}”) print(f“关键词 ‘{keyword}’ 爬取完成共处理{len(products_data)}条商品。”)实操心得京东的页面结构可能会变化select语句中使用的CSS选择器需要根据实际情况调整。最稳妥的方法是打开京东搜索页使用浏览器的“开发者工具”F12查看商品列表的HTML结构。另外搜索页显示的价格可能是静态的或需要JS加载上述代码可能抓不到实时价格。更专业的做法是抓取商品IDSKU后再去请求京东的一个内部价格API通过浏览器网络请求分析获得但这涉及更复杂的逆向工程作为毕设用页面上的价格做演示已经足够。4.4 第四步创建视图与模板首先在price_crawler/views.py中编写处理搜索和展示的视图。from django.shortcuts import render from django.http import JsonResponse from .crawler import JDCrawler from .models import Product def search_view(request): 处理搜索请求 if request.method ‘GET’: keyword request.GET.get(‘q’, ‘’).strip() if keyword: # 调用爬虫这里为了演示直接同步调用。实际应考虑异步任务避免请求超时 crawler JDCrawler() crawler.crawl_and_save(keyword) # 从数据库获取刚爬取的商品 products Product.objects.filter(name__icontainskeyword).order_by(‘current_price’) else: products Product.objects.none() return render(request, ‘price_crawler/search_results.html’, {‘products’: products, ‘keyword’: keyword}) return render(request, ‘price_crawler/search.html’) def product_list_view(request): 商品列表页展示所有已爬取的商品 products Product.objects.all().order_by(‘-updated_at’) return render(request, ‘price_crawler/product_list.html’, {‘products’: products})然后配置URL路由。在price_crawler目录下创建urls.pyfrom django.urls import path from . import views urlpatterns [ path(‘search/’, views.search_view, name‘search’), path(‘list/’, views.product_list_view, name‘product_list’), ]在项目主urls.py中包含它from django.contrib import admin from django.urls import path, include urlpatterns [ path(‘admin/’, admin.site.urls), path(‘’, include(‘price_crawler.urls’)), ]最后创建模板文件。在price_crawler下新建templates/price_crawler/目录然后创建search_results.html!DOCTYPE html html lang“zh-CN” head meta charset“UTF-8” meta name“viewport” content“widthdevice-width, initial-scale1.0” title京东比价 - 搜索结果/title link href“https://cdn.jsdelivr.net/npm/bootstrap5.1.3/dist/css/bootstrap.min.css” rel“stylesheet” /head body div class“container mt-4” h2搜索关键词: “{{ keyword }}”/h2 a href“{% url ‘search’ %}” class“btn btn-secondary mb-3”返回搜索/a {% if products %} div class“table-responsive” table class“table table-hover table-striped” thead tr th scope“col”图片/th th scope“col”商品名称/th th scope“col”价格/th th scope“col”店铺/th th scope“col”自营/th th scope“col”操作/th /tr /thead tbody {% for product in products %} tr tdimg src“{{ product.image_url }}” alt“{{ product.name }}” style“max-height: 60px;” onerror“this.style.display‘none’”/td tda href“{{ product.detail_url }}” target“_blank”{{ product.name|truncatechars:80 }}/a/td td class“fw-bold text-danger”¥{{ product.current_price }}/td td{{ product.shop_name|truncatechars:20 }}/td td{% if product.is_self_operated %}span class“badge bg-success”是/span{% else %}span class“badge bg-secondary”否/span{% endif %}/td tda href“#” class“btn btn-sm btn-outline-primary” onclick“trackPrice(‘{{ product.sku_id }}’)“关注/a/td /tr {% endfor %} /tbody /table /div {% else %} div class“alert alert-info”未找到相关商品或尚未爬取数据。/div {% endif %} /div script src“https://cdn.jsdelivr.net/npm/bootstrap5.1.3/dist/js/bootstrap.bundle.min.js”/script script function trackPrice(skuId) { alert(‘关注功能SKU: ’ skuId ‘需后端配合定时任务实现。此处为前端演示。’); // 实际应发送Ajax请求到后端将商品加入监控列表 } /script /body /html4.5 第五步启用Admin后台并创建超级用户Django Admin是快速管理数据的利器。在price_crawler/admin.py中注册模型from django.contrib import admin from .models import Product, PriceHistory class PriceHistoryInline(admin.TabularInline): # 内联显示方便在商品页面直接看价格历史 model PriceHistory extra 0 readonly_fields (‘created_at’,) admin.register(Product) class ProductAdmin(admin.ModelAdmin): list_display (‘name’, ‘current_price’, ‘shop_name’, ‘is_self_operated’, ‘updated_at’) list_filter (‘is_self_operated’, ‘shop_name’) search_fields (‘name’, ‘sku_id’) inlines [PriceHistoryInline] admin.register(PriceHistory) class PriceHistoryAdmin(admin.ModelAdmin): list_display (‘product’, ‘price’, ‘created_at’) list_filter (‘created_at’,) date_hierarchy ‘created_at’然后创建超级用户运行python manage.py createsuperuser按提示输入用户名、邮箱和密码。运行开发服务器python manage.py runserver访问http://127.0.0.1:8000/admin/即可登录后台管理所有数据。5. 部署、优化与问题排查一个能在本地跑起来的系统只是第一步。要让别人也能访问或者让它长期稳定运行还需要考虑部署和优化。5.1 简易部署方案以Linux服务器为例对于毕业设计演示或个人使用部署到一台云服务器是最佳选择。准备服务器购买一台最低配置的云服务器如1核1G安装Ubuntu系统。上传代码通过Git或SFTP工具将你的Django项目代码上传到服务器。安装环境在服务器上安装Python、pip、虚拟环境virtualenv。sudo apt update sudo apt install python3-pip python3-venv cd /path/to/your/project python3 -m venv venv source venv/bin/activate pip install -r requirements.txt # 安装项目依赖配置生产设置修改settings.py关闭调试模式DEBUG False设置允许访问的域名ALLOWED_HOSTS [‘你的服务器IP或域名’]。静态文件收集python manage.py collectstatic。使用WSGI服务器开发服务器runserver不适合生产。使用Gunicorn作为WSGI服务器。pip install gunicorn gunicorn --workers 3 your_project_name.wsgi:application搭配Nginx用Nginx作为反向代理处理静态文件并转发动态请求给Gunicorn。配置Nginx站点文件指向你的项目静态文件目录和Gunicorn socket。进程管理使用Supervisor来管理Gunicorn进程确保应用崩溃后能自动重启。5.2 性能与反爬优化策略爬虫优化请求头伪装成主流浏览器包含完整的User-Agent、Referer、Accept-Language等。代理IP池如果频繁抓取触发IP限制需要考虑使用代理IP。有免费和付费的代理IP服务但免费的质量不稳定。降低频率在爬虫代码的请求间加入随机延时time.sleep(random.uniform(2, 5))这是最基本的道德和规避反爬的措施。错误重试使用tenacity或retrying库为请求添加重试机制应对网络波动。异步爬取对于大量商品可以使用aiohttpasyncio进行异步IO爬取极大提升效率但代码复杂度会增加。数据库优化建立索引对经常用于查询和排序的字段建立数据库索引如Product表的name、current_price、updated_at字段。在Django模型中可以通过db_indexTrue参数设置。分页查询商品列表一定要做分页使用Django内置的Paginator类避免一次性加载海量数据。前端优化异步加载将搜索和价格监控改为Ajax请求提升用户体验。价格图表使用轻量级的图表库如Chart.js在商品详情页展示其价格历史曲线。5.3 常见问题与排查实录在开发和运行这个系统的过程中你几乎一定会遇到下面这些问题爬虫抓不到数据或数据错乱现象爬虫运行后product_list为空或者提取的字段全是错的。排查检查网络请求首先打印resp.status_code和resp.text的前几百字符看请求是否成功返回的HTML是否正常。验证选择器京东的页面结构可能已更新。用浏览器开发者工具重新检查商品列表、价格、标题等元素对应的CSS选择器路径。处理动态内容如果价格是JS动态加载的在resp.text里就找不到。需要分析网络请求找到真正的数据接口通常是返回JSON的XHR请求然后直接请求那个接口。解决更新parse_search_page方法中的CSS选择器。对于动态数据改用requests直接调用找到的API接口并注意携带必要的请求参数和头信息如cookies。Django报错TemplateDoesNotExist现象访问页面时Django报错找不到模板。排查检查settings.py中TEMPLATES的DIRS设置以及你的模板文件是否放在了正确的路径下app_name/templates/app_name/。解决确保项目结构正确并在INSTALLED_APPS中注册了你的应用。数据库操作错误IntegrityError(UNIQUE constraint failed)现象在保存商品时提示唯一约束失败。排查这通常是因为你试图插入sku_id重复的商品。update_or_create方法应该能处理这种情况检查它的逻辑是否正确或者是否有其他地方直接调用了Product.objects.create()。解决确保所有保存商品的地方都使用update_or_create或者先查询是否存在再决定是更新还是创建。部署后静态文件CSS, JS, 图片404现象网站能访问但样式全无浏览器控制台显示静态文件404。排查Django在生产环境不处理静态文件。检查settings.py中的STATIC_URL和STATIC_ROOT以及Nginx配置中是否正确指向了STATIC_ROOT目录。解决正确运行collectstatic命令并在Nginx配置中添加location /static/块指向收集后的静态文件目录。定时任务不执行现象配置了django-crontab但任务没有按计划运行。排查首先确认是否将django-crontab添加到了INSTALLED_APPS并运行了python manage.py crontab add将任务添加到系统的crontab。在Linux上可以用crontab -l查看当前用户的任务列表。解决确保Django项目在cron任务执行时的环境变量尤其是Python路径是正确的。一个常见做法是在cron命令中先切换到项目目录并激活虚拟环境再执行Django管理命令。例如0 2 * * * cd /path/to/your/project /path/to/venv/bin/python manage.py runcrons这个基于PythonDjango的京东商品比价系统从学习角度看它是一条贯穿多个核心知识点的绝佳实践路径从实用角度看它孵化出了一个能解决实际问题的工具原型。在实现过程中你会深刻体会到从数据获取到最终呈现的完整闭环也会遇到并解决各种典型的开发问题。无论是为了完成一份出色的毕业设计还是作为个人技能提升的练手项目它都极具价值。最后记得在遵守规则的前提下进行技术探索让技术服务于生活而不是带来麻烦。本文还有配套的精品资源点击获取
返回列表