Django爬虫项目页面加载过慢的优化方案及实现咨询
嘿,我来帮你搞定这个页面加载慢的困扰!你的思路非常对——把爬取到的数据存入数据库,后台定时自动更新,这样用户访问页面时就不用每次都等待第三方网站的响应了。下面我一步步给你讲具体实现方法,还有几个适合新手的额外优化方案:
一、创建Model存储爬取的数据
首先,在你的Django app的models.py里创建一个模型,用来保存爬取到的疫情数据,还可以加一个更新时间字段方便追踪最新数据:
from django.db import models class CoronavirusStats(models.Model): cases = models.CharField(max_length=20) deaths = models.CharField(max_length=20) recovered = models.CharField(max_length=20) updated_at = models.DateTimeField(auto_now=True) class Meta: get_latest_by = 'updated_at' # 方便快速获取最新记录 def __str__(self): return f"Stats updated at {self.updated_at}"
写完后别忘了执行迁移命令:
python manage.py makemigrations python manage.py migrate
二、编写数据更新函数
把你原来的getNums函数改造一下,让它爬取数据后更新数据库里的记录:
from bs4 import BeautifulSoup import requests from .models import CoronavirusStats def update_coronavirus_stats(): url = "https://www.worldometers.info/coronavirus/" try: response = requests.get(url, timeout=10) response.raise_for_status() # 捕获请求异常 soup = BeautifulSoup(response.text, "html.parser") number_containers = soup.select(".maincounter-number") # 提取数据 cases = number_containers[0].find("span").decode_contents().strip() deaths = number_containers[1].find("span").decode_contents().strip() recovered = number_containers[2].find("span").decode_contents().strip() # 更新或创建记录 stats, created = CoronavirusStats.objects.update_or_create( defaults={ 'cases': cases, 'deaths': deaths, 'recovered': recovered } ) return True except Exception as e: print(f"更新数据失败: {e}") return False
三、后台定时执行更新任务
我们可以用Django自定义命令+系统定时任务的方式,让这个更新函数自动运行。
1. 创建自定义Django命令
在你的app目录下创建如下结构的文件:
your_app/ ├── management/ │ ├── __init__.py │ └── commands/ │ ├── __init__.py │ └── update_coronavirus_stats.py
然后在update_coronavirus_stats.py里写命令逻辑:
from django.core.management.base import BaseCommand from ..utils import update_coronavirus_stats # 替换成你函数的实际路径 class Command(BaseCommand): help = '更新冠状病毒统计数据' def handle(self, *args, **options): success = update_coronavirus_stats() if success: self.stdout.write(self.style.SUCCESS('数据更新成功!')) else: self.stdout.write(self.style.ERROR('数据更新失败,请检查日志。'))
现在你可以手动运行这个命令测试:
python manage.py update_coronavirus_stats
2. 设置系统定时任务
Linux/macOS:用
crontab,输入crontab -e添加定时任务,比如每小时更新一次:0 * * * * /path/to/your/python /path/to/your/project/manage.py update_coronavirus_stats >> /var/log/coronavirus_update.log 2>&1注意替换成你自己的Python路径和项目路径。
Windows:用「任务计划程序」创建一个定时任务,执行
python manage.py update_coronavirus_stats命令。
四、修改视图函数从数据库取数据
现在把你的homeView改成从数据库获取最新数据,不用每次爬取:
from django.shortcuts import render from .models import CoronavirusStats from .utils import update_coronavirus_stats def homeView(request): try: # 获取最新的统计数据 stats = CoronavirusStats.objects.latest('updated_at') except CoronavirusStats.DoesNotExist: # 如果数据库还没有数据,手动爬取一次 update_coronavirus_stats() stats = CoronavirusStats.objects.latest('updated_at') context = { "cases": stats.cases, "deaths": stats.deaths, "recovered": stats.recovered, } return render(request, "home.html", context)
这样用户访问页面时,直接从数据库读取数据,加载速度会快很多!
额外优化方案(适合新手)
视图缓存:用Django的缓存框架把视图结果缓存起来,进一步提升速度。在
settings.py里配置缓存后,给视图加装饰器:from django.views.decorators.cache import cache_page @cache_page(60 * 15) # 缓存15分钟 def homeView(request): # 原视图逻辑异步加载数据:页面先渲染骨架,然后用AJAX异步请求数据并填充,让用户感觉页面加载更快。比如在
home.html里加一段简单的JS:<div id="stats-container"> <!-- 先显示加载提示 --> <p>加载中...</p> </div> <script> // 页面加载完成后异步获取数据 window.onload = function() { fetch('/get-stats/') // 需要新建一个API视图返回数据 .then(response => response.json()) .then(data => { document.getElementById('stats-container').innerHTML = ` <p>确诊: ${data.cases}</p> <p>死亡: ${data.deaths}</p> <p>康复: ${data.recovered}</p> `; }); }; </script>错误处理增强:爬取失败时,不要让用户看到错误页面,而是继续显示上次的有效数据,提升用户体验。
内容的提问来源于stack exchange,提问作者Owen Moogk

