搭建一個彈幕新聞網站

本項目僅供學習使用, 請勿用來進行商業用途

本期知識點:

  1. 使用JS製作彈幕的方法
  2. 使用分組定位來實現彈幕不重疊
  3. 使用flask構建網站
  4. 爬蟲: 百度新聞, B站榜單, 知乎熱榜

前言

你是否在 刷B站 或 刷知乎 時覺得不夠暢? 是否想在一個平臺上同時獲取多個平臺的有趣內容?

這個網站將爲你打開一扇快速通道

先來看效果

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-DZkmz6Nx-1588593087094)()]

  1. 彈幕可分類顯示, 也可以全部顯示(可自己添加更多網站, 接口的使用方法見下文)
  2. 彈幕列表展示當前網站上顯示的所有彈幕
  3. 點擊彈幕可以查看詳情, 包括作者/熱度 和預覽圖(可擴展)
  4. 前後端分離, 後端無論使用什麼語言和框架, 只要有數據傳輸到接口即可實現.

製作網站的緣由是我在刷新聞時的突發奇想, 純屬個人愛好, 項目源碼: https://github.com/zhanghao19/LetMeSee

網站的核心框架選擇的是Flask, 優勢是便捷, 且官方文檔中有詳細的入門教程: 快速上手flask

文章的描述順序也是筆者搭建的流程

1>前端

彈幕新聞的重點在於展示, 其原理簡單來說就像"往杯子裏倒水"一樣

1.1>網站框架

這裏網站的框架指的是彈幕所顯示在的地方, 我使用的是之前在學習Django的時候搭建的一個框架

以原網站作爲基礎框架, 使用jinja的繼承功能來使我們的主要內容融入基礎框架

你可以使用任意一款你喜歡的網站模板, 來作爲放置彈幕的容器, 參考網站: Bootstrap

下載好你的模板, 參考以下代碼中的block位置, 對自己的模板進行靜態抽取:

