django scrapy交互简单实例

多页爬取365租房

任务:爬取下图红色内容并展示出来。
django scrapy交互简单实例_第1张图片
django scrapy交互简单实例_第2张图片

分析

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

交互设置:

指定一个项目路径 way

在way路径下:

I.django项目创建

2.scrapy框架创建

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

django scrapy交互简单实例_第3张图片
rent:指定的way路径
c_rent:scrapy框架项目
d_rent:django项目子应用
rent:django项目主应用
static:静态文件夹
templates:模板文件夹

4.配置设置
django配置设置:
django scrapy交互简单实例_第4张图片
django函数模板模板设置
django scrapy交互简单实例_第5张图片
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,方便使用,这里就不聊了,因为我也是菜鸟,而且时扣脚的那种,挺好用的,推荐大家使用!
小白记录,请多多指教。

你可能感兴趣的:(爬虫)