搭建一个弹幕新闻网站
本項(xiàng)目?jī)H供學(xué)習(xí)使用, 請(qǐng)勿用來(lái)進(jìn)行商業(yè)用途
本期知識(shí)點(diǎn):
前言
你是否在 刷B站 或 刷知乎 時(shí)覺(jué)得不夠暢? 是否想在一個(gè)平臺(tái)上同時(shí)獲取多個(gè)平臺(tái)的有趣內(nèi)容?
這個(gè)網(wǎng)站將為你打開(kāi)一扇快速通道
先來(lái)看效果
制作網(wǎng)站的緣由是我在刷新聞時(shí)的突發(fā)奇想, 純屬個(gè)人愛(ài)好, 項(xiàng)目源碼: https://github.com/zhanghao19/LetMeSee
網(wǎng)站的核心框架選擇的是Flask, 優(yōu)勢(shì)是便捷, 且官方文檔中有詳細(xì)的入門教程: 快速上手flask
文章的描述順序也是筆者搭建的流程
1>前端
彈幕新聞的重點(diǎn)在于展示, 其原理簡(jiǎn)單來(lái)說(shuō)就像"往杯子里倒水"一樣
1.1>網(wǎng)站框架
這里網(wǎng)站的框架指的是彈幕所顯示在的地方, 我使用的是之前在學(xué)習(xí)Django的時(shí)候搭建的一個(gè)框架
以原網(wǎng)站作為基礎(chǔ)框架, 使用jinja的繼承功能來(lái)使我們的主要內(nèi)容融入基礎(chǔ)框架
你可以使用任意一款你喜歡的網(wǎng)站模板, 來(lái)作為放置彈幕的容器, 參考網(wǎng)站: Bootstrap
下載好你的模板, 參考以下代碼中的block位置, 對(duì)自己的模板進(jìn)行靜態(tài)抽取:
<!-- Web/App/templates/base.html --> <!DOCTYPE html> <html lang="zh-cn"> <head><meta charset="utf-8"><title id="title">{% block title %}{% endblock %}</title><link rel="stylesheet" href="../static/css/reset.css"><link rel="stylesheet" href="../static/css/base.css"><!-- 上面的是模板自帶的靜態(tài)文件, 下面是為項(xiàng)目需要準(zhǔn)備的 -->{% block link %}{% endblock %} </head> <body> <!-- header start --> <header id="header"><div class="mw1200 header-contain clearfix"><!-- logo start --><h1 class="logo"><a href="javascript:void(0);" class="logo-title">Python</a></h1><!-- logo end --><!-- nav start --><nav class="nav"><ul class="menu"><!-- 這里是導(dǎo)航條上的一些選項(xiàng)-->{% block nav %}{% endblock %}</ul></nav><!-- nav end --></div> </header> <!-- header end --> <!-- mian start --> <main id="main"> <!-- 彈幕的容器 --> {% block main %}{% endblock %} </main> <!-- main end --> <!-- footer start --> <footer id="footer"...> <!-- footer end --> <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.js"></script> {% block script %}{% endblock %} </body> </html>1.2>網(wǎng)站內(nèi)容
這里的內(nèi)容是彈幕的主體, 可以放在大部分的網(wǎng)站模板上使用
下面的代碼包含, 彈幕的容器, 彈幕列表, 彈幕詳情頁(yè)
<!-- Web/App/templates/barrage.html --> {% extends 'base.html' %} {% block title %}LetMeSee-彈幕新聞網(wǎng){% endblock %} {% block link %}<link rel="stylesheet" href="../static/css/barrage.css"><!-- 解決圖片加載失敗的問(wèn)題 --><meta name="referrer" content="no-referrer" /> {% endblock %}{% block nav %} <li><a href="/">全部</a></li> <li><a href="/baidu/">新聞</a></li> <li><a href="/bilibili/">B站</a></li> <li><a href="/zhihu/">知乎</a></li> {% endblock %} {% block main %}<div class="box"><div class="barrage-container-wrap clearfix"><div class="barrage-container"><!-- 彈幕主體 --></div><div class="expand"><img src="../static/img/list.png" alt="expand" title="彈幕列表"></div></div></div><!-- 彈幕列表 start --><div class="barrage-list"><div class="list-header">彈幕列表<img src="../static/img/close.png" alt="close" class="close-btn" title="關(guān)閉"></div><ul>{% for barrage in barrages %}<!-- for循環(huán)展示彈幕 --><li class="barrage-list-item" data-id="{{ barrage.BID }}"><!-- truncate_text過(guò)濾器,過(guò)長(zhǎng)字符串末尾顯示為... -->{{ barrage.BText | truncate_text }}</li>{% endfor %}</ul></div><!-- 彈幕列表 end --><!-- 彈幕詳情 start --><div class="barrage-detail-panel"><div class="list-header">彈幕詳情<img src="../static/img/close.png" alt="close" class="close-btn" title="關(guān)閉"></div><h3 class="title"></h3><p class="author"></p><img src="../static/img/loading.gif" alt="彈幕封面" class="cover"><a class="source"><--查看源網(wǎng)頁(yè)--></a></div><!-- 彈幕列表 彈幕詳情 --> {% endblock %} {% block script %}<script type="text/javascript">//js和html文件是分開(kāi)的,傳遞數(shù)據(jù)需要先定義好參數(shù),再執(zhí)行js。參考:https://blog.csdn.net/m0_38061194/article/details/78891125var Server = {barrages:{{ barrages|safe }}};</script><script src="../static/js/barrage.js"></script><script src="../static/js/barrage_list.js"></script><script src="../static/js/barrage_details.js"></script> {% endblock %}自定義的過(guò)濾器truncate_text如下, 作用是過(guò)長(zhǎng)字符串末尾顯示為…
# Web/App/my_filters/truncate_text.py def truncate_text(text):if len(text) > 19:new_text = text[0:17] + "..."return new_textelse:return text整理一下上面代碼在頁(yè)面中實(shí)現(xiàn)的框架, 如圖(同色表示同級(jí)):
barrage-container-wrap是彈幕容器的底層畫(huà)布, barrage-container是盛放彈幕的容器
barrege-list和barrage-detail是觸發(fā)點(diǎn)擊事件才顯示的.
1.3>JS部分
1.3.1>彈幕主體
網(wǎng)上有很多中彈幕的設(shè)計(jì)方式, 個(gè)人認(rèn)為區(qū)別點(diǎn)在于彈幕的不重疊, 本次使用的方式是通過(guò)分組定位來(lái)實(shí)現(xiàn)彈幕不重疊.
//Web/App/static/js/barrage.js //彈幕的實(shí)現(xiàn) (function () {/*******定義參數(shù)********/let barrageColorArray = {baidu : '#5519EB', bilibili: '#ff53e0', zhihu: '#0099cc'};let barrageBoxWrap = document.querySelector('.barrage-container-wrap');let barrageBox = document.querySelector('.barrage-container');//容器的寬高度let contentWidth = ~~window.getComputedStyle(barrageBoxWrap).width.replace('px', '');let boxHeight = ~~window.getComputedStyle(barrageBox).height.replace('px', '');//當(dāng)前窗口可以垂直展示多少個(gè)彈幕, 30代表彈幕字體大小let howManyBarrageY = Math.round(boxHeight / 30);//定義一個(gè)包含彈幕的寬和高度范圍的數(shù)組let heightArray = [];//將每個(gè)可用的高度,放入數(shù)組, 以便在創(chuàng)建數(shù)組時(shí)使用for (let i = 30; i < boxHeight - 10; i += 30) {heightArray.push(i)}/*******創(chuàng)建彈幕**********/function createBarrage(item, index, forTime) {if (index >= howManyBarrageY) {//如果索引達(dá)到高度數(shù)組的長(zhǎng)度,則需重置索引到0,因此取余數(shù)index = index % howManyBarrageY;}let divNode = document.createElement('div'); //彈幕的標(biāo)簽let divChildNode = document.createElement('div'); //提示文本的標(biāo)簽divNode.innerHTML = item.BText; //將彈幕內(nèi)容插入標(biāo)簽中, innerHTML表示這個(gè)標(biāo)簽中的字符內(nèi)容divNode.classList.add('barrage-item'); //追加classbarrageBox.appendChild(divNode); //彈幕的標(biāo)簽作為彈幕容器的子代標(biāo)簽divChildNode.innerHTML = '點(diǎn)擊查看詳情'; //鼠標(biāo)懸停展示的內(nèi)容divChildNode.classList.add('barrage-link');divNode.appendChild(divChildNode); //提示文本的標(biāo)簽作為彈幕標(biāo)簽的子代標(biāo)簽//***設(shè)置彈幕的初始位置***//以容器的寬度為基準(zhǔn)隨機(jī)生成每條彈幕的左側(cè)偏移值let barrageOffsetLeft = getRandom(contentWidth * forTime, contentWidth * (forTime + 0.618));//以容器的高度為基準(zhǔn)隨機(jī)生成每條彈幕的上方偏移值let barrageOffsetTop = heightArray[index];//通過(guò)彈幕類型選擇顏色let barrageColor = barrageColorArray[item.BType];//執(zhí)行初始化滾動(dòng)//fun.call()傳入的第一個(gè)參數(shù)作為之后的this,詳解:https://codeplayer.vip/p/j7sj5initBarrage.call(divNode, {left: barrageOffsetLeft,top: barrageOffsetTop,color: barrageColor,barrageId: item.BID,});}/*******初始化彈幕移動(dòng)(速度,延遲)*********/function initBarrage(obj) {//初始化位置顏色this.style.left = obj.left + 'px';this.style.top = obj.top + 'px';this.style.color = obj.color;//添加屬性this.distance = 0; //移動(dòng)速度基準(zhǔn)值this.width = ~~window.getComputedStyle(this).width.replace('px', ''); //彈幕的長(zhǎng)度this.offsetLeft = obj.left;this.timer = null;this.timeOut = null;//彈幕子節(jié)點(diǎn),即提示信息,span標(biāo)簽let barrageChileNode = this.children[0];barrageChileNode.style.left = (this.width - barrageTipWidth) / 2 + 'px';//定義span標(biāo)簽的位置//運(yùn)動(dòng)barrageAnimate(this);//鼠標(biāo)懸停停止this.onmouseenter = function () {cancelAnimationFrame(this.timer);//彈幕停止移動(dòng)function showDetailPopups() {//顯示提示****此處用于展示詳情窗口barrageChileNode.style.display = 'block';}//設(shè)置延遲顯示this.timeOut = setTimeout(showDetailPopups, 1000);};//鼠標(biāo)移走this.onmouseleave = function () {//鼠標(biāo)移走,隱藏提示barrageChileNode.style.display = 'none';barrageAnimate(this);//彈幕繼續(xù)移動(dòng)clearTimeout(this.timeOut)};//打開(kāi)彈幕對(duì)應(yīng)的目標(biāo)頁(yè)面this.onclick = function () {let url = "/detail/",data = {barrage_id:obj.barrageId};$.ajax({type : "get",async : false, //同步請(qǐng)求url : url,data : data,dataType: "json",success:function(barrage){showDetailPanel(barrage)// console.log(barrage)},error: function() {alert("失敗,請(qǐng)稍后再試!");}});};}/*******輔助彈幕移動(dòng)*********///彈幕動(dòng)畫(huà)function barrageAnimate(obj) {move(obj);if (Math.abs(obj.distance) < obj.width + obj.offsetLeft) {//滿足以上條件說(shuō)明彈幕在可見(jiàn)范圍內(nèi)obj.timer = requestAnimationFrame(function () {//在頁(yè)面重繪之前會(huì)調(diào)用這個(gè)回調(diào)函數(shù)-->讓彈幕繼續(xù)移動(dòng)barrageAnimate(obj);});} else {//超出可見(jiàn)范圍,取消回調(diào)函數(shù)的調(diào)用-->讓彈幕停止移動(dòng)cancelAnimationFrame(obj.timer);//刪除節(jié)點(diǎn)obj.parentNode.removeChild(obj);}}//回流:增刪元素會(huì)引起回流,重繪:改變樣式會(huì)引起重繪//彈幕移動(dòng)function move(obj) {obj.distance -= 2; //移動(dòng)速度為一次1像素//transform可以對(duì)元素進(jìn)行翻轉(zhuǎn)、移動(dòng)、傾斜等操作,這里主要使用了移動(dòng)元素的效果obj.style.transform = 'translateX(' + obj.distance + 'px)';}//隨機(jī)獲取區(qū)間內(nèi)的一個(gè)值function getRandom(start, end) {return start + (Math.random() * (end - start)); //Math.random()隨機(jī)獲取一個(gè)0~1之間的值}/*******初始化事件**********/ //整個(gè)事件的入口//獲取彈幕數(shù)據(jù)集let barrageArray = Server.barrages;//循環(huán)彈幕數(shù)組所需的切片次數(shù), 彈幕總數(shù)/垂直可以顯示的彈幕數(shù)=彈幕播放組數(shù)let howManyGroupBarrages = Math.ceil(barrageArray.length / howManyBarrageY);for (let i = 0; i < howManyGroupBarrages; i++) {//對(duì)彈幕數(shù)組切片,取出一部分要顯示的彈幕,一直循環(huán)到取完let eachBarrageArray = barrageArray.slice(howManyBarrageY * i, howManyBarrageY * (i + 1));for (let item of eachBarrageArray) {//遍歷每個(gè)彈幕, 并傳入彈幕元素的索引,和循環(huán)次數(shù)(用作定位)createBarrage(item, eachBarrageArray.indexOf(item), i + 1);}} })();上面的代碼主要完成的了彈幕的生成, 簡(jiǎn)單來(lái)講就是:生成->分組->定位, 下面這張圖能更清楚的表達(dá)邏輯:
PS: 彈幕不重疊還可以使用時(shí)間延遲的方式來(lái)實(shí)現(xiàn), 有興趣的同學(xué)可以參考文章:不碰撞彈幕的研究與實(shí)現(xiàn)
1.3.2>彈幕列表
//Web/App/static/js/barrage_list.js let barrageList = document.querySelector('.barrage-list'),barrageDetailPanel = document.querySelector('.barrage-detail-panel'); //彈幕列表的實(shí)現(xiàn) (function () {let expandBtn = document.querySelector('.expand');expandBtn.onclick = function () {//點(diǎn)擊展開(kāi)再次點(diǎn)擊關(guān)閉if (barrageList.style.display === "none") {barrageList.style.display = "block";}else {barrageList.style.display = "none";}//關(guān)閉詳情頁(yè)顯示列表頁(yè)barrageDetailPanel.style.display = 'none'};let barrageItems = document.getElementsByClassName('barrage-list-item'); //li的集合for (let item of barrageItems){let barrageId = item.getAttribute('data-id');//點(diǎn)擊單項(xiàng)打開(kāi)詳情頁(yè)item.onclick = function () {let url = "/detail/",data = {barrage_id:barrageId};//ajax請(qǐng)求, 攜帶參數(shù)barrage_id$.ajax({type : "get",async : false, //同步請(qǐng)求url : url,data : data,dataType: "json",success:function(barrage){showDetailPanel(barrage)},error: function() {alert("失敗,請(qǐng)稍后再試!");}});};} })();1.3.3>彈幕詳情
//Web/App/static/js/barrage_details.js //展示彈幕詳情頁(yè) function showDetailPanel(obj) {let barrageTitle = document.querySelector('.title'),barrageAuthor = document.querySelector('.author'),barrageCover = document.querySelector('.cover'),barrageURL = document.querySelector('.source');//關(guān)閉列表頁(yè)顯示詳情頁(yè)barrageDetailPanel.style.display = 'block';barrageList.style.display = "none";//設(shè)置詳情頁(yè)的參數(shù)barrageTitle.innerHTML = obj.BText;barrageAuthor.innerHTML = '--' + obj.BAuthor;barrageCover.setAttribute('src', obj.BCover);barrageURL.onclick = function () {window.open(obj.BUrl);}; }//close button event let closeBtns = document.querySelectorAll('.close-btn'); for (let closeBtn of closeBtns){closeBtn.onclick = function () {barrageDetailPanel.style.display = "none";barrageList.style.display = "none";}; }1.4>其它靜態(tài)文件
CSS
https://github.com/zhanghao19/LetMeSee/tree/master/Web/App/static/css
Image
https://github.com/zhanghao19/LetMeSee/tree/master/Web/App/static/css
2>后端
2.1>用flask構(gòu)建網(wǎng)站
# Web/App/views/first_blue.py import random from pymongo import MongoClient from flask import Blueprint, render_template, request, jsonify# Blueprint(藍(lán)圖),提供快速注冊(cè)端口,方便快捷. # https://dormousehole.readthedocs.io/en/latest/blueprints.html#blueprints first_blue = Blueprint('index', __name__) # 創(chuàng)建一個(gè)藍(lán)圖對(duì)象coll = MongoClient(host="localhost", port=27017).Spider.LetMeSee# 從數(shù)據(jù)庫(kù)中獲取數(shù)據(jù) baidu_barrages = [i for i in coll.find({'BType': 'baidu'},{'_id': 0, 'BID': 1, 'BText': 1, 'BUrl': 1, 'BType': 1})]bilibili_barrages = [i for i in coll.find({'BType': 'bilibili'},{'_id': 0, 'BID': 1, 'BText': 1, 'BUrl': 1, 'BType': 1})]zhihu_barrages = [i for i in coll.find({'BType': 'zhihu'},{'_id': 0, 'BID': 1, 'BText': 1, 'BUrl': 1, 'BType': 1})]@first_blue.route('/') def index():# 拼接兩個(gè)彈幕列表barrages = baidu_barrages + bilibili_barrages + zhihu_barragesrandom.shuffle(barrages) # 打亂列表的順序# 渲染模板, 傳遞數(shù)據(jù)return render_template('barrage.html', barrages=barrages)@first_blue.route('/baidu/') def baidu():return render_template('barrage.html', barrages=baidu_barrages)@first_blue.route('/bilibili/') def bilibili():return render_template('barrage.html', barrages=bilibili_barrages)@first_blue.route('/zhihu/') def zhihu():return render_template('barrage.html', barrages=zhihu_barrages)@first_blue.route('/detail/') def barrage_details():# 獲取ajax請(qǐng)求攜帶的data中的barrage_idbarrage_id = request.args.get('barrage_id')# 通過(guò)barrage_id取匹配數(shù)據(jù)庫(kù)里的項(xiàng)barrage = coll.find_one({'BID': barrage_id},{'_id': 0, 'WriteTime': 0})print(barrage, barrage_id, type(barrage_id))# 以json的形式返回響應(yīng)return jsonify(barrage) # Web/App/views/__init__.py from .first_blue import first_blue from Web.App.my_filters.truncate_text import truncate_textdef init_view(app):# 在應(yīng)用對(duì)象上注冊(cè)這個(gè)藍(lán)圖對(duì)象app.register_blueprint(first_blue)# 指定jinja引擎env = app.jinja_env# 加載自定義過(guò)濾器env.filters["truncate_text"] = truncate_text # Web/App/__init__.py from flask import Flaskfrom Web.App.views import init_viewdef create_app():# 創(chuàng)建一個(gè)應(yīng)用對(duì)象app = Flask(__name__)# 調(diào)用該方法,以初始化路由init_view(app)return app # manage.py from flask_script import Managerfrom Web.App import create_appapp = create_app() manager = Manager(app=app)if __name__ == '__main__':manager.run() # 使flask能夠像django一樣使用命令啟動(dòng), "python manage.py runserver -r -d"參考文檔: 快速上手flask / Blueprint / jsonify
參考視頻: 黑馬程序員-6節(jié)課入門Flask框架web開(kāi)發(fā)視頻
ps: 我也是看這個(gè)視頻學(xué)的flask, 老師講解的很棒!
2.2>爬蟲(chóng)
2.2.1>百度新聞
# Spider/spider_mode/baidu_spider.py import requests from datetime import datetime from lxml import etreefrom pymongo import MongoClientcoll = MongoClient(host="localhost", port=27017).Spider.LetMeSeeresp = requests.get('https://news.baidu.com/') # 請(qǐng)求頁(yè)面 html = etree.HTML(resp.text) # 創(chuàng)建xpath對(duì)象 barrage = [] item = {}title_ls = html.xpath('//*[@id="pane-news"]//a//text()') # 提取標(biāo)題 url_ls = html.xpath('//*[@id="pane-news"]//a/@href') # 提取鏈接for n in range(len(title_ls)):item['BID'] = f'{n + 86000}' # iditem['BText'] = title_ls[n]item['BUrl'] = url_ls[n]item['BType'] = 'baidu'item['BCover'] = r'D:\Fire\PycharmProject\LetMeSee\Web\App\static\img\loading.gif' # 封面item['BAuthor'] = '未知作者' # 作者item['WriteTime'] = datetime.utcnow() # 寫(xiě)入時(shí)間, 用于設(shè)置過(guò)期時(shí)間coll.insert_one(dict(item)) print('百度新聞--爬取完成!')2.2.2>B站榜單
# Spider/spider_mode/bilibili_spider.py from datetime import datetime import json import requests import refrom pymongo import MongoClientcoll = MongoClient(host="localhost", port=27017).Spider.LetMeSeeresp = requests.get('https://www.bilibili.com/ranking') # 請(qǐng)求頁(yè)面 # 使用正則獲取源碼中存放在script標(biāo)簽中的數(shù)據(jù) data_url = re.findall('window.__INITIAL_STATE__=(.*);\(function', resp.text)[0] data_loaded = json.loads(data_url) # 使用loads方法從 字符串 變成 字典 rankList = data_loaded['rankList'] # 排行榜中100個(gè)視頻的信息item ={} for i in range(len(rankList)):item['BID'] = f'{i + 81000}' # iditem['BText'] = rankList[i]['title'] # 標(biāo)題item['BAuthor'] = rankList[i]['author'] # 作者item['BUrl'] = 'https://www.bilibili.com/video/' + rankList[i]['bvid'] # 拼接的視頻av號(hào)item['BType'] = 'bilibili'item['BCover'] = rankList[i]['pic'] # 封面item['WriteTime'] = datetime.utcnow() # 寫(xiě)入時(shí)間, 用于設(shè)置過(guò)期時(shí)間coll.insert_one(dict(item)) print('B站榜單--爬取完成!')2.2.3>知乎熱榜
# Spider/spider_mode/zhihu_spider.py import json from datetime import datetimeimport requests from lxml import etree from pymongo import MongoClient# 用戶登錄后的cookies,直接F12->Network復(fù)制Request Headers的cookie即可, 這里只是自己建了一個(gè)放cookies的文件 from util.zhihu_cookies import Cookiescoll = MongoClient(host="localhost", port=27017).Spider.LetMeSeeheaders = {'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8','cache-control': 'max-age=0','cookie': Cookies, # 也可以直接將cookies直接copy到這里'upgrade-insecure-requests': '1','user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36'} resp = requests.get('https://www.zhihu.com/hot', headers=headers) # 請(qǐng)求頁(yè)面html = etree.HTML(resp.text) # 創(chuàng)建xpath對(duì)象data = html.xpath('//*[@id="js-initialData"]/text()')[0] # 提取數(shù)據(jù)集 data_loaded = json.loads(data) # 使用loads方法從 字符串 變成 字典 hotList = data_loaded["initialState"]["topstory"]["hotList"] # 提取目標(biāo)數(shù)據(jù)'hotList'item ={} for i in range(len(hotList)):item['BID'] = f'{i + 83000}' # iditem['BText'] = hotList[i]["target"]["titleArea"]["text"] # 標(biāo)題item['BAuthor'] = hotList[i]["target"]["metricsArea"]["text"] # 標(biāo)題item['BUrl'] = hotList[i]["target"]["link"]["url"] # 拼接的視頻av號(hào)item['BType'] = 'zhihu'item['BCover'] = hotList[i]["target"]["imageArea"]["url"] # 封面item['WriteTime'] = datetime.utcnow() # 寫(xiě)入時(shí)間, 用于設(shè)置過(guò)期時(shí)間coll.insert_one(dict(item)) print('知乎熱榜--爬取完成!')2.3>運(yùn)行爬蟲(chóng)
爬蟲(chóng)文件都可以直接運(yùn)行, 為了節(jié)省不必要的時(shí)間, 所以將它們整理到一個(gè)文件中運(yùn)行, 如下:
# Spider/runSpider.py from pymongo import MongoClient import os# 創(chuàng)建數(shù)據(jù)庫(kù)對(duì)象 coll = MongoClient(host="localhost", port=27017).Spider.LetMeSee coll.drop() # 清空LetMeSee, 目的是使數(shù)據(jù)保持最新 # 設(shè)置延遲刪除字段, 單位為秒 coll.create_index([('WriteTime', 1)], expireAfterSeconds=43200)os.system(r"python D:\Fire\PycharmProject\LetMeSee\Spider\spider_mode\bilibili_spider.py") os.system(r"python D:\Fire\PycharmProject\LetMeSee\Spider\spider_mode\baidu_spider.py") os.system(r"python D:\Fire\PycharmProject\LetMeSee\Spider\spider_mode\zhihu_spider.py")3>總結(jié)
好了以上就是本次分享的全部?jī)?nèi)容了, 目前項(xiàng)目的規(guī)模不算大, 但有很大的擴(kuò)展性, 后續(xù)如果有更多點(diǎn)子會(huì)再更新這個(gè)項(xiàng)目.
總結(jié)
以上是生活随笔為你收集整理的搭建一个弹幕新闻网站的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: swarm集群搭建教程
- 下一篇: 检测本地连接并自动连接宽带连接.cmd