You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django爬虫项目页面加载过慢的优化方案及实现咨询

解决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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 11:08:15