<!-- 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">
    <!-- 上面的是模板自帶的靜態文件, 下面是爲項目需要準備的 -->
    {% 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">
        <!-- 這裏是導航條上的一些選項-->
          {% 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>網站內容

這裏的內容是彈幕的主體, 可以放在大部分的網站模板上使用

下面的代碼包含, 彈幕的容器, 彈幕列表, 彈幕詳情頁

<!-- Web/App/templates/barrage.html -->
{% extends 'base.html' %}
{% block title %}LetMeSee-彈幕新聞網{% endblock %}
{% block link %}
    <link rel="stylesheet" href="../static/css/barrage.css">
    <!-- 解決圖片加載失敗的問題 -->
    <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="關閉">
        </div>
        <ul>
            {% for barrage in barrages %}
                <!-- for循環展示彈幕 -->
                <li class="barrage-list-item" data-id="{{ barrage.BID }}">
                    <!-- truncate_text過濾器,過長字符串末尾顯示爲... -->
                    {{ 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="關閉">
        </div>
        <h3 class="title"></h3>
        <p class="author"></p>
        <img src="../static/img/loading.gif" alt="彈幕封面" class="cover">
        <a class="source"><--查看源網頁--></a>
    </div>
    <!-- 彈幕列表 彈幕詳情 -->
{% endblock %}
{% block script %}
    <script type="text/javascript">
    //js和html文件是分開的,傳遞數據需要先定義好參數,再執行js。參考:https://blog.csdn.net/m0_38061194/article/details/78891125
        var 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 %}

自定義的過濾器truncate_text如下, 作用是過長字符串末尾顯示爲…

# Web/App/my_filters/truncate_text.py
def truncate_text(text):
    if len(text) > 19:
        new_text = text[0:17] + "..."
        return new_text
    else:
        return text

整理一下上面代碼在頁面中實現的框架, 如圖(同色表示同級):

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-7Wzh5zAL-1588593087098)()]

  1. barrage-container-wrap是彈幕容器的底層畫布, barrage-container是盛放彈幕的容器

  2. barrege-listbarrage-detail是觸發點擊事件才顯示的.

1.3>JS部分

1.3.1>彈幕主體

網上有很多中彈幕的設計方式, 個人認爲區別點在於彈幕的不重疊, 本次使用的方式是通過分組定位來實現彈幕不重疊.

//Web/App/static/js/barrage.js
//彈幕的實現
(function () {
    /*******定義參數********/
    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', '');
    //當前窗口可以垂直展示多少個彈幕, 30代表彈幕字體大小
    let howManyBarrageY = Math.round(boxHeight / 30);
    //定義一個包含彈幕的寬和高度範圍的數組
    let heightArray = [];
    //將每個可用的高度,放入數組, 以便在創建數組時使用
    for (let i = 30; i < boxHeight - 10; i += 30) {
        heightArray.push(i)
    }

    /*******創建彈幕**********/
    function createBarrage(item, index, forTime) {
        if (index >= howManyBarrageY) {
            //如果索引達到高度數組的長度,則需重置索引到0,因此取餘數
            index = index % howManyBarrageY;
        }
        let divNode = document.createElement('div');    //彈幕的標籤
        let divChildNode = document.createElement('div');  //提示文本的標籤

        divNode.innerHTML = item.BText;    //將彈幕內容插入標籤中, innerHTML表示這個標籤中的字符內容
        divNode.classList.add('barrage-item');  //追加class
        barrageBox.appendChild(divNode);    //彈幕的標籤作爲彈幕容器的子代標籤

        divChildNode.innerHTML = '點擊查看詳情';  //鼠標懸停展示的內容
        divChildNode.classList.add('barrage-link');
        divNode.appendChild(divChildNode);  //提示文本的標籤作爲彈幕標籤的子代標籤

        //***設置彈幕的初始位置***
        //以容器的寬度爲基準隨機生成每條彈幕的左側偏移值
        let barrageOffsetLeft = getRandom(contentWidth * forTime, contentWidth * (forTime + 0.618));
        //以容器的高度爲基準隨機生成每條彈幕的上方偏移值
        let barrageOffsetTop = heightArray[index];
        //通過彈幕類型選擇顏色
        let barrageColor = barrageColorArray[item.BType];
        
        //執行初始化滾動
        //fun.call()傳入的第一個參數作爲之後的this,詳解:https://codeplayer.vip/p/j7sj5
        initBarrage.call(divNode, {
            left: barrageOffsetLeft,
            top: barrageOffsetTop,
            color: barrageColor,
            barrageId: item.BID,
        });
    }

    /*******初始化彈幕移動(速度,延遲)*********/
    function initBarrage(obj) {
        //初始化位置顏色
        this.style.left = obj.left + 'px';
        this.style.top = obj.top + 'px';
        this.style.color = obj.color;

        //添加屬性
        this.distance = 0;  //移動速度基準值
        this.width = ~~window.getComputedStyle(this).width.replace('px', '');   //彈幕的長度
        this.offsetLeft = obj.left;
        this.timer = null;
        this.timeOut = null;

        //彈幕子節點,即提示信息,span標籤
        let barrageChileNode = this.children[0];
        barrageChileNode.style.left = (this.width - barrageTipWidth) / 2 + 'px';//定義span標籤的位置

        //運動
        barrageAnimate(this);

        //鼠標懸停停止
        this.onmouseenter = function () {
            cancelAnimationFrame(this.timer);//彈幕停止移動
            function showDetailPopups() {
                //顯示提示****此處用於展示詳情窗口
                barrageChileNode.style.display = 'block';
            }
            //設置延遲顯示
            this.timeOut = setTimeout(showDetailPopups, 1000);
        };

        //鼠標移走
        this.onmouseleave = function () {
            //鼠標移走,隱藏提示
            barrageChileNode.style.display = 'none';
            barrageAnimate(this);//彈幕繼續移動
            clearTimeout(this.timeOut)
        };

        //打開彈幕對應的目標頁面
        this.onclick = function () {
            let url = "/detail/",
                data = {barrage_id:obj.barrageId};
            $.ajax({
                type : "get",
                async : false,  //同步請求
                url : url,
                data : data,
                dataType: "json",
                success:function(barrage){
                    showDetailPanel(barrage)
                    // console.log(barrage)
                },
                error: function() {
                   alert("失敗,請稍後再試!");
                }
            });
        };
    }
    
    /*******輔助彈幕移動*********/
    //彈幕動畫
    function barrageAnimate(obj) {
        move(obj);

        if (Math.abs(obj.distance) < obj.width + obj.offsetLeft) {
            //滿足以上條件說明彈幕在可見範圍內
            obj.timer = requestAnimationFrame(function () {
                //在頁面重繪之前會調用這個回調函數-->讓彈幕繼續移動
                barrageAnimate(obj);
            });
        } else {
            //超出可見範圍,取消回調函數的調用-->讓彈幕停止移動
            cancelAnimationFrame(obj.timer);
            //刪除節點
            obj.parentNode.removeChild(obj);
        }
    }//迴流:增刪元素會引起迴流,重繪:改變樣式會引起重繪
    
    //彈幕移動
    function move(obj) {
        obj.distance -= 2; //移動速度爲一次1像素
        //transform可以對元素進行翻轉、移動、傾斜等操作,這裏主要使用了移動元素的效果
        obj.style.transform = 'translateX(' + obj.distance + 'px)';
    }

    //隨機獲取區間內的一個值
    function getRandom(start, end) {
        return start + (Math.random() * (end - start)); //Math.random()隨機獲取一個0~1之間的值
    }

    /*******初始化事件**********/    //整個事件的入口
    //獲取彈幕數據集
    let barrageArray = Server.barrages;
    //循環彈幕數組所需的切片次數, 彈幕總數/垂直可以顯示的彈幕數=彈幕播放組數
    let howManyGroupBarrages = Math.ceil(barrageArray.length / howManyBarrageY);
    for (let i = 0; i < howManyGroupBarrages; i++) {
        //對彈幕數組切片,取出一部分要顯示的彈幕,一直循環到取完
        let eachBarrageArray = barrageArray.slice(howManyBarrageY * i, howManyBarrageY * (i + 1));
        for (let item of eachBarrageArray) {
            //遍歷每個彈幕, 並傳入彈幕元素的索引,和循環次數(用作定位)
            createBarrage(item, eachBarrageArray.indexOf(item), i + 1);
        }
    }
})();

上面的代碼主要完成的了彈幕的生成, 簡單來講就是:生成->分組->定位, 下面這張圖能更清楚的表達邏輯:

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-PoJM59hU-1588593087101)()]

  1. 初始化彈幕: 從後端獲取彈幕數據. 計算屏幕的高度可以顯示多少彈幕, 並對其進行切片分組. 然後傳入創建彈幕事件.
  2. 創建彈幕: 在一個指定區域內, 通過隨機值的方式設置彈幕的初始位置. 將設置好的彈幕元素傳入初始化彈幕移動事件.
  3. 初始化彈幕移動: 左側偏移值遞減, 從而使彈幕移動, 然後將元素帶入移動動畫方法使移動軌跡更絲滑. 同時給彈幕元素設置一些事件(滑入, 滑出, 點擊)
  4. 到這裏第一組彈幕就開始移動了, 之所以彈幕會順序播放且不會重疊, 根本原因就是他們的初始位置有足夠的距離.

