天天看點

采用Django網站架構, 結合Scrapy架構,ElasticSearch,建構搜尋系統目的解析源代碼可到微信公衆号"一團追夢喵"回複"Django搜尋"擷取

目的解析

在Django網站架構下,建立Scrapy爬蟲架構,擷取豆瓣電影Top250的資料,将資料儲存到mysql資料庫中,最後連結ElasticSearch搜尋,将資訊導入到其中,實作可以在前端頁面搜尋資料。

建立Django網站

本文在pycharm中直接建立(我的項目名為Top250)

采用Django網站架構, 結合Scrapy架構,ElasticSearch,建構搜尋系統目的解析源代碼可到微信公衆号"一團追夢喵"回複"Django搜尋"擷取

建立完項目,建立app,打開terminal 輸入指令

采用Django網站架構, 結合Scrapy架構,ElasticSearch,建構搜尋系統目的解析源代碼可到微信公衆号"一團追夢喵"回複"Django搜尋"擷取
python manage.py startapp 子產品的名字(我的是douban_test)
           

我這邊Django的版本是3.2.13,運作的時候報錯os,隻需要在setting中import os 即可

采用Django網站架構, 結合Scrapy架構,ElasticSearch,建構搜尋系統目的解析源代碼可到微信公衆号"一團追夢喵"回複"Django搜尋"擷取
采用Django網站架構, 結合Scrapy架構,ElasticSearch,建構搜尋系統目的解析源代碼可到微信公衆号"一團追夢喵"回複"Django搜尋"擷取

建立app之後,在setting的installled_apps中加入新建立的app名字

采用Django網站架構, 結合Scrapy架構,ElasticSearch,建構搜尋系統目的解析源代碼可到微信公衆号"一團追夢喵"回複"Django搜尋"擷取

啟動Django,點選右上角的運作按鈕即可

采用Django網站架構, 結合Scrapy架構,ElasticSearch,建構搜尋系統目的解析源代碼可到微信公衆号"一團追夢喵"回複"Django搜尋"擷取

在浏覽器輸入127.0.0.1:8000,顯示如下,即運作成功

采用Django網站架構, 結合Scrapy架構,ElasticSearch,建構搜尋系統目的解析源代碼可到微信公衆号"一團追夢喵"回複"Django搜尋"擷取

Django的運作順序是從項目的urls.py轉到app的urls.py再到views.py,然後到顯示html

我們開始設定在douban_test的目錄中建立檔案urls.py

from douban_test import views
from django.urls import path
app_name = 'douban_test'  #此處改成自己的app名字 

urlpatterns = [
    path('', views.IndexView.as_view()),

]
           
采用Django網站架構, 結合Scrapy架構,ElasticSearch,建構搜尋系統目的解析源代碼可到微信公衆号"一團追夢喵"回複"Django搜尋"擷取

将項目的urls.py與app(即douban_test)的urls.py連接配接起來,在項目的urls.py中設定

path('', include('douban_test.urls')),
path('search/', include('haystack.urls')),
           
采用Django網站架構, 結合Scrapy架構,ElasticSearch,建構搜尋系統目的解析源代碼可到微信公衆号"一團追夢喵"回複"Django搜尋"擷取

接着進入douban_te的views.py中

from django.shortcuts import render
# Create your views here.
from django.views import View

class IndexView(View):     #注意此時的類名,應與urls.py中path('', views.IndexView.as_view()),的IndexView一緻,并且繼				  承于View
    def get(self,request):
        return render(request, 'index.html')
           
采用Django網站架構, 結合Scrapy架構,ElasticSearch,建構搜尋系統目的解析源代碼可到微信公衆号"一團追夢喵"回複"Django搜尋"擷取

接着在項目的根目錄下建立templates

采用Django網站架構, 結合Scrapy架構,ElasticSearch,建構搜尋系統目的解析源代碼可到微信公衆号"一團追夢喵"回複"Django搜尋"擷取

在templates中建立新的html檔案,html檔案的命名方式與views.py中的index.html一緻

采用Django網站架構, 結合Scrapy架構,ElasticSearch,建構搜尋系統目的解析源代碼可到微信公衆号"一團追夢喵"回複"Django搜尋"擷取

在html裡,我們寫個簡單的搜尋框

<!DOCTYPE html>
<html >
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form role="search" method="get" id="searchform" action="{% url 'haystack_search' %}"> # 此處的haystack_search下面會用到,為的是連結ElasticSearch
  <input type="search" name="q" placeholder="搜尋" required>
  <button type="submit">送出<span class="ion-ios-search-strong"></span></button>
</form>

</body>
</html>

           

此時,Django的基礎基礎設定結束,還有資料庫表,

在Django的setting中連接配接mysql

#資料庫配置
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'novel_test',
        'USER':'root',
        'PASSWORD':'123456',
        'HOST':'localhost',
        'PORT':3306
    }
}

           

我們分析豆瓣 電影 top250資料中的 ‘名字’ ,‘評分’ , ‘簡介 ’, ‘主演’。我們編寫models.py

from django.db import models

# Create your models here.


class Top(models.Model):
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=100)
    grade = models.CharField(max_length=100)
    introduction = models.CharField(max_length=1000)
    role = models.CharField(max_length=1000)

    def __str__(self):
        return self.name

           

接着進行資料庫表的遷移

python manage.py makemigrations
python manage.py migrate

           

設定Scrapy

采用Django網站架構, 結合Scrapy架構,ElasticSearch,建構搜尋系統目的解析源代碼可到微信公衆号"一團追夢喵"回複"Django搜尋"擷取

在 項目根目錄下的terminal中輸入

pip install scrapy
           

安裝完成後,還是在根目錄下的terminal

scrapy startproject Top250_spider
cd Top250_spider
scrapy genspider douban_spider movie.douban.com  #scrapy genspider 爬蟲項目名 爬蟲網址(後面能改)
           

結構如下

采用Django網站架構, 結合Scrapy架構,ElasticSearch,建構搜尋系統目的解析源代碼可到微信公衆号"一團追夢喵"回複"Django搜尋"擷取

接下來對Scrapy中的setting設定,連接配接到django中,setting中加入以下代碼

import os
import sys
sys.path.append(os.path.dirname(os.path.abspath('.')))
os.environ['DJANGO_SETTINGS_MODULE'] = 'django_scrapy_test.settings'    # 項目名.settings
import django
django.setup()
           

将setting中的機器人協定

采用Django網站架構, 結合Scrapy架構,ElasticSearch,建構搜尋系統目的解析源代碼可到微信公衆号"一團追夢喵"回複"Django搜尋"擷取

改為False

接着,我們在douban_spider.py中開始對豆瓣top250電影代碼進行編寫

import scrapy
from douban_test.models import Top

class DoubanSpiderSpider(scrapy.Spider):
    name = 'douban_spider'
    allowed_domains = ['movie.douban.com']
    start_urls = ['http://movie.douban.com/top250']

    def parse(self, response):

        nodelist = response.xpath('//div[@class="info"]')
        for node in nodelist:
            list = {}
            list['name'] = node.xpath("./div[1]/a/span[1]/text()")[0].extract()
            list['grade'] = node.xpath("./div[2]/div[1]/span[2]/text()")[0].extract()
            list['introduction'] = ''.join(node.xpath("./div[2]/p[2]/span/text()").extract())
            list['role'] = node.xpath("./div[2]/p[1]/text()")[0].extract().strip()
            Top.objects.create(name=list['name'],grade=list['grade'],introduction=list['introduction'],role=list['role'])
            yield list

        nextpage = response.xpath('//span[@class="next"]/a/@href').extract()

        # print(new_url)
        if nextpage:
            new_url = 'http://movie.douban.com/top250' + nextpage[0]
            yield scrapy.Request(url=new_url,callback=self.parse)
           

在top250_spider 裡的items.py

from scrapy_djangoitem import DjangoItem
import douban_test as t

class Top250SpiderItem(DjangoItem):

    django_model = t.Top

           

在pipelines.py

from .models.es_types import ArticleIndex


class Top250SpiderPipeline:
    def process_item(self, item, spider):

		item.save(0

           

在這裡可以先運作爬蟲,看看資料是否已經儲存到MySQL中

scrapy crawl douban_spider (爬蟲名)
           

我們可以看到已經成功爬到資料庫中

采用Django網站架構, 結合Scrapy架構,ElasticSearch,建構搜尋系統目的解析源代碼可到微信公衆号"一團追夢喵"回複"Django搜尋"擷取

設定ElasticSearch

接着需要在電腦上安裝ElasticSearch,建議自行搜尋,然後我們在項目裡安裝elasticsearch_dsl

pip in stall elasticsearch_dsl
           

需要注意安裝的ElasticSearch與這個插件elasticsearch_dsl版本需要一緻,比如

# Elasticsearch 7.x
elasticsearch-dsl>=7.0.0,<8.0.0
 
# Elasticsearch 6.x
elasticsearch-dsl>=6.0.0,<7.0.0
 
# Elasticsearch 5.x
elasticsearch-dsl>=5.0.0,<6.0.0
 
# Elasticsearch 2.x
elasticsearch-dsl>=2.0.0,<3.0.0
           

在項目models下建立es_types.py檔案,在檔案中建立索引mapping

# -*- coding: utf-8 -*-

from elasticsearch_dsl import Document, Keyword, Text, Integer
from elasticsearch_dsl.connections import connections

connections.create_connection(hosts=["localhost"])


class ArticleIndex(Document):
    id = Integer()
    name = Keyword()
    grade = Integer()
    introduction = Text(analyzer="ik_max_word")
    role = Text(analyzer="ik_max_word")

    class Index:
        name = "boge1"
        doc_type = "article"
           
采用Django網站架構, 結合Scrapy架構,ElasticSearch,建構搜尋系統目的解析源代碼可到微信公衆号"一團追夢喵"回複"Django搜尋"擷取

運作es_types.py檔案,需要先開啟elasticsearch服務

回到elasticsearch-head可視化頁面,可以看到成功生成索引

采用Django網站架構, 結合Scrapy架構,ElasticSearch,建構搜尋系統目的解析源代碼可到微信公衆号"一團追夢喵"回複"Django搜尋"擷取

在pipelines檔案中定義管道類ElasticsearchPipeline将資料寫入到es中

from .models.es_types import ArticleIndex


class Top250SpiderPipeline:
    def process_item(self, item, spider):

        article = ArticleIndex()
        article.id = item['id']
        article.name = item['name']
        article.grade = item['grade']
        article.introduction = item['introduction']
        article.role = item['role']

        article.save()
        return item

           
采用Django網站架構, 結合Scrapy架構,ElasticSearch,建構搜尋系統目的解析源代碼可到微信公衆号"一團追夢喵"回複"Django搜尋"擷取

接着,使用安裝djangohaystack來搭建搜尋系統,連結到django中

# 安裝djangohaystack
pip install django-haystack
           

接着在django的setting裡加入應用

采用Django網站架構, 結合Scrapy架構,ElasticSearch,建構搜尋系統目的解析源代碼可到微信公衆号"一團追夢喵"回複"Django搜尋"擷取

在配置檔案中配置Haystack為搜尋引擎後端

# 在配置檔案中配置Haystack為搜尋引擎後端
HAYSTACK_CONNECTIONS = {
    'default': {
    'ENGINE': 'haystack.backends.elasticsearch7_backend.Elasticsearch7SearchEngine', #前面的Elasticsearch7SearchEngine裡的 7 對應着你的elasticsearch的版本
    'URL': 'http://127.0.0.1:9200/', # Elasticsearch伺服器ip位址,端口号固定為9200
    'INDEX_NAME': 'boge', # Elasticsearch建立的索引庫的名稱
 	},
}
# 當添加、修改、删除資料時,自動生成索引,保證了在Django運作起來後,
# 有新的資料産生時,Haystack仍然可以讓Elasticsearch實時生成新資料的索引
HAYSTACK_SIGNAL_PROCESSOR = 'haystack.signals.RealtimeSignalProcessor'
# haystack分頁
HAYSTACK_SEARCH_RESULTS_PER_PAGE = 6
           

在Django app的檔案裡建立search_indexes.py檔案

采用Django網站架構, 結合Scrapy架構,ElasticSearch,建構搜尋系統目的解析源代碼可到微信公衆号"一團追夢喵"回複"Django搜尋"擷取
from haystack import indexes
from .models import Top

class NewsIndex(indexes.SearchIndex, indexes.Indexable):# 這裡的類名也是固定的,索引的模型名+Index,繼承也是固定的
	"""
	 
       這個模型的作用類似于django的模型,它告訴haystack哪些資料會被
       放進查詢傳回的模型對象中,以及通過哪些字段進行索引和查詢
    
	"""
# 這字段必須這麼寫,用來告訴haystack和搜尋引擎要索引哪些字段
	text = indexes.CharField(document=True, use_template=True)
# 模型字段,打包資料
	id = indexes.CharField(model_attr='id')
	name = indexes.CharField(model_attr='name')
	grade = indexes.CharField(model_attr='grade')
	introduction = indexes.CharField(model_attr='introduction')
	role = indexes.CharField(model_attr='role')


	def get_model(self):
		"""
		傳回建立索引的模型
		:return:
		"""
		return Top


	def index_queryset(self, using=None):
		"""
		傳回要建立索引的資料查詢集
		:param using:
		:return:
		"""
		# 這種寫法遵從官方文檔的指引
		return self.get_model().objects.filter()
           

根據上面建立的模型中的第一個text字段中的use_template=True參數,還需要建立一個索引資料模闆,用來告訴搜尋引擎需要索引哪些字段。

在templates中建立檔案search/indexes//_text.txt,

采用Django網站架構, 結合Scrapy架構,ElasticSearch,建構搜尋系統目的解析源代碼可到微信公衆号"一團追夢喵"回複"Django搜尋"擷取
~$ python manage.py rebuild_index	# 看到如下類似資訊,說明運作成功
WARNING: This will irreparably remove EVERYTHING from your search index in connection 'default'.
Your choices after this are to restore from backups or rebuild via the `rebuild_index` command.
Are you sure you wish to continue? [y/N] y
Removing all documents from your index because you said so.
All documents removed.
Indexing 889 新聞文章
GET /tzpython/_mapping [status:404 request:0.005s]

           

接着運作Django架構,搜尋結果如下所示

采用Django網站架構, 結合Scrapy架構,ElasticSearch,建構搜尋系統目的解析源代碼可到微信公衆号"一團追夢喵"回複"Django搜尋"擷取
采用Django網站架構, 結合Scrapy架構,ElasticSearch,建構搜尋系統目的解析源代碼可到微信公衆号"一團追夢喵"回複"Django搜尋"擷取

源代碼可到微信公衆号"一團追夢喵"回複"Django搜尋"擷取