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,
}
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='详情图片')
爬虫文件:
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参数必须写
业务层函数逻辑处理
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,方便使用,这里就不聊了,因为我也是菜鸟,而且时扣脚的那种,挺好用的,推荐大家使用!
小白记录,请多多指教。