PS: 彈幕不重疊還可以使用時間延遲的方式來實現, 有興趣的同學可以參考文章:不碰撞彈幕的研究與實現

1.3.2>彈幕列表

//Web/App/static/js/barrage_list.js
let barrageList = document.querySelector('.barrage-list'),
    barrageDetailPanel = document.querySelector('.barrage-detail-panel');
//彈幕列表的實現
(function () {
    let expandBtn = document.querySelector('.expand');
    expandBtn.onclick = function () {
        //點擊展開再次點擊關閉
        if (barrageList.style.display === "none") {
            barrageList.style.display = "block";
        }else {
            barrageList.style.display = "none";
        }
        //關閉詳情頁顯示列表頁
        barrageDetailPanel.style.display = 'none'
    };

    let barrageItems = document.getElementsByClassName('barrage-list-item');    //li的集合
    for (let item of barrageItems){
        let barrageId = item.getAttribute('data-id');
        //點擊單項打開詳情頁
        item.onclick = function () {
            let url = "/detail/",
                data = {barrage_id:barrageId};
            //ajax請求, 攜帶參數barrage_id
            $.ajax({
                type : "get",
                async : false,  //同步請求
                url : url,
                data : data,
                dataType: "json",
                success:function(barrage){
                    showDetailPanel(barrage)
                },
                error: function() {
                   alert("失敗,請稍後再試!");
                }
            });
        };
    }
})();

1.3.3>彈幕詳情

//Web/App/static/js/barrage_details.js
//展示彈幕詳情頁
function showDetailPanel(obj) {
    let barrageTitle = document.querySelector('.title'),
        barrageAuthor = document.querySelector('.author'),
        barrageCover = document.querySelector('.cover'),
        barrageURL = document.querySelector('.source');
    //關閉列表頁顯示詳情頁
    barrageDetailPanel.style.display = 'block';
    barrageList.style.display = "none";
    //設置詳情頁的參數
    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>其它靜態文件

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構建網站

# Web/App/views/first_blue.py
import random
from pymongo import MongoClient
from flask import Blueprint, render_template, request, jsonify

# Blueprint(藍圖),提供快速註冊端口,方便快捷.
# https://dormousehole.readthedocs.io/en/latest/blueprints.html#blueprints
first_blue = Blueprint('index', __name__)   # 創建一個藍圖對象

coll = MongoClient(host="localhost", port=27017).Spider.LetMeSee

# 從數據庫中獲取數據
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():
    # 拼接兩個彈幕列表
    barrages = baidu_barrages + bilibili_barrages + zhihu_barrages
    random.shuffle(barrages)    # 打亂列表的順序
    # 渲染模板, 傳遞數據
    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請求攜帶的data中的barrage_id
    barrage_id = request.args.get('barrage_id')
    # 通過barrage_id取匹配數據庫裏的項
    barrage = coll.find_one(
        {'BID': barrage_id},
        {'_id': 0, 'WriteTime': 0})
    print(barrage, barrage_id, type(barrage_id))
    # 以json的形式返回響應
    return jsonify(barrage)

# Web/App/views/__init__.py
from .first_blue import first_blue
from Web.App.my_filters.truncate_text import truncate_text


def init_view(app):
    # 在應用對象上註冊這個藍圖對象
    app.register_blueprint(first_blue)
    # 指定jinja引擎
    env = app.jinja_env
    # 加載自定義過濾器
    env.filters["truncate_text"] = truncate_text
    
# Web/App/__init__.py
from flask import Flask

from Web.App.views import init_view


def create_app():
    # 創建一個應用對象
    app = Flask(__name__)
    # 調用該方法,以初始化路由
    init_view(app)
    return app

# manage.py
from flask_script import Manager

from Web.App import create_app

app = create_app()
manager = Manager(app=app)

if __name__ == '__main__':
    manager.run()	# 使flask能夠像django一樣使用命令啓動, "python manage.py runserver -r -d"
    

參考文檔: 快速上手flask / Blueprint / jsonify

參考視頻: 黑馬程序員-6節課入門Flask框架web開發視頻

ps: 我也是看這個視頻學的flask, 老師講解的很棒!

2.2>爬蟲

2.2.1>百度新聞

# Spider/spider_mode/baidu_spider.py
import requests
from datetime import datetime
from lxml import etree

from pymongo import MongoClient

coll = MongoClient(host="localhost", port=27017).Spider.LetMeSee

resp = requests.get('https://news.baidu.com/')	# 請求頁面
html = etree.HTML(resp.text)	# 創建xpath對象
barrage = []
item = {}

title_ls = html.xpath('//*[@id="pane-news"]//a//text()')	# 提取標題
url_ls = html.xpath('//*[@id="pane-news"]//a/@href')	# 提取鏈接

for n in range(len(title_ls)):
    item['BID'] = f'{n + 86000}'  # id
    item['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()  # 寫入時間, 用於設置過期時間
    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 re

from pymongo import MongoClient

coll = MongoClient(host="localhost", port=27017).Spider.LetMeSee

resp = requests.get('https://www.bilibili.com/ranking')	# 請求頁面
# 使用正則獲取源碼中存放在script標籤中的數據
data_url = re.findall('window.__INITIAL_STATE__=(.*);\(function', resp.text)[0]
data_loaded = json.loads(data_url)  # 使用loads方法從 字符串 變成 字典
rankList = data_loaded['rankList']  # 排行榜中100個視頻的信息

item ={}
for i in range(len(rankList)):
    item['BID'] = f'{i + 81000}'     # id
    item['BText'] = rankList[i]['title']    # 標題
    item['BAuthor'] = rankList[i]['author']  # 作者
    item['BUrl'] = 'https://www.bilibili.com/video/' + rankList[i]['bvid']   # 拼接的視頻av號
    item['BType'] = 'bilibili'
    item['BCover'] = rankList[i]['pic']    # 封面
    item['WriteTime'] = datetime.utcnow()   # 寫入時間, 用於設置過期時間
    coll.insert_one(dict(item))
print('B站榜單--爬取完成!')

2.2.3>知乎熱榜

# Spider/spider_mode/zhihu_spider.py
import json
from datetime import datetime

import requests
from lxml import etree
from pymongo import MongoClient

# 用戶登錄後的cookies,直接F12->Network複製Request Headers的cookie即可, 這裏只是自己建了一個放cookies的文件
from util.zhihu_cookies import Cookies


coll = MongoClient(host="localhost", port=27017).Spider.LetMeSee

headers = {'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)	# 請求頁面

html = etree.HTML(resp.text)	# 創建xpath對象

data = html.xpath('//*[@id="js-initialData"]/text()')[0]	# 提取數據集
data_loaded = json.loads(data)	# 使用loads方法從 字符串 變成 字典
hotList = data_loaded["initialState"]["topstory"]["hotList"]	# 提取目標數據'hotList'

item ={}
for i in range(len(hotList)):
    item['BID'] = f'{i + 83000}'     # id
    item['BText'] = hotList[i]["target"]["titleArea"]["text"]    # 標題
    item['BAuthor'] = hotList[i]["target"]["metricsArea"]["text"]    # 標題
    item['BUrl'] = hotList[i]["target"]["link"]["url"]   # 拼接的視頻av號
    item['BType'] = 'zhihu'
    item['BCover'] = hotList[i]["target"]["imageArea"]["url"]    # 封面
    item['WriteTime'] = datetime.utcnow()   # 寫入時間, 用於設置過期時間
    coll.insert_one(dict(item))
print('知乎熱榜--爬取完成!')

2.3>運行爬蟲

爬蟲文件都可以直接運行, 爲了節省不必要的時間, 所以將它們整理到一個文件中運行, 如下:

# Spider/runSpider.py
from pymongo import MongoClient
import os


# 創建數據庫對象
coll = MongoClient(host="localhost", port=27017).Spider.LetMeSee
coll.drop()	# 清空LetMeSee, 目的是使數據保持最新
# 設置延遲刪除字段, 單位爲秒
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>總結

好了以上就是本次分享的全部內容了, 目前項目的規模不算大, 但有很大的擴展性, 後續如果有更多點子會再更新這個項目.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章