django scrapy交互简单实例

本文介绍了一个基于Django和Scrapy的租房信息爬虫项目,该爬虫能够从365租房网站抓取房源信息,并将数据保存至数据库中,最后通过Django展示在前端页面上。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

多页爬取365租房

任务:爬取下图红色内容并展示出来。
在这里插入图片描述
在这里插入图片描述

分析

django+scrapy交互执行爬取数据,思想:
1.利用scrapy爬取的数据,
2.保存到django关联的数据库里
3.用django从数据库提取出来前台展示

交互设置:

指定一个项目路径 way

在way路径下:

I.django项目创建

2.scrapy框架创建

3.自定义一个静态文件夹static

在这里插入图片描述
rent:指定的way路径
c_rent:scrapy框架项目
d_rent:django项目子应用
rent:django项目主应用
static:静态文件夹
templates:模板文件夹

4.配置设置
django配置设置:
在这里插入图片描述
django函数模板模板设置
在这里插入图片描述
django静态文件设置

scrapy配置设置:
在scrapy设置里加入下面代码

import os
import sys
import django
sys.path.append(os.path.dirname(os.path.abspath('.')))   #获取到路径
os.environ['DJANGO_SETTINGS_MODULE'] = 'rent.settings'
										#rent为django项目名字
django.setup()

下面的配置自动生成需要注释打开,简单修改即可

ROBOTSTXT_OBEY = False   #不限制访问
#UA
USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36'  
#管道解开,管道才能接受到内容
ITEM_PIPELINES = {
   'c_rent.pipelines.CRentPipeline': 300,
}

django准备工作代码

model文件创建表

from django.db import models
class Rent(models.Model):
    z_d_title=models.CharField(max_length=50,verbose_name='大标题')
    z_d_img=models.CharField(max_length=255,verbose_name='主页图片')
    z_d_name=models.CharField(max_length=30,verbose_name='简写名称')
    d_price=models.CharField(max_length=50,verbose_name='价格')
    d_spare=models.CharField(max_length=50,verbose_name='面积')
    d_style=models.CharField(max_length=50,verbose_name='装修样式')
    d_room=models.CharField(max_length=255,verbose_name='布局')
    d_height=models.CharField(max_length=30,verbose_name='楼层')
    d_date=models.CharField(max_length=50,verbose_name='日期')
    d_img=models.CharField(max_length=255,verbose_name='详情图片')

scrapy代码

爬虫文件:

import scrapy #导入框架
from urllib import request  #导入请求
from ..items import CRentItem  #导入item的类

class FangSpider(scrapy.Spider):
    name = 'fang'   #爬虫名
    allowed_domains = ['sh.rent.house365.com']  #域名
    start_urls = ['http://sh.rent.house365.com/']  #起始访问的url

    #请求详情地址
    def parse(self, response):
        res=response.xpath('//dd[@class="listItem clearfix"]')
        for i in res:
            item=CRentItem()  #实例化Item类,一定要放在循环之下,否则会出现数据库的数据未按
            d_url=i.xpath('.//h3[@class="name"]/a/@href').extract_first() #详情地址
            yield scrapy.Request(url=d_url,callback=self.detail,meta={'item':item})
            #回调掉详情页,一次次返回数据,并将item对象存储在meta中,让它进行传递。
        url='http://sh.rent.house365.com/district/dl_p{}.html'
        #多页请求
        for j in range(2,11):
            new_url=url.format(j)
            yield scrapy.Request(url=new_url,callback=self.parse)
            #回调自身函数
    #解析首页及详情内容
    def detail(self,response):
        item=response.meta['item']  #取出item,类似字典,为数据库字段赋值做准备
        title=response.xpath('//h1[@class="h2"]/text()').extract_first()  #大标题
        price=response.xpath('//dd[@class="info"]/span/text()').extract_first() #价格
        b_image=response.xpath('//img[@id="picture"]/@src').extract_first() #大图
        spare=response.xpath('//dd[@class="info"]/text()').extract()[1] #面积
        style=response.xpath('//dd[@class="info"]/text()').extract()[2]  #装修样式
        room=response.xpath('//dd[@class="info"]/text()').extract()[4]  #布局
        height=''.join(response.xpath('//dl[@class="item"]/text()').extract()).strip() #楼层
        #. join():连接字符串数组。将字符串、元组、列表中的元素以指定的字符(分隔符)连接生成一个新的字符串

        #楼层取出来有很多\n的空白,需要用join()函数使用空字符把它消除掉
        s_title=response.xpath('//dd[@class="info"]/text()').extract()[7]  #简写名称
        date=response.xpath('//div[@class="time"]/text()').extract_first()  #日期
        s_img=response.xpath('//img[@class="small"]/@src').extract() #详情图片

       #数据库表字段赋值(保证item里的键和数据库的字段名一致)
        item['z_d_title']=title
        item['z_d_img']=b_image
        item['z_d_name']=s_title
        item['d_price']=price
        item['d_spare']=spare
        item['d_style']=style
        item['d_room']=room
        item['d_height']=height
        item['d_date']=date
        item['z_d_img']=b_image
        item['d_img']=s_img
        yield item 						#返回数据存到tem返回给管道

item文件代码

from scrapy_djangoitem import DjangoItem   #导入django交互Item
from d_rent.models import Rent  #导入表名

class CRentItem(DjangoItem):      #继承Djangoitem搭建交互
    django_model =Rent   #交互只当给表

pipelines文件代码

import json
from urllib import request
class CRentPipeline(object):
打开函数
    def open_spider(self,spider):
        self.f=open('rent.json','a',encoding='utf-8')
处理数据
    def process_item(self, item, spider):
    	#写入json文件
        self.f.write(json.dumps(dict(item),ensure_ascii=False,indent=4)+',\n')
		
        # 下载主页图片保存到一个自定义的文件夹
        # 重新找一个要保存的图片名字
        b_image = item['z_d_img']
        b = b_image.split('/')[-1]
        item['z_d_img'] = b  # 给数据库图片赋值新名称b
        request.urlretrieve(url=b_image, filename='../static/img/{}'.format(b))
        # 将要保存的图片的名字赋值给静态文件下的图片的名称,保证与数据库一一对应

        # 下载详情页图片保存到一个自定义的文件夹
        s_img=item['d_img']
        list = []
        for i in s_img:
            j = i.split('/')[-1]
            request.urlretrieve(url=i, filename='../static/images/{}'.format(j))
            list.append(j)
        item['d_img'] = list
        # 因为详情页图片是多张,所以用一个字段接收时,将它保存在数据库里,是一个列表,但也要保证图片名字
        # 与静态文件下图片名字一致
        item.save()     #最后讲数据保存到数据库,然后用django从数据库中取数据展示
        return item  #必须return了item,管道的下一个item才能进入1管道继续操作

关闭函数
        def close_spider(self,spider):
            self.f.close()
    #open_spider函数和close_spider函数时自定义写的,注意名字必须这样写,而且spider参数必须写

django展示前台

业务层函数逻辑处理

from django.shortcuts import render
from d_rent.models import Rent
#首页
def index(request):
    all_data=Rent.objects.all()
    return render(request,'index.html',locals())
   					 #传到模板进行遍历即可
#详情页
def detail(request):
    id=request.GET.get('id')
    one=Rent.objects.filter(id=id).first()
    #这个d_img字段存储的是一个列表所以,先把这个列表找出来然后再对它进行遍历
    two=one.d_img #获取到详情字段的图片对象
    t=q=eval(two) #使用eval()函数转成列表,然后在模板中遍历展示
    return render(request,'show.html',locals())
    #虽然它们有详情,但是它们属于一个表,因为只是进行一张表的尾部追加的思想,
    #让他们通过详情获取的数据,在添加到对应的表的记录里就好了。

模板展示使用了bootstrap,方便使用,这里就不聊了,因为我也是菜鸟,而且时扣脚的那种,挺好用的,推荐大家使用!
小白记录,请多多指教。

### 整合 DjangoScrapy 实现网页抓取 在现代 Python Web 开发中,Django 是一个流行的全栈框架,而 Scrapy 则专注于高效的数据提取。两者结合能够创建强大的数据采集应用。 #### 创建 Django 项目并配置环境 首先,在目标环境中安装必要的包: ```bash pip install django scrapy ``` 接着初始化一个新的 Django 项目以及应用程序: ```bash django-admin startproject myproject cd myproject python manage.py startapp scraper_app ``` 确保 `scraper_app` 已经被加入到项目的设置文件 (`settings.py`) 中的应用列表里。 #### 构建 Scrapy 爬虫 在同一目录下建立新的 Scrapy 项目结构而不是默认位置,以便更好地管理依赖关系和服务发现路径: ```bash scrapy startproject crawler . ``` 调整 `crawler/settings.py` 来指定自定义项存储管道,并引入 Django 设置模块: ```python import os import sys sys.path.append(os.path.join(os.path.dirname(__file__), "..")) os.environ['DJANGO_SETTINGS_MODULE'] = 'myproject.settings' # 导入 Django 模型和其他资源前必须执行此操作 import django django.setup() ITEM_PIPELINES = { 'crawler.pipelines.CrawlerPipeline': 300, } ``` #### 设计爬虫逻辑与模型交互 编写具体的 Spider 类来描述要访问的目标网站及其解析规则;同时设计 Pipeline 处理函数用于保存获取的信息至数据库表单内。由于 Scrapy 默认运行于异步模式之下,当涉及到同步 API 如 Django ORM 查询时,则需借助 Twisted 提供的帮助方法——即通过装饰器 `@sync_to_async` 将其转换成协程形式[^1]。 下面给出一段简单的例子说明如何利用上述技术完成从页面读取新闻标题的任务并将它们存入对应的记录之中: ```python from twisted.internet import defer, threads from asgiref.sync import sync_to_async class CrawlerPipeline: @defer.inlineCallbacks def process_item(self, item, spider): yield threads.deferToThread( self._process_item_sync, item=item, spider=spider ) def _process_item_sync(self, item, spider): model_instance = MyModel(title=item.get('title')) # 使用 sync_to_async 调用同步的 Django ORM 方法 loop = asyncio.new_event_loop() asyncio.set_event_loop(loop) result = loop.run_until_complete(sync_to_async(model_instance.save)()) return item ``` 这里假设存在名为 `MyModel` 的 Django 数据库映射类负责持久化所收集的内容片段。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值