1.項目需求分析javascript
立項:Javis&&taisen(三個月所有,先模擬出一個玩具,硬件須要週期長一些)html
想法 --- 需求分析: 1.經過玩具與孩子實時進行溝通 2.但願玩具的知識淵博 3.但願玩具最好能代替我陪伴孩子 4.給孩子播放幼教內容 兒歌 睡前故事 國學 5.自擴散 - 幼兒社交圈 需求分析: 4.給孩子播放幼教內容 兒歌 睡前故事 國學 - 數據採集(爬蟲) - 獲取本地資源 - 家長能夠控制玩具播放的內容 - 控制端 App 2019年4月19日: 1.喜馬拉雅聽 採集數據 2.存放數據目錄結構 3.數據存放在MongoDB中 4.在App中展現資源: 經過/content_list接口獲取資源 5.播放幼教內容在App端播放 plus.audio.createPlayer(URL_PATH).play() 6.家長能夠控制玩具播放的內容 1.經過玩具與孩子實時進行溝通 - 對玩具發起消息 - 手機 App - 基於通信錄的IM功能 IM:即時通信 - WebSocket 2.但願玩具的知識淵博 - 問題庫 百科 - 問答機器人 Tuling 3.但願玩具最好能代替我陪伴孩子 - 聊天庫 - 問答機器人 Tuling 5.自擴散 - 幼兒社交圈 - 玩具與玩具之間對話 - 玩具須要具備通信錄的功能 - 基於通信錄的IM功能 IM:即時通信 - WebSocket App的功能? 1.用戶管理 - 註冊登陸 - 用戶信息 - 通信錄 - 綁定玩具 2.管理玩具 - 綁定玩具 - 控制玩具通信錄 - 幫助玩具創建社交圈 3.內容審覈 - App看到內容 - App聽內容 - App給玩具發過去 - 遙控器(只要有網就行) 4.與玩具通信功能 - App通信錄 - App聊天界面 - 語音消息發送 - 錄音 - 播放錄音 玩具的功能?因爲玩具硬件開發週期很是長,本身模擬WebToy玩具 1.播放幼教內容 - 點播 語音指令 - 遙控 App發送音樂給玩具 {music:"小毛驢.mp3"} - WebToy - audio 2.播放語音消息 - 通信 - 收取消息 實時 - WebSocket - WebToy - audio 3.發送語音消息 - 錄音 - 發送? - App - 玩具 - 問答機器人 4.語音指令 - 錄音 - 上傳 - NLP 天然語言處理 - 我要聽 - 發消息給xxxx
注意:沒有誰一看到項目,立刻就有思路了,都是一步一步來的,不要慌,一點一點來前端
2.數據採集 xmlyjava
首先,咱們須要採集數據,存在法律風險,須要帶上出處和做者這個東西,不然極可能出現賠償問題web
音頻可能沒有太大影響,可是視頻是視覺上的,就存在風險了算法
起名字無所謂的.mongodb
yinwangba//12//eightapp//13king//14tuxingsun//15chunsheng//16laopobing//17vista//18javis數據庫
建立完後端,須要在前端同步開發json
在前端中,新建一個appflask
清除原來的內容,寫一個md代碼塊,進行獲得下面的內容:
咱們想要採集的內容爬爬內容:"幼教類網站"=>"幼教網"
上邊的名詞難度有點高
親寶網,"貝瓦兒歌"
"喜馬拉雅"
不入虎穴焉得虎子,捨不得孩子套不着狼(鞋子)
動態class是最難爬取的
請求頭裏邊有請求地址
上邊顯示請求的URL和請求的方式GET
上邊顯示的是響應應用類型:
下圖顯示的是普通請求方式:
用戶代理,在請求頭裏邊:見下圖
咱們須要用get請求進行訪問,
獲得下面的結果,響應的是200,也就是能夠響應
在打印一下里邊的內容,結果是空的
反爬請求方式1:校驗當前的用戶是否爲瀏覽器訪問
下面,咱們開始模擬一下:
這個時候,咱們爬取的內容,見上圖
反爬的機制1就是"動態class"隨時可能變化
下面咱們經過json,變成字典:
rest是一種開發方式,一種標準:相似於下圖的一種標準的格式
下面,咱們須要經過for循環,拿取裏邊的內容:也就是先拿名字:
下面咱們除了須要名字,還須要播放的連接地址:
咱們須要存儲起來,防止網址變動.
咱們下面,驗證的結果就是流:
也就是不須要請求頭的.
下面咱們須要開始寫入某個內容:
運行以後的到的結果:
右擊,打開文件的位置:
不要覺得別人好像很簡單作成了某件事情,別人可能花了你所不知道的更多的時間,進行處理這個問題.
有可能連接可能變了
上邊寫的方式是單線程的,可是會慢一些,可是無所謂了,如今能用就行.
下面新建兩個文件夾:一個存圖片,一個存音樂
咱們再見一個settings.py進行數據庫的配置,優選mongodb,簡單粗暴
最終版程序:
papaxiao.py
# Author: studybrother sun import os import time import requests from uuid import uuid4 from settings import MONGODB,MUSIC_PATH,COVER_PATH xmly_url="https://www.ximalaya.com/revision/play/album?albumId=424529&pageNum=1&sort=1&pageSize=30" # 424529指的是專題ID header={ "User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36" } def papaxiao(tar): res = requests.get(xmly_url, headers=header) music_list=[]# 新建一個空列表music的 for audio_info in res.json().get("data").get("tracksAudioPlay"): print(audio_info.get("trackName"), audio_info.get("src")) music = requests.get(audio_info.get("src")) # 音樂 cover = requests.get("http:" + audio_info.get("trackCoverPath")) # 圖片 filename = uuid4() # 保證每一個名字都不同 cover_file = os.path.join(COVER_PATH, f"{filename}.jpg") # 拼接路徑 music_file = os.path.join(MUSIC_PATH, f"{filename}.mp3") # 拼接路徑 with open(music_file, "wb")as f: f.write(music.content) with open(cover_file, "wb")as f: f.write(cover.content) music_info = { "music": f"{filename}.mp3", "cover": f"{filename}.jpg", "title": audio_info.get("trackName"), # 展現的內容 "ZJ": audio_info.get("albumName"), # 專輯名字須要拿出來,防止被告 "class": tar # "class": "兒歌分類" } music_list.append(music_info) # time.sleep(0.12)#防止無限爬取,咱們須要防止屏蔽 # 將music_info插入數據庫,30次 MONGODB.content.insert_many(music_list) papaxiao("兒歌")
settings.py
# Author: studybrother sun from pymongo import MongoClient mc=MongoClient("127.0.0.1",27017) MONGODB=mc["Taisen_J"] #目錄配置 MUSIC_PATH="Music" COVER_PATH="Cover"
目錄結構:
還有,咱們須要開啓mongodb
最終獲得的結果:
注意,反爬機制會很全面的,特別是這種大的網站
播放次數.點播次數&&推薦次數,這種算法.
咱們採集完內容,咱們應該怎樣操做?
3.App內容列表&&App播放歌曲
咱們須要將數據庫,裏邊的內容,變成列表返回這些內容:
咱們須要寫一個視圖函數進行返回,
新建一個manager.py和一個文件夾,serv
主要用C#的一種架構方式寫的:
下面咱們再寫一個content內容藍圖
只支持"POST"的方式,是複寫而不是追加,緣由是源碼中進行了覆蓋methods
面對一個美麗的前端小姐姐,咱們該如何處理?
咱們須要,在前端中導入上邊的內容,
# Author: studybrother sun from flask import Blueprint,jsonify from settings import MONGODB,RET content=Blueprint("content",__name__) @content.route("/content_list",methods=["POST"]) def content_list(): #寫一個視圖函數,在上邊導入mongodb res=list(MONGODB.content.find()) #這是一個生成器,須要轉換成一個列表 for index,con in enumerate(res): res[index]["_id"]=str(con.get("_id")) # 須要修改格式和_id RET["code"]=0 RET["msg"]="查詢內容列表" RET["data"]=res return jsonify(RET)
咱們寫了攬入須要在manager.py裏邊先註冊一下:
下面,咱們須要在Hbuilder前端裏邊寫一個內容,開始拿咱們的請求內容:
清空前端index.html裏邊的內容,而後md代碼塊,
先運行項目:Hbuilder,這個時候咱們能夠獲得一個乾淨的項目,也就是什麼都沒有
注意,創建鏈接的過程會比較慢,這很正常,多長時間幾回就能夠鏈接上了
再加上mat代碼塊,底部多了一個
而後輸入代碼塊在body裏邊:
新建一個home.html頁面,清空改爲md
再在home裏邊加上mhe
先寫一個mbo,再在裏邊寫一個msl輪播圖
再寫一個mg九宮格
咱們再寫一個mlis代碼塊,選擇第三個
這個時候,咱們須要在index.html裏邊的初始化進行修改
先刪除上邊的第30行,
這個時候,咱們再進行保存處理
再次獲得下面熟悉的界面:
可是標題已經發生了改變,咱們本身起的名字"泰森_賈"
將後邊的數字,都改爲4,就變成了九宮格
也就是說一共屏幕上有12個格,每一個佔4個,就顯示3個標籤
下面,咱們須要對"幸福","木屋","CBD"等進行替換成歌曲
也就是說,咱們加載完home頁面以後,須要對服務器發起一個請求,
寫一個mpl
下面,咱們發起一個post請求
注意,這個後端,須要開啓後端的服務,
如今,前端,咱們保存一次就會運行一次.
咱們想將li包裹的裏邊的東西進行處理:
也就是說,咱們要將下圖中紅框的位置刪除:
代碼,見下圖:
很明顯,咱們這樣操做會出錯,顯示下圖中的語法錯誤:
接下來,咱們應該如何操做?
下面,咱們要建立標籤,
這個時候能夠把上邊的結構表刪除了
也就是下圖中,紅框的內容:
咱們須要執行的位置,見下圖:
上圖是執行的位置,咱們能夠判斷的是,這個js不是按照從上到下執行的
寫代碼塊fori,獲得下圖的內容
咱們將Things修改爲data.data,也就是數據的長度
咱們先運行起後端程序manager.py,在保存也就是運行home.html,獲得下面的結果:
咱們再處理下面的內容:
注意,要把內容,寫對,內容可能會出來的慢一些,不要着急
修改p標籤爲ZJ
上邊表示能夠加載出歌名來.
保存也就是運行,獲得下面的結果:
思考,可不能夠直接那裏邊的圖片:也就是
img.src=content.cover;
訪問的結果,咱們須要的是一個流,進行處理
下面咱們須要再建立一個接口進行處理:
下面,咱們須要註冊一個藍圖,進行處理,
保存上圖的內容,這個時候,應該能夠加載出圖片了.
這個地方爬蟲寫錯了一個字母,致使後邊出現的歌名所有同樣:
就是由於爬蟲中寫錯了一個字母,致使了這個音樂列表中的名字和圖片都出現的不正確,如今上邊就顯示正常了
下面,咱們想要播放列表中的音樂,咱們該如何處理?
點擊事件,咱們想要,點擊a標籤就能夠播放音樂
下面,咱們再建立一個player頁面:
在清空,寫入代碼塊:md
在body裏邊寫mhe,選擇帶箭頭的,緣由是"這是一個子集"
將title裏邊寫上標題,
下面咱們再寫一個mbo代碼塊,
下面咱們再在home.html裏編寫,打開頁面,寫mop代碼塊,打開頁面
咱們須要將上圖中的styles去掉,保存也就是運行:
這個時候,機器可能的比較慢
點擊任意一首歌曲,都會跳轉到player.html界面
下面,咱們還須要傳遞一個參數,進行處理.
下面,咱們將執行的參數進行傳遞:
也就是傳遞到player.html,這個時候player.html就能夠接收了
這個時候,咱們能夠獲得上邊的內容,其中webview裏邊能夠包含傳遞過來的參數content,也就是data.data
這個時候再次保存,就能夠,點擊歌曲裏邊,能夠看到結果了,可是這個時候,電腦可能會卡一下,注意一下
這樣就能夠根據點擊進去的歌名,顯示標題的樣式了
下面,再寫一個mro
這個時候,咱們想要再在下圖寫一個圖片:
下面,咱們再加上一個id=cover
由於是傳遞過來的,咱們須要修改的位置,見下圖:
咱們看到所佔的頁面是有點大的,下面處理一下:
咱們須要在這裏改變大小,而且居中
距離頂部必定的距離,改爲圓形
下面,咱們再寫一個按鈕
如何進行播放,這個時候,咱們須要查一下文檔,
選擇第二個Audio,也就是音頻的錄製和播放
這個時候,咱們須要在後端寫一個getmusic
注意,這個時候,咱們不在須要註冊了,註冊的是實例化以後的藍圖,不是函數,記住這一點
之因此,沒有播放的緣由是缺乏一行代碼
這個時候,咱們點擊,就能夠播放音樂了.
後端的請求就拿到了MP3
設置=>聲音=>默認通知聲音=>選擇聲音
如今,咱們想要音樂中止,怎麼操做?
4.Player用法
下面,咱們須要加上幾個按鈕,實現暫停,繼續等功能
mbu代碼塊功能,選擇第一個
下面咱們開始綁定事件:
dga代碼塊
player 而且咱們在plusReady裏邊賦值成了一個新的對象
下面咱們能夠用了.
下面,咱們再上邊再定義一個公共事件:
也就是說咱們再plusReady裏邊先設置好值.
此時的播放是重建的對象,再次播放是從頭開始進行播放的.
上邊出錯的緣由是加上了var
下面,咱們修改一下home裏邊九宮格所表明的東西:
MUI本身學習這些功能:
咱們須要的是上拉下載:
國學列表,古詩列表等等.
5.Websocket遙控器
需求分析: 4.給孩子播放幼教內容 兒歌 睡前故事 國學 - 數據採集(爬蟲) - 獲取本地資源 - 家長能夠控制玩具播放的內容 - 控制端 App 2019年4月19日: 1.喜馬拉雅聽 採集數據 2.存放數據目錄結構 3.數據存放在MongoDB中 4.在App中展現資源: 經過/content_list接口獲取資源 5.播放幼教內容在App端播放 plus.audio.createPlayer(URL_PATH).play() 6.家長能夠控制玩具播放的內容 1.經過玩具與孩子實時進行溝通 - 對玩具發起消息 - 手機 App - 基於通信錄的IM功能 IM:即時通信 - WebSocket 2.但願玩具的知識淵博 - 問題庫 百科 - 問答機器人 Tuling 3.但願玩具最好能代替我陪伴孩子 - 聊天庫 - 問答機器人 Tuling 5.自擴散 - 幼兒社交圈 - 玩具與玩具之間對話 - 玩具須要具備通信錄的功能 - 基於通信錄的IM功能 IM:即時通信 - WebSocket App的功能? 1.用戶管理 - 註冊登陸 - 用戶信息 - 通信錄 - 綁定玩具 2.管理玩具 - 綁定玩具 - 控制玩具通信錄 - 幫助玩具創建社交圈 3.內容審覈 - App看到內容 - App聽內容 - App給玩具發過去 - 遙控器 4.與玩具通信功能 - App通信錄 - App聊天界面 - 語音消息發送 - 錄音 - 播放錄音 玩具的功能?因爲玩具硬件開發週期很是長,本身模擬WebToy玩具 1.播放幼教內容 - 點播 語音指令 - 遙控 App發送音樂給玩具 {music:"小毛驢.mp3"} - WebToy - audio 2.播放語音消息 - 通信 - 收取消息 實時 - WebSocket - WebToy - audio 3.發送語音消息 - 錄音 - 發送? - App - 玩具 - 問答機器人 4.語音指令 - 錄音 - 上傳 - NLP 天然語言處理 - 我要聽 - 發消息給xxxx
下面進行模擬一個web進行處理:
下面須要再建立一個html文件:,注意,如今咱們模擬的是web頁面,不寫先後端分離了
江老師傳授的播放方式:
音樂的名字 能夠直接copy採集下來的數據名稱用上邊的命令進行處理
下面咱們再寫一個發送按鈕:
在組件中看一下顏色:
下面,咱們須要再次寫一個事件
咱們先寫一些數字,看能不能發送成功:
下面,咱們須要在服務端新建一個ws_serv.py開啓一個通信服務
下面,咱們須要基於flask,寫一個websocket服務
兩套服務,寫在同一套代碼裏邊:一個開ws_serv.py,另外一個專門開manager.py
剛纔江老師的方式也是一種get請求方式
我覺得你是個暖男,結果你只支持get請求:
先安裝好這個包,再處理:
ws_serv.py
import json from flask import Flask,request ws_serv=Flask(__name__) from geventwebsocket.websocket import WebSocket from gevent.pywsgi import WSGIServer #替換werkzurg from geventwebsocket.handler import WebSocketHandler #處理wsgi帶的請求頭的信息 user_socket_dict={} @ws_serv.route("/app/<app_id>") def app(app_id): user_socket=request.environ.get("wsgi.websocket") if user_socket: user_socket_dict[app_id]=user_socket print(len(user_socket_dict),user_socket_dict) while True: msg=user_socket.receive() msg_dict=json.loads(msg) #msg{to_user:toy01,music: getmusic/25d3c036-4b1f-4f4b-827a-fc4ddc50286f.mp3 } print(msg_dict)
if __name__ == '__main__':
http_serv=WSGIServer(("0.0.0.0",9528),app,handler_class=WebSocketHandler)
http_serv.serve_forever()
下面,咱們看一下,能不能拿出值來
運行上邊的ws_serv.py程序,這個時候就會阻塞住
這個時候,咱們隨便點擊一首歌,點擊發送
報錯,不能傳遞兩個參數
錯誤的緣由是上邊的app寫錯了,應該是ws_serv
這個時候運行,再次點擊進入一首歌,點擊"發送",而後咱們再後端就能夠收到信息了
下面咱們看一下,能不能發送這個字典:
咱們再次方式會報一堆錯誤:
思考,咱們應該如何處理?咱們應該先轉成字符串在進行處理,也就是json轉換成字符串:
上邊報錯的緣由是,我把點好寫成了冒號上邊是改正過來的信息
再次修改:
再次發送,獲得下面發送的結果:
爲了保證不出錯,注意放的位置
爲了避免出錯,咱們能夠有兩種方式,防止內容:下圖是放置好的方式,目的就是,放好了防止出錯,JavaScript是異步代碼,防止線程過快等問題
下面,咱們須要接收代碼:
下面是ws_serv.py的代碼
# Author: studybrother sun import json from flask import Flask,request ws_serv=Flask(__name__) from geventwebsocket.websocket import WebSocket from gevent.pywsgi import WSGIServer #替換werkzurg from geventwebsocket.handler import WebSocketHandler #處理wsgi帶的請求頭的信息 user_socket_dict={} @ws_serv.route("/app/<app_id>") def app(app_id): user_socket=request.environ.get("wsgi.websocket") if user_socket: user_socket_dict[app_id]=user_socket print(len(user_socket_dict),user_socket_dict) while True: msg=user_socket.receive() msg_dict=json.loads(msg) #msg{to_user:toy01,music: getmusic/25d3c036-4b1f-4f4b-827a-fc4ddc50286f.mp3 } print(msg_dict) @ws_serv.route("/toy/<toy_id>") def toy(toy_id): user_socket=request.environ.get("wsgi.websocket") if user_socket: user_socket_dict[toy_id]=user_socket print(len(user_socket_dict),user_socket_dict) while True: msg=user_socket.receive() msg_dict=json.loads(msg) #msg{to_user:toy01,music: getmusic/25d3c036-4b1f-4f4b-827a-fc4ddc50286f.mp3 } print(msg_dict) if __name__ == '__main__': http_serv=WSGIServer(("0.0.0.0",9528),ws_serv,handler_class=WebSocketHandler) http_serv.serve_forever()
下面是WebToy.html代碼:
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta http-equiv="content-Type" charset="UTF-8"> <meta http-equiv="x-ua-compatible" content="IE=edge"> <meta name="viewport" content="width=device-width" ,initial-scale="1"> <!--上邊這個表示手機版的調整尺寸--> <!--上述2個meta標籤"必須"放在最前面,任何其餘內容都必須跟隨其後--> <title>Title</title> </head> <body> <audio controls autoplay id="player"></audio> <!--咱們經過id進行控制--> </body> <script type="application/javascript"> var ws=new WebSocket("ws://192.168.14.133:9528/toy/toy01"); //這樣寫的緣由是toy有不少種,不得不這樣寫 ws.onmessage=function (eventMessage) { msg=JSON.parse(eventMessage.data) //字符串轉換成object document.getElementById("player").src="http://192.168.14.133:9527/getmusic"+msg.music;//大前提是須要發送消息 }//這個時候可以接收消息 </script> </html>
目錄結構:
由於這個涉及到web錄音,咱們須要用到火狐瀏覽器,重啓一下ws_serv.py文件
用火狐瀏覽器訪問,注意這個訪問的端口是服務器的端口"9527"
報錯緣由,是咱們沒有放值
這個時候,就沒有問題了
若是,咱們訪問的是9528,獲得下面的結果:
正確訪問地址以後,ws_serv獲得下面的結果:
另外一個,點擊發送歌曲的時候,就鏈接上了,第一個是火狐瀏覽器輸入地址,就能訪問,第二個是app點擊發送獲得的結果:
修改爲下面的內容:
再次運行ws_serv.py,運行火狐
下圖就是咱們的單聊:
也就是遙控器功能.給服務器前端節省一些資源
在火狐上一直出不來的緣由就是少寫了一個/
寫完以後,運行manager.py和ws_serv.py,運行前端程序,在瀏覽器上輸入網址:(192.168.14.133:9527),在模擬器上打開歌曲,點擊發送,這個時候,瀏覽器就能夠接收到音樂了,能夠進行播放了.
6.能夠進行的一些拓展
1.立項 - 名字隨意 - 最好有意義 2.Index + Home + Player 3.圖文列表經過JS document.createElement Item 4.Player 播放內容 實現暫停繼續 5.App遙控玩具 - Websocket 單聊技術 擴展任務: 6.自動登陸 + 註冊 { _id:"", username:"", password:"MD5", nickname:"", gender: 1 / 2, avatar: 1==girl.jpg / 2==boy.jpg, bind_toy : [], firend_list:[] } reg.html gender 單選框 password MD5 login.html 自動登陸
核心問題:
先研究好這些邏輯的問題再說.
查文檔,看視頻.