如何在Django中爬取网页数据自动存入PostgreSQL及解决配置报错
配置报错解决方案
该报错的核心是直接运行独立脚本时未初始化Django运行环境,框架无法读取项目配置参数,可通过两种方式解决:
方法1:脚本开头手动加载Django环境
在你的tasks.py最开头添加初始化代码即可:
import os import django # 替换为你实际项目的settings路径,如项目名为movie_project则写movie_project.settings os.environ.setdefault('DJANGO_SETTINGS_MODULE', '你的项目名.settings') django.setup() # 初始化完成后再导入模型和其他依赖,注意导入模型要写全app路径 from 你的app名.models import Movies from bs4 import BeautifulSoup import requests
方法2(更推荐):使用Django自定义命令运行
该方式符合Django开发规范,无需手动加载配置,适配后续定时执行等场景:
- 在你的app目录下创建层级目录
management/commands,两个目录下都要新增空的__init__.py文件 - 在commands目录下新建
scrape_movies.py,写入以下内容:
from django.core.management.base import BaseCommand from 你的app名.models import Movies from bs4 import BeautifulSoup import requests class Command(BaseCommand): def handle(self, *args, **options): url = '你的爬取目标地址' # 增加超时配置避免请求挂起 r = requests.get(url, timeout=10).text soup = BeautifulSoup(r, 'lxml') title = soup.find('a', class_='movie_name') year = soup.find('span', class_='year') rating = soup.find('p', class_='rate') # 非空判断避免解析失败报错 if all([title, year, rating]): Movies.objects.create( title=title.text.strip(), year=int(year.text.strip().strip('()')), rating=float(rating.text.strip()) ) self.stdout.write(self.style.SUCCESS('爬取任务执行完成'))
- 运行时直接执行命令:
python manage.py scrape_movies即可自动加载Django环境运行。
爬取入库优化方案
- 首先修正模型定义:
IntegerField、FloatField不需要max_length参数,原有写法冗余,同时建议调整字段长度避免内容截断、增加唯一约束防重复:
from django.db import models class Movies(models.Model): title = models.CharField(max_length=100, unique=True) year = models.IntegerField() rating = models.FloatField()
- 增加防重复逻辑:爬取到数据后先判断是否已存在,避免重复入库,推荐用
get_or_create方法:
Movies.objects.get_or_create( title=title.text.strip(), defaults={ 'year': int(year.text.strip().strip('()')), 'rating': float(rating.text.strip()) } )
- 增加异常捕获:分别处理请求异常、解析异常、数据格式异常、入库异常,避免单条数据失败导致整个脚本终止。
- 反爬优化:请求时增加User-Agent请求头,批量爬取时增加随机延时,避免被站点封禁。
- 定时爬取:如需定期更新数据,可配置系统crontab定时执行上述自定义Django命令即可。
内容的提问来源于stack exchange,提问作者Aryan Hab
相关产品推荐
相关产品推荐

