Spark机器学习实验
Spark機器學習實驗
- 一、出租車數據分析
- 1.數據處理
- 2.數據分析
- 2.1創建 DataFrame
- 2.2KMeans 聚類分析
- 3.百度地圖可視化
- 3.1申請地圖 key
- 3.2聚類結果可視化
- 二、圖書推薦系統
- 1.Django簡介
- 1.1.ORM 模型
- 1.2.Template 模板
- 1.3 View 視圖
- 2.Django 項目搭建
- 2.1 項目創建
- 2.2 視圖和 URL 配置
- 2.3 創建應用
- 2.4 創建模型
- 2.5 Admin 管理工具
- 3.推薦引擎設計
- 3.1導入數據
- 3.2訓練模型
- 3.3圖書推薦
- 4.系統設計與實現
- 4.1BootStrap介紹與使用
- 4.2Redis數據庫安裝與使用
- 4.3視圖與路由設計
- 4.4界面設計
- 5.Issue
- 6.參考文檔
- 三、轉載申明
一、出租車數據分析
出租車是我們經常乘坐的交通工具,但是經常會遇到打車難的問題,給我們生活和工作帶來諸多不便。本章介紹 Spark 在人們打車出行生活中的應用,該應用把某地區各出租車實時的并帶有地理坐標的 GPS(Global Positioning System)點作為分析對象,使用 Kmeans 聚類方法把出租車軌跡點按簇分類,通過該分類方法找到出租車出現密集的地方,并用地圖的方式進行可視化展示,為人們的出行提供新的思路。
本章主要內容如下。
(1)準備數據并對數據特點進行分析。
(2)從文本文件創建 Spark DataFrame。
(3)使用 Spark 的機器學習庫 Kmeans 進行聚類。
(4)使用百度地圖對聚類的結果進行可視化。
1.數據處理
一般情況下,在進行分析之前需要對數據的分布、狀態等有一個整體的了解,從而確定數據使用哪種方法進行分析,進而對數據進行預處理。本章使用文本數據,打開數據觀察發現,數據集合中存在缺失項或是 GPS 定位點坐標無效的情況,因此需要對此種情況進行處理。因為出租車點上傳的速率非??觳⑶颐芏却?#xff0c;所以可以把其中缺失和無效的數據進行刪除,對數據分析不會造成較大的影響。
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-QuzNjsmS-1623383617088)(images/image-20200519094316427.png)]
其中,tid:出租車編號;lat:緯度;lon:經度;time:時間戳;tid 的值相同表示相同的車在不同的時間所處的位置。
2.數據分析
在上一節整理的數據的基礎上,使用 Spark 從文本創建 DataFrame,并結合 Kmeans 機器學習聚類方法,實現對出租車在空間位置上的聚類。Kmeans 聚類可根據設定的聚類個數找出若干個聚類中心,對于出租車來講就是出租車經常出現位置點坐標。
2.1創建 DataFrame
from pyspark.sql import SparkSession from pyspark import SparkContext from pyspark.ml.linalg import Vectorssc = SparkContext("local[4]", "taxi") taxi_data = sc.textFile("datas/taxi.csv") taxi_rdd = taxi_data.map(lambda line: line.split(','))# 創建矢量 RDD,矢量的兩個參數分別為緯度和經度。下面的聚類函數需要 RDD 進行聚類。 taxi_row = taxi_rdd.map(lambda x: (Vectors.dense(x[1], x[2]),)) #顯示數據的前五行 print(taxi_row.collect()[:5]) sqlsc = SparkSession.builder.getOrCreate() taxi_df = sqlsc.createDataFrame(taxi_row, ["features"])2.2KMeans 聚類分析
KMeans 是最常用的聚類算法之一,它將數據點聚類成預定義的簇數。Spark MLlib 實現了包括一個并行化的 k-means++,稱為 kmeans||.。
from pyspark.ml.clustering import KMeans # 引入聚類包kmeans = KMeans(k=3, seed=1) # 聚成 3 類 model = kmeans.fit(taxi_df) # 注意,傳入的 DataFrame 是矢量名稱為 features 的集合 centers = model.clusterCenters() # 產生聚類集合 # 聚類的結果是一系列的點集,這些點集也就是出租車聚集的地區,上述代碼中將數據聚類成 3 類,如圖 9-2 所示。 print(centers)3.百度地圖可視化
通過 Spark 提供的 Kmeans 聚類方法已經找到了出租車聚集的地圖坐標,但是并不能清楚地看到具體的位置,因此需要通過可視化的方法把數據在地圖上進行展示。百度地圖是國內頂級的地圖服務提供商之一,在提供了基于位置服務的同時也提供了在不同平臺下的對外開放接口,允許用戶自定義地圖并根據相應業務邏輯開發自己的地理信息應用。本節利用百度地圖為開發者提供的第三方開發接口,并對聚類結果進行可視化,讓結果的展現更直接。
3.1申請地圖 key
在使用百度地圖接口之前需要,通過百度地圖的一個認證,用戶要在百度地圖開發平臺中申請一個密鑰 key。讀者可以登錄百度地圖官網,注冊個人賬號,然后選擇申請 key,申請界面如圖:
申請地址:http://lbsyun.baidu.com/
地圖Api控制臺:http://lbsyun.baidu.com/apiconsole/center#/home
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-xfsggRFk-1623383617089)(images/image-20200519102035742.png)]
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-I6iHEozU-1623383617090)(images/image-20200519102105847.png)]
3.2聚類結果可視化
html文件要在apache或者ngnix服務器中運行,因為百度地圖API中設置了白名單。
<!DOCTYPE html> <html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><meta name="viewport" content="initial-scale=1.0, user-scalable=no" /><style type="text/css">body,html,#allmap {width: 100%;height: 100%;overflow: hidden;margin: 0;font-family: "微軟雅黑";}</style><script type="text/javascript" src="http://api.map.baidu.com/api?v=2.0&ak=Dv4X6zApF1yzMQNFoEypNfLX"></script><title>Kmeans 聚類可視化</title> </head><body><div id="allmap"></div> </body></html> <script type="text/javascript">// 百度地圖API功能var map = new BMap.Map("allmap"); // 創建Map實例map.enableScrollWheelZoom(); // 允許滑輪進行放大縮小map.centerAndZoom(new BMap.Point(104.01741982, 30.67598985), 13);// 初始位置與范圍map.addControl(new BMap.NavigationControl());// 添加平移縮放控件map.addControl(new BMap.ScaleControl());// 添加比例尺控件var myP1 = new BMap.Point(104.01741982, 30.67598985); // 聲明點對象var myP2 = new BMap.Point(103.65063611, 30.89504347);var myP3 = new BMap.Point(104.07063581, 30.64562312);map.clearOverlays(); // 清空地圖中的對象var marker1 = new BMap.Marker(myP1); // 定義點樣式,默認為紅色水滴形狀var marker2 = new BMap.Marker(myP2);var marker3 = new BMap.Marker(myP3);map.addOverlay(marker1); // 添加點到地圖map.addOverlay(marker2);map.addOverlay(marker3); </script>[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-Lj3ygxcX-1623383617091)(images/image-20200519105430246.png)]
地圖
map.addOverlay(marker2);map.addOverlay(marker3); </script>[外鏈圖片轉存中…(img-Lj3ygxcX-1623383617091)]
二、圖書推薦系統
注意:在使用源代碼請把所有<% %>請替換為[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-oxpYEXA0-1623383822799)(images/image-20200529210559026.png)],為jekyll編譯的問題不能編譯通過生成Github Page.
1.Django簡介
參照Django菜鳥教程:https://www.runoob.com/django/django-tutorial.html
pip install django1.1.ORM 模型
對象關系映射 ORM(Object Relational Mapping)是一種在面向對象編程語言里實現不同類型系統數據之間轉換的程序技術。
class user(models.Model):#name 字段 max_length 為字段長度, default 為默認值name=model.CharFiled(max_length=50 , default=‘‘)email=model.EmailField()password=model.CharField(max_length=8 , default=‘‘)1.2.Template 模板
Django 的模板引擎為定義應用程序面向用戶的層提供了一種強大的迷你語言,使應用程序和前端邏輯分離。模板由 HTML 和模板語法關鍵詞組成,并不需要用到 Python 的知識。
Django 模板采用前端模塊化的思路,可以將模塊的前端和后端進行封裝,用繼承和包含的方法實現模塊的重用。HTML 之間可以通過 extends 關鍵字和 block 關鍵字進行相互嵌套。
1.base.html
<!DOCTYPE html> <head> <meta charset="UTF-8"> <title>demo</title> </head> <body> <!-- 頭部導航區域 --> <% block top %> <% endblock %> <!-- 中部內容區域 --> <% block content %> <% endblock %> <!-- 底部區域 --> <% block bottom %> <% endblock %> </body> </html>2.top.html
<% extends 'base.html' %> <% block top %> <div><h1> 此處為頂部導航界面 </h1></div> <% endblock %>3.content.html
<% extends 'base.html' %> <% block content %> <div><h1> 此處為中部內容界面 </h1></div> <% endblock %>4.bottom.html
<% extends 'base.html' %> <% block bottom %> <div><h1> 此處為底部內容界面 </h1></div> <% endblock %>接下來我們需要向Django說明模板文件的路徑,修改settings.py,修改 TEMPLATES 中的 DIRS 為**[BASE_DIR+"/templates",]**,如:
TEMPLATES = [{'BACKEND': 'django.template.backends.django.DjangoTemplates','DIRS': [BASE_DIR + "/templates", ],'APP_DIRS': True,'OPTIONS': {'context_processors': ['django.template.context_processors.debug','django.template.context_processors.request','django.contrib.auth.context_processors.auth','django.contrib.messages.context_processors.messages',],},}, ]1.3 View 視圖
Django 是一種基于 MVT(model,view,template)模型的 Web 開發框架。前端請求的后臺響應是通過 view.py 文件中對應的處理函數進行接收請求進行處理。示例代碼如下所示。
def index(request):book_list= book.objects.all()usr=request.session.get('user' , None) # 獲取當前登錄用戶名稱userid=request.session.get('userid' , None) # 獲取當前登錄用戶的唯一標識 idreturn render(request , 'home/index.html' , locals()) # 渲染主頁并向模板傳遞數據2.Django 項目搭建
2.1 項目創建
django-admin.py startproject testdjango # startproject :創建項目 film :項目名稱[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-aqMWbrdi-1623383682886)(images/image-20200526185338773.png)]
- testdjango: 項目的容器。
- manage.py: 一個實用的命令行工具,可讓你以各種方式與該 Django 項目進行交互。
- testdjango/init.py: 一個空文件,告訴 Python 該目錄是一個 Python 包。
- testdjango/asgi.py: 一個 ASGI 兼容的 Web 服務器的入口,以便運行你的項目。
- testdjango/settings.py: 該 Django 項目的設置/配置。
- testdjango/urls.py: 該 Django 項目的 URL 聲明; 一份由 Django 驅動的網站"目錄"。
- testdjango/wsgi.py: 一個 WSGI 兼容的 Web 服務器的入口,以便運行你的項目。
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-y02ZmFB6-1623383682887)(images/225A52EA-25EF-4BF1-AA5A-B91490CBF26D.jpg)]
2.2 視圖和 URL 配置
在先前創建的 testdjango目錄下的 testdjango目錄新建一個 views.py 文件,并輸入代碼:
from django.http import HttpResponsedef hello(request):return HttpResponse("Hello world ! ")接著,綁定 URL 與視圖函數。打開 urls.py 文件,刪除原來代碼,將以下代碼復制粘貼到 urls.py 文件中:
from django.urls import pathfrom . import viewsurlpatterns = [path('hello/', views.hello), ]2.3 創建應用
Django 規定,如果要使用模型,必須要創建一個 app。我們使用以下命令創建一個 TestModel 的 app:
django-admin.py startapp TestModel[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-lVuTyBlF-1623383682889)(images/image-20200526190940213.png)]
2.4 創建模型
我們修改 TestModel/models.py 文件,代碼如下:
from django.db import models# Create your models here. class user(models.Model):name = models.CharField(max_length=50, default='') # 用戶名email = models.EmailField() # 郵箱地址password = models.CharField(max_length=6, default='admin') # 密碼def __str__(self):return self.nameclass Meta:verbose_name = "用戶管理" # 修改 Admin 后臺 App 名稱verbose_name_plural = "用戶管理"class hits(models.Model):userid = models.IntegerField(default=0)bookid = models.IntegerField(default=0)hitnum = models.IntegerField(default=0)def __str__(self):return str(self.userid)class Meta:verbose_name = "單擊量"verbose_name_plural = "單擊量"class book(models.Model):id = models.CharField(max_length=50, blank=False, verbose_name="ID", default='', primary_key=True)name = models.CharField(max_length=50, blank=False, verbose_name="書名", default='')price = models.CharField(max_length=50, blank=False, verbose_name="價格", default='')cover = models.ImageField(verbose_name="封面", upload_to='upload', default='img/default.png')introduction = models.TextField(verbose_name="介紹", blank=True, default='')url = models.URLField(verbose_name='URL', blank=True, default='')publish = models.CharField(verbose_name=' 出版社 ', max_length=50, default='', blank=True)rating = models.CharField(verbose_name=' 評分 ', max_length=5, default='0')def __str__(self):return self.nameclass Meta:verbose_name = " 圖書管理 "verbose_name_plural = " 圖書管理 "接下來在 settings.py 中找到INSTALLED_APPS這一項,如下:
INSTALLED_APPS = ('django.contrib.admin','django.contrib.auth','django.contrib.contenttypes','django.contrib.sessions','django.contrib.messages','django.contrib.staticfiles','TestModel', # 添加此項 )在命令行中運行:
$ python manage.py migrate # 創建表結構$ python manage.py makemigrations TestModel # 讓 Django 知道我們在我們的模型有一些變更 $ python manage.py migrate TestModel # 創建表結構2.5 Admin 管理工具
Django 提供了基于 web 的管理工具。
Django 自動管理工具是 django.contrib 的一部分。你可以在項目的 settings.py 中的 INSTALLED_APPS 看到它:
INSTALLED_APPS = ('django.contrib.admin','django.contrib.auth','django.contrib.contenttypes','django.contrib.sessions','django.contrib.messages','django.contrib.staticfiles', )通常我們在生成項目時會在 urls.py 中自動設置好,我們只需去掉注釋即可。
from django.contrib import admin from django.urls import pathurlpatterns = [path('admin/', admin.site.urls), ]你可以通過命令 python manage.py createsuperuser 來創建超級用戶,如下所示:
# python manage.py createsuperuser啟動開發服務器,然后在瀏覽器中訪問 http://127.0.0.1:8000/admin/,得到如下界面:
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-lH4VaHkr-1623383682890)(images/admin1.png)]
之后輸入用戶名密碼登錄,界面如下:
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-ChjvPt9Z-1623383682891)(images/A995340B-8F8C-4777-9B79-846B6A34508A.jpg)]
3.推薦引擎設計
3.1導入數據
本章實驗數據來自 GitHub 共享者 moverzp 提供的 GoodBooks 數據集,讀者可以在 GitHub中搜索 moverzp 即可找到該貢獻者的倉庫。 該數據集抓取自豆瓣圖書網站,一共有 5 萬多條,主要包含序號、書名、評分、價格、出版社、爬取鏈接的地址,數據格式如圖:
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-MY1dN0ZY-1623383682892)(images/image-20200527171230075.png)]
為了在網頁前端界面上進行展示,并對圖書信息進行查看,需要先將圖書信息導入到數據庫中。該實驗主要使用的 Django 自動生成的 SQLite 數據庫進行數據存儲,通過 Python 腳本把 csv格式文件導入到數據庫中。其主要思路是通過在前端單擊瀏覽按鈕選擇圖書表格上傳到后臺,后臺接收到 csv 文件后進行解析,通過 Python 代碼打開文件并逐條將數據寫入到數據庫中,核心代碼如下。
# 上傳圖書數據到服務器端并入庫 def handle_upload_file(name, file):path = os.path.join(settings.BASE_DIR, 'uploads') # 服務器上傳地址fileName = path + '/' + name # 文件名with open(fileName, 'wb') as destination: # 接收數據并保存到服務器端for chunk in file.chunks():destination.write(chunk)insertToSQL(fileName) # 將數據插入到數據庫中def insertToSQL(fileName):txtfile = open(fileName, 'r', encoding='UTF-8')for line in txtfile.readlines(): # 逐行讀取數據try:bookinfo = line.split(',') # 數據按照逗號切分獲取各個字段id = bookinfo[0].decode().encode('utf-8') # 圖書編號name = bookinfo[1].decode().encode('utf-8') # 圖書名稱rating = bookinfo[2].decode().encode('utf-8') # 圖書評分得分price = bookinfo[3].decode().encode('utf-8') # 圖書價格publish = bookinfo[4].decode().encode('utf-8') # 出版社url = bookinfo[5].decode().encode('utf-8') # 豆瓣鏈接try:# 創建圖書對象bk_entry = book(name=name, price=price, url=url, publish=publish, rating=rating)bk_entry.save() # 插入數據到數據庫except:print('save error' + id)except:print('read error ' + id)def importBookData(request):if request.method == 'POST':file = request.FILES.get('file', None) # 獲取上傳的文件信息if not file:return HttpResponse('None File uploads !')else:name = file.namehandle_upload_file(name, file)return HttpResponse('success')return render(request, 'upload.html')3.2訓練模型
因為用戶在訪問圖書網站的時候不一定會對圖書進行評分,所以不根據用戶評分來進行訓練模型,而根據用戶的瀏覽記錄進行相似性推薦。在項目的后臺業務邏輯中會收集用戶的單擊事件,記錄下用戶 id、圖書 id 以及單擊的次數等信息,數據格式如表:
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-pJWBnfPQ-1623383682893)(images/image-20200527194253126.png)]
因為不根據用戶評分進行訓練,所以在訓練時候采用隱式評分模型,核心代碼如下:
from pyspark import SparkContext from pyspark.sql import SparkSession, Row from pyspark.mllib.recommendation import ALS import os import shutilsc = SparkContext() # 獲取 Spark 上下文 txt = sc.textFile('datas/hit.txt') # 讀取本地用戶瀏覽記錄文件 ratingsRDD = txt.flatMap(lambda x: x.split()).map(lambda x: x.split(',')) # 用戶記錄轉換為 RDD sqlContext = SparkSession.builder.getOrCreate() # 創建 sqlContextuser_row = ratingsRDD.map(lambda x: Row( # 將 RDD 轉換成行數據userid=int(x[0]), bookid=int(x[1]), hitnum=int(x[2]) )) user_df = sqlContext.createDataFrame(user_row) user_df.registerTempTable('test') # 登錄臨時表 datatable = sqlContext.sql("select userid, bookid, sum(hitnum) as hitnum from test group by userid , bookid") # 統計用戶單擊過得圖書次數 bookrdd = datatable.rdd.map(lambda x: (x.userid, x.bookid, x.hitnum)) model = ALS.trainImplicit(bookrdd, 10, 10, 0.01) # 訓練模型if os.path.exists('recommendModel'): # 判斷是否存在模型文件夾shutil.rmtree('recommendModel') # 遞歸刪除文件夾 model.save(sc, 'recommendModel') # 保存模型到本地3.3圖書推薦
模型訓練完畢后,可以通過 MatrixFactorizationModel 類的 load 方法加載模型,該方法有兩個參數,第一個參數 spark 初始化上下文,第二個參數為用戶的編號,可以通過 recommendProducts函數對用戶進行圖書推薦,該函數有兩個參數,第一個參數為用戶編號,第二個編號為推薦的圖書數量,可以通過前端請求靈活設定推薦的數目。對用戶推薦的結果存到 Redis 內存數據庫中,后臺定時執行該訓練代碼更新數據庫,隨著用戶瀏覽量的增加和系統用戶量的增加,推薦會越來越準確。
import redis from pyspark import SparkContext from pyspark.mllib.recommendation import MatrixFactorizationModelpool = redis.ConnectionPool(host='localhost', port=6379) redis_client = redis.Redis(connection_pool=pool) sc = SparkContext()def getRecommendByUserId(userid, rec_num):try:model = MatrixFactorizationModel.load(sc, 'recommendModel')result = model.recommendProducts(userid, rec_num)temp = ''for r in result:temp += str(r[0]) + ',' + str(r[1]) + ',' + str(r[2]) + '|'redis_client.set(userid, temp)print('load model success ---' + temp)except Exception as e:print('load model failed!' + str(e))sc.stop()getRecommendByUserId(1, 5)4.系統設計與實現
4.1BootStrap介紹與使用
Bootstrap 是 Twitter 推出的一個用于前端開發的開源工具包。它由 Twitter 的設計師 Mark Otto和 Jacob Thornton 合作開發,是一個 CSS/HTML 框架。
BootStrap中文網:https://www.bootcss.com/
Bootstrap 教程:https://www.runoob.com/bootstrap/bootstrap-tutorial.html
Bootstrap 已經定義了包括按鈕、表單、表格等基本元素在內的多種不同的樣式,不需要開發者再去重新寫 css 樣式去控制外觀。同時 Bootstrap 還提供了柵格布局結構,可以通過簡單的 class設置即可實現響應式布局以適應不同屏幕尺寸的終端。
bootstrap除了包含一個css文件之外還包含有BootStrap.min.js文件,因為js文件是基于JQuery開發的,所以在引用 bootstrap 時候需要先引入 jquery,引用方式如下。
<link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css"> <script src="https://cdn.bootcss.com/jquery/2.1.1/jquery.min.js"></script> <script src="https://cdn.bootcss.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>注:使用 cdn 時候,如果網絡連接斷開會導致樣式訪問不到,網站排版錯亂。
4.2Redis數據庫安裝與使用
Redis教程:https://www.runoob.com/redis/redis-tutorial.html
Python redis 使用介紹:https://www.runoob.com/w3cnote/python-redis-intro.html
pip3 install redis簡單實例:
import redis # 導入redis 模塊r = redis.Redis(host='localhost', port=6379, decode_responses=True) r.set('name', 'runoob') # 設置 name 對應的值 print(r['name']) print(r.get('name')) # 取出鍵 name 對應的值 print(type(r.get('name'))) # 查看類型連接池:
import redis # 導入redis 模塊pool = redis.ConnectionPool(host='localhost', port=6379, decode_responses=True) r = redis.Redis(connection_pool=pool) r.set('name', 'runoob') # 設置 name 對應的值 print(r.get('name')) # 取出鍵 name 對應的值4.3視圖與路由設計
視圖views.py需要應用的包:
from django.shortcuts import render from django.http import HttpResponse, HttpResponseRedirect import osfrom testdjango import settings from .models import * from utils import tools import redis(1)創建用戶登錄視圖
def login(request):if request.method == 'POST': # 相應前臺的 POST 事件name = request.POST.get('name') # 接收前臺傳遞的用戶名password = request.POST.get('password') # 接收前臺傳遞的密碼userEntry = user.objects.filter(name=name, password=password) # 查詢數據庫if userEntry.exists(): # 判斷是否存在用戶request.session['user'] = name # 用戶名寫入到 session 會話request.session['userid'] = userEntry[0].idreturn HttpResponseRedirect('/')return render(request, 'login.html')(2)創建用戶注冊視圖,核心代碼如下
def register(request):if request.method == 'POST':name = request.POST.get('name')password = request.POST.get('password')userEntry = user(name=name, password=password)userEntry.save()return HttpResponseRedirect('/login/')return render(request, 'register.html', locals())(3)創建用戶單擊視圖,核心代碼如下
def getBookInfo(request):id = request.GET.get('id')bk = book.objects.get(id=id)# 設置單擊量username = request.session.get('user', None)currentuser = user.objects.get(name=username)try:hit = hits.objects.get(userid=currentuser.id, bookid=id)hit.hitnum += 1hit.save()except:hit = hits()hit.bookid = idhit.hitnum = 1hit.userid = currentuser.idhit.save()data = str(currentuser.id) + ',' + str(id) + ',' + str(1)tools.writeToLocal('datas/hit.txt', data)return render(request, 'detail.html', locals())(4)創建主頁,核心代碼如下
def index(request):book_list = book.objects.all()usr = request.session.get('user', None)userid = request.session.get('userid', None)return render(request, 'index.html', locals())(5)創建推薦視圖,核心代碼如下
pool = redis.ConnectionPool(host='localhost', port=6379) redis_client = redis.Redis(connection_pool=pool)def getRecommendBook(request):userid = request.session.get('userid', None)recommendbook = redis_client.get(int(userid))booklist = str(recommendbook).split('|')bookset = []for bk in booklist[:-1]:bookid = bk.split(',')[1]bk_entry = book.objects.get(id=bookid)bookset.append(bk_entry)return render(request, 'recommend.html', locals())(6)路由設計,核心代碼如下
from django.contrib import admin from django.urls import path from TestModel import viewsurlpatterns = [path('admin/', admin.site.urls),path('hello/', views.hello),path('/', views.index),path('importBookData/', views.importBookData),path('login/', views.login),path('register/', views.register),path('getBookInfo/', views.getBookInfo),path('getRecommendBook/', views.getRecommendBook), ](7)在項目的根路徑下新建utils包,并新建tools.py,內容如下:
def writeToLocal(filepath, str):ft = open(filepath, "a+")ft.writelines(str + '\n')ft.close()4.4界面設計
在項目的路徑下新增templates目錄,分別新建下面的文件:
(1)base.html
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>圖書推薦系統</title><link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css"> </head> <body><!-- 中部內容區域 --><div class="container"><div class="row" ><div class="col-md-6"><% block content %><% endblock %></div></div></div><script src="https://cdn.bootcss.com/jquery/2.1.1/jquery.min.js"></script><script src="https://cdn.bootcss.com/bootstrap/3.3.7/js/bootstrap.min.js"></script></body> </html>(2)login.html
<% extends 'base.html' %> <% block content %><form action="/login/" method="post"><% csrf_token %><div class="form-group"><label for="name">用戶名</label><input type="text" class="form-control" id="name" name="name" placeholder="請輸入用戶名"></div><div class="form-group"><label for="name">密碼</label><input type="password" class="form-control" id="password" name="password" placeholder="請輸入密碼"></div><button type="submit" class="btn btn-default">登錄</button><a href="/register/" class="btn btn-primary">注冊</a></form> <% endblock %>(3)register.html
<% extends 'base.html' %> <% block content %><form action="/register/" method="post"><% csrf_token %><div class="form-group"><label for="name">用戶名</label><input type="text" class="form-control" id="name" name="name" placeholder="請輸入用戶名"></div><div class="form-group"><label for="password">密碼</label><input type="password" class="form-control" id="password" name="password" placeholder="請輸入密碼"></div><button type="submit" class="btn btn-default">注冊</button></form> <% endblock %>(4)index.html
<% extends 'base.html' %> <% block content %><table class="table"><caption>圖書列表</caption><thead><tr><th>ID</th><th>名稱</th><th>價格</th></tr></thead><tbody><% for book in book_list %><tr><td><a href="/getBookInfo/?id={{ book.id }}">{{ book.id }}</a></td><td>{{ book.name }}</td><td>{{ book.price }}</td></tr><% endfor %></tbody></table><a href="/getRecommendBook/" class="btn btn-primary">我的推薦列表</a> <% endblock %>(5)detail.html
<% extends 'base.html' %> <% block content %><form><div class="form-group"><label for="name">書名</label><input type="text" class="form-control" id="name" name="name" value="{{ bk.name }}" disabled></div><div class="form-group"><label for="name">出版社</label><input type="text" class="form-control" id="publish" name="publish" value="{{ bk.publish }}" disabled></div><div class="form-group"><label for="name">價格</label><input type="text" class="form-control" id="price" name="price" value="{{ bk.price }}" disabled></div><div class="form-group"><label for="name">評分</label><input type="text" class="form-control" id="name" name="name" value="{{ bk.rating }}" disabled></div><div class="form-group"><label for="name">URL</label><input type="text" class="form-control" id="url" name="url" value="{{ bk.url }}" disabled></div><a href="/" class="btn btn-primary">返回</a></form> <% endblock %>(6)recommend.html
<% extends 'base.html' %> <% block content %><table class="table"><caption>推薦列表</caption><thead><tr><th>ID</th><th>名稱</th><th>價格</th></tr></thead><tbody><% for book in bookset %><tr><td><a href="/getBookInfo/?id={{ book.id }}">{{ book.id }}</a></td><td>{{ book.name }}</td><td>{{ book.price }}</td></tr><% endfor %></tbody></table><a href="/" class="btn btn-primary">返回</a> <% endblock %>(7)upload.html
<% extends 'base.html' %> <% block content %><form action="/importBookData/" method="post" enctype="multipart/form-data"><% csrf_token %><label> 請選擇上傳的文件: </label><input class="form-control" type="file" name="file"><button class="btn btn-primary" type="submit"> 上傳 </button></form> <% endblock %>5.Issue
1.django.template.exceptions.TemplateDoesNotExist: upload.html
解決方案:
- 在項目的目錄下面新增templates目錄
- 在settings.py的TEMPLATES中修改DIRS設置,添加模板路徑
2.RuntimeError: You called this URL via POST, but the URL doesn’t end in a slash and you have APPEND_SLASH set
解決方案:在settings.py中設置APPEND_SLASH = False
3.Forbidden (CSRF token missing or incorrect.)
解決方案:https://blog.csdn.net/weixin_42694291/article/details/86165884
確認settings.py中MIDDLEWARE的有:django.middleware.csrf.CsrfViewMiddleware
html中的form添加模板標簽<% csrf_token %>
6.參考文檔
三、轉載申明
本文轉自csdn、博客園多個網站匯總所得,屬于個人筆記,不與轉載
總結
以上是生活随笔為你收集整理的Spark机器学习实验的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 大-杂-烩
- 下一篇: OSChina 周三乱弹 ——找女朋友都