Django集成爬虫如何实现?

访客 全栈框架 2

Django集成爬虫实战:从零搭建数据采集与Web展示系统

目录导读

  1. Django与爬虫集成核心价值
  2. 环境搭建与项目初始化
  3. 爬虫模块设计与数据模型
  4. 爬虫调度与任务管理
  5. Web界面展示与交互
  6. 常见问题与解决方案(Q&A)

Django与爬虫集成核心价值

Django作为Python最流行的Web框架,与爬虫技术结合能快速构建数据采集、清洗、存储和展示的完整闭环,这种架构特别适合需要定时抓取竞品数据、监控网站变化、或者构建垂直搜索引擎的场景,相比单独使用Scrapy或Requests,Django提供ORM、Admin后台、模板引擎和认证系统,让数据管理变得异常高效。

环境搭建与项目初始化

首先确保安装Python 3.8+,然后创建虚拟环境:

pip install django scrapy requests beautifulsoup4 celery redis
django-admin startproject DataHub
cd DataHub
django-admin startapp spider_manager

模型设计(在spider_manager/models.py中):

from django.db import models
class Task(models.Model):
    name = models.CharField(max_length=200)
    target_url = models.URLField()
    status = models.CharField(max_length=20, choices=[
        ('pending', '待执行'),
        ('running', '运行中'),
        ('completed', '已完成'),
        ('failed', '失败'),
    ], default='pending')
    created_at = models.DateTimeField(auto_now_add=True)
class DataItem(models.Model):
    task = models.ForeignKey(Task, on_delete=models.CASCADE)= models.CharField(max_length=500)
    content = models.TextField()
    source_url = models.URLField()
    fetched_at = models.DateTimeField(auto_now_add=True)

爬虫模块设计与数据模型

集成Scrapy的方式有两种:直接集成Scrapy引擎,或用Requests+BeautifulSoup轻量实现,对于简单场景推荐后者。

爬虫核心模块spider_manager/crawler.py):

import requests
from bs4 import BeautifulSoup
from .models import DataItem, Task
class SimpleCrawler:
    def __init__(self, task):
        self.task = task
    def fetch_data(self):
        try:
            response = requests.get(self.task.target_url, timeout=10)
            response.encoding = 'utf-8'
            soup = BeautifulSoup(response.text, 'html.parser')
            # 示例:抓取文章标题和正文
            for article in soup.select('article'):
                DataItem.objects.create(
                    task=self.task,
                    title=article.find('h2').text.strip(),
                    content=article.find('div', class_='content').text.strip(),
                    source_url=article.find('a')['href']
                )
            self.task.status = 'completed'
            self.task.save()
        except Exception as e:
            self.task.status = 'failed'
            self.task.save()
            raise e

爬虫调度与任务管理

使用Celery+Redis实现异步任务调度,避免爬虫阻塞Web服务:

配置CeleryDataHub/celery.py):

from celery import Celery
import os
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'DataHub.settings')
app = Celery('DataHub')
app.config_from_object('django.conf:settings', namespace='CELERY')
app.autodiscover_tasks()

异步任务spider_manager/tasks.py):

from celery import shared_task
from .crawler import SimpleCrawler
from .models import Task
@shared_task
def execute_crawl(task_id):
    task = Task.objects.get(id=task_id)
    crawler = SimpleCrawler(task)
    crawler.fetch_data()

定时任务配置settings.py):

from celery.schedules import crontab
CELERY_BEAT_SCHEDULE = {
    'daily_crawl': {
        'task': 'spider_manager.tasks.execute_crawl',
        'schedule': crontab(hour=6, minute=0),
        'args': (1,),  # 传递Task ID
    },
}

Web界面展示与交互

视图函数spider_manager/views.py):

from django.shortcuts import render
from .models import DataItem, Task
from .tasks import execute_crawl
def home(request):
    items = DataItem.objects.select_related('task').all()[:50]
    tasks = Task.objects.all()
    return render(request, 'index.html', {'items': items, 'tasks': tasks})
def trigger_crawl(request, task_id):
    execute_crawl.delay(task_id)
    return JsonResponse({'status': 'started'})

模板示例templates/index.html):

<div class="container">
    <h2>数据看板</h2>
    <div class="task-list">
        {% for task in tasks %}
        <div class="task-card">
            <h3>{{ task.name }}</h3>
            <span class="status-{{ task.status }}">{{ task.status }}</span>
            <button onclick="startCrawl({{ task.id }})">执行采集</button>
        </div>
        {% endfor %}
    </div>
    <table>
        <thead>
            <tr><th>标题</th><th>来源</th><th>采集时间</th></tr>
        </thead>
        <tbody>
            {% for item in items %}
            <tr>
                <td>{{ item.title }}</td>
                <td>{{ item.source_url|truncatechars:30 }}</td>
                <td>{{ item.fetched_at }}</td>
            </tr>
            {% endfor %}
        </tbody>
    </table>
</div>

常见问题与解决方案(Q&A)

Q1:爬虫运行时Django页面卡顿怎么办?
A:使用Celery异步执行爬虫任务,Web进程和Worker进程分离,生产环境建议设置CELERY_WORKER_CONCURRENCY=4限制并发,同时添加爬虫运行状态监控。

Q2:如何防止爬虫被目标网站屏蔽?
A:实施以下策略:

  • 随机User-Agent:使用fake-useragent
  • 请求间隔:每次请求后time.sleep(random.uniform(2,5))
  • 代理IP轮换:集成免费代理池(如ProxyBroker)
  • 使用Scrapy的RetryMiddleware自动重试失败请求

Q3:抓取大量数据时数据库写入慢怎么优化?
A:使用Django ORM的bulk_create()批量插入,或者改用Elasticsearch作为存储后端,读取时使用only()方法限制字段加载,避免查询所有字段。

Q4:如何定时自动运行爬虫?
A:配合Celery Beat实现定时任务,在settings.py中配置CELERY_BEAT_SCHEDULE字典,也可以使用系统Crontab每分钟调用manage.py命令触发爬虫。

Q5:爬虫结果如何实时推送到前端?
A:使用Django Channels实现WebSocket通信,当爬虫完成一条数据时,通过Channel Layer推送到指定前端页面,对于轻量场景,可轮询后台状态API(每5秒检查爬虫进度状态)。


通过以上方法,Django成功承担了爬虫的调度、数据存储和展示功能,完整的集成方案还包括异常日志记录(建议集成Sentry)、数据去重(使用Redis布隆过滤器)以及爬虫可视化监控(可用Grafana+Prometheus),对于企业级应用,可将爬虫拆分为独立微服务,通过REST API与Django主站通信,进一步提高系统稳定性。

标签: Django爬虫

抱歉,评论功能暂时关闭!