Django集成爬虫实战:从零搭建数据采集与Web展示系统
目录导读
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服务:
配置Celery(DataHub/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爬虫