畢設(shè)實(shí)戰(zhàn):爬蟲、NLP與前后端分離全流程)
簡介基于Python語言開發(fā)的旅游景點(diǎn)評論情感分析畢業(yè)設(shè)計(jì)項(xiàng)目集成攜程、馬蜂窩爬蟲采用前后端分離架構(gòu)。面向計(jì)算機(jī)、通信、人工智能、自動化等專業(yè)的學(xué)生、老師或從業(yè)者既可用于期末課程設(shè)計(jì)、課程大作業(yè)也可作為畢業(yè)設(shè)計(jì)的完整參考方案解決景點(diǎn)評論數(shù)據(jù)采集、文本情感分析及結(jié)果展示等關(guān)鍵問題。zip壓縮包共102個(gè)文件大小約47.71MB其中32個(gè)py源碼承載爬蟲、情感分析、后端接口等核心邏輯10個(gè)vue組件與6個(gè)js腳本搭建前端界面4個(gè)json、3個(gè)html及md/txt文檔輔助配置與使用說明結(jié)構(gòu)清晰便于按模塊查看。項(xiàng)目為答辯評審98分的個(gè)人畢設(shè)全部代碼經(jīng)過調(diào)試測試可運(yùn)行覆蓋從數(shù)據(jù)采集、文本預(yù)處理、情感分類到可視化展示的完整鏈路既有新手友好的學(xué)習(xí)價(jià)值也有較強(qiáng)的擴(kuò)展空間有基礎(chǔ)者可根據(jù)需要調(diào)整爬蟲目標(biāo)、優(yōu)化模型或增加圖表。目前已有228人學(xué)習(xí)下載適合作為計(jì)算機(jī)、人工智能等相關(guān)方向的課題參考與二次開發(fā)基礎(chǔ)。1. 這套旅游評論情感分析系統(tǒng)98 分畢設(shè)里真正能跑起來的東西先說結(jié)論這是一套前后端分離的旅游景點(diǎn)評論情感分析項(xiàng)目爬蟲端覆蓋攜程和馬蜂窩兩個(gè)平臺分析端對評論做情感極性判定最終通過注冊登錄、景點(diǎn)篩選、結(jié)果圖表把整個(gè)流程串起來。作者在答辯里拿到 98 分不是靠概念堆出來的而是因?yàn)槊總€(gè)環(huán)節(jié)都有可演示的產(chǎn)物——你打開前端頁面選一個(gè)景點(diǎn)系統(tǒng)能從爬蟲抓取一直跑到情感分布圖渲染。對于要做 Python 畢業(yè)設(shè)計(jì)、課程大作業(yè)或者想入門爬蟲與 NLP 結(jié)合的從業(yè)者來說這套系統(tǒng)的價(jià)值在于它把爬蟲、數(shù)據(jù)清洗、情感分析、前后端交互四條線完整打通了。我拆完這套資源后的直觀感受是代碼量不大但工程結(jié)構(gòu)比大多數(shù)“只有一個(gè) notebook”的畢設(shè)完整得多值得照著復(fù)現(xiàn)一遍。2. 前后端分離的工程骨架Quasar 前端與 Python 后端的啟動順序2.1 先從 quasar.conf.js 看懂前端的真實(shí)身份這套系統(tǒng)前端目錄里有 index.html、result.html、index.template.html、quasar.conf.js稍微熟悉 Vue 生態(tài)的人一眼就能認(rèn)出來這是 Quasar 框架的項(xiàng)目結(jié)構(gòu)。Quasar 是一套基于 Vue 的 UI 框架官方定位是“一套代碼編譯成 SPA、SSR、PWA 甚至移動端”畢設(shè)用它來寫后臺管理類頁面非常合適因?yàn)楸砀?、表單、圖表組件開箱即用不用像手寫 Bootstrap 那樣拼半天。quasar.conf.js 是這個(gè)前端項(xiàng)目的核心配置文件里面主要做三件事聲明要用哪些 Quasar 插件比如 Loading、Notify、配置 dev server 的端口和代理、定義構(gòu)建產(chǎn)物的輸出路徑。注意這里的 dev server 端口默認(rèn)是 8080而后端 Python 服務(wù)我拆下來看默認(rèn)跑在 5000 或 8000 端口兩者不同源所以前端請求后端接口時(shí)大概率會遇到跨域問題——這一點(diǎn)我會在第 5 章專門講實(shí)際上這個(gè)項(xiàng)目里已經(jīng)內(nèi)置了代理方案但你如果直接雙擊 index.html 打開是跑不起來的必須通過 quasar dev 啟動。2.2 后端 Python 服務(wù)的路由設(shè)計(jì)與數(shù)據(jù)流向后端的核心邏輯按模塊拆分爬蟲模塊負(fù)責(zé)抓取評論情感分析模塊負(fù)責(zé)對評論文本打分API 層負(fù)責(zé)把結(jié)果暴露成 HTTP 接口。一個(gè)典型的數(shù)據(jù)流向是用戶在前端選擇景點(diǎn) → 前端調(diào)用后端/api/analyze接口 → 后端讀取該景點(diǎn)在數(shù)據(jù)庫里已有的評論 → 情感分析模塊逐條打分 → 返回各情感類別的統(tǒng)計(jì)結(jié)果和樣例評論 → 前端用 ECharts 渲染餅圖和柱狀圖。# app.py 中的核心路由示意 from flask import Flask, jsonify, request from analyzer import SentimentAnalyzer from db import get_reviews_by_scenic app Flask(__name__) analyzer SentimentAnalyzer() app.route(/api/analyze, methods[POST]) def analyze(): scenic_id request.json.get(scenic_id) reviews get_reviews_by_scenic(scenic_id) if not reviews: return jsonify({code: 404, msg: 該景點(diǎn)暫無評論數(shù)據(jù)請先爬取}) result analyzer.analyze_batch(reviews) return jsonify({code: 0, data: result})這個(gè)路由做的事情非常直白拿到前端傳來的景點(diǎn) ID去數(shù)據(jù)庫撈評論丟給情感分析器批量處理最后把結(jié)構(gòu)化結(jié)果返回。值得留意的是analyze_batch這個(gè)方法它不是簡單地 for 循環(huán)而是內(nèi)部先做文本清洗再逐條走分詞和詞表匹配最后按正面、負(fù)面、中性三個(gè)類別做聚合統(tǒng)計(jì)。2.3 依賴安裝與啟動順序先后端后前端很多第一次跑這個(gè)項(xiàng)目的人翻車不是因?yàn)榇a有問題而是啟動順序錯(cuò)了。后端 Flask 服務(wù)如果沒起來前端頁面能打開但所有接口全部報(bào)錯(cuò)頁面看起來是“白屏控制臺一片紅”。正確的順序是先裝后端依賴啟動 Python 服務(wù)再啟動 Quasar 前端。# 第一步安裝后端依賴Python 3.8 環(huán)境 pip install flask flask-cors requests jieba sqlalchemy pymysql # 第二步啟動后端服務(wù) python app.py # 第三步進(jìn)入前端目錄安裝依賴并啟動 cd frontend npm install npx quasar dev這套順序里有幾個(gè)參數(shù)需要按你自己的環(huán)境改數(shù)據(jù)庫連接串在db.py里默認(rèn)我拆包看到的是 MySQL 的配置如果你本地沒裝 MySQL可以直接改 SQLite改動量大約是 10 行Flask 的端口如果在app.run(port5000)被占用改成 5001 后前端quasar.conf.js里的 proxy 目標(biāo)端口也要同步改否則代理轉(zhuǎn)發(fā)會失效。啟動完成后訪問http://localhost:8080能看到登錄注冊頁說明前端起來了再往后端http://localhost:5000/api/ping發(fā)一個(gè) GET 請求返回 JSON 說明鏈路通了一半。3. 攜程與馬蜂窩評論爬蟲請求偽裝、分頁抓取與字段落庫3.1 兩個(gè)平臺的反爬差異與應(yīng)對策略攜程和馬蜂窩的評論接口形態(tài)完全不一樣。攜程的評論數(shù)據(jù)走的是一套內(nèi)部 API返回 JSON 結(jié)構(gòu)里面嵌套了用戶名、評分、評論內(nèi)容、點(diǎn)評時(shí)間等字段但請求頭里必須帶特定的 Referer 和 User-Agent否則直接拒絕服務(wù)。馬蜂窩則是服務(wù)端渲染的 HTML 頁面評論數(shù)據(jù)混在 DOM 節(jié)點(diǎn)里需要先請求頁面再用 XPath 或正則抽取而且它的列表頁有滾動懶加載直接 requests 只能拿到前幾條。這套系統(tǒng)的爬蟲代碼里對兩個(gè)平臺分別寫了獨(dú)立的爬蟲類公共部分抽了一個(gè) BaseCrawler里面封裝了帶重試的請求方法。核心思路就是把請求頭偽裝成真實(shí)瀏覽器攜程接口用requests.get帶 params 拉取馬蜂窩用requests.get拿 HTML 后用lxml解析。# crawler_ctrip.py 的核心抓取邏輯節(jié)選 import requests from lxml import etree class CtripCrawler: def __init__(self): self.headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36, Referer: https://you.ctrip.com/, Accept: application/json, } self.base_url https://you.ctrip.com/sight/{poi_id}/comment-list.html def fetch_comments(self, poi_id, pages5): all_comments [] for page in range(1, pages 1): resp requests.get( self.base_url.format(poi_idpoi_id), params{start: (page - 1) * 10}, headersself.headers, timeout10 ) data resp.json() items data.get(data, {}).get(commentList, []) for item in items: all_comments.append({ user: item.get(userName), content: item.get(content), score: item.get(score), time: item.get(commentTime) }) return all_comments這個(gè)實(shí)現(xiàn)里有幾個(gè)參數(shù)是實(shí)際調(diào)試時(shí)最關(guān)鍵的點(diǎn)params里的start控制分頁偏移攜程每頁固定 10 條timeout10是給每個(gè)請求的上限防止某個(gè) IP 被限制后卡住整個(gè)爬蟲poi_id是景點(diǎn)在攜程內(nèi)部的唯一 ID這個(gè) ID 怎么找打開攜程景點(diǎn)頁URL 里sight/后面那串?dāng)?shù)字就是。3.2 馬蜂窩的滾動加載問題與 XPath 字段抽取馬蜂窩的評論列表頁不是分頁按鈕而是“滾動到底部加載更多”這是典型的動態(tài)加載頁面。直接 requests 拿到的 HTML 里只有第一屏的數(shù)據(jù)。這套系統(tǒng)里處理方式很務(wù)實(shí)分析頁面里預(yù)埋的window.__INITIAL_STATE__全局變量這個(gè)變量里包含了前幾頁的評論數(shù)據(jù)夠演示用了。如果要做大樣本采集再考慮用 Selenium 模擬滾動但畢設(shè)場景下沒必要引入那么重的依賴。# crawler_mafengwo.py 的 HTML 解析邏輯 import requests from lxml import etree import json import re class MafengwoCrawler: def __init__(self): self.headers { User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X), Accept: text/html,application/xhtmlxml } def fetch_comments(self, scenic_id, pages3): url fhttps://www.mafengwo.cn/poi/{scenic_id}.html resp requests.get(url, headersself.headers, timeout10) html resp.text # 提取預(yù)埋在頁面里的初始數(shù)據(jù) match re.search(rwindow\.__INITIAL_STATE__\s*\s*(.*?)/script, html) if not match: return [] state json.loads(match.group(1)) comments state.get(commentList, []) return [{ user: c.get(nickname), content: c.get(comment), score: c.get(score, 0), time: c.get(date) } for c in comments]這里值得注意的細(xì)節(jié)是 User-Agent 用了 iPhone 的標(biāo)識因?yàn)轳R蜂窩移動端的反爬策略比 PC 端寬松返回的 HTML 結(jié)構(gòu)也更規(guī)整。re.search的正則里.*?是非貪婪匹配確保拿到第一個(gè)/script前的內(nèi)容如果頁面改版導(dǎo)致結(jié)構(gòu)變化最先報(bào)錯(cuò)的就是這一行。整體看下來馬蜂窩的爬蟲實(shí)現(xiàn)比攜程更簡單但容錯(cuò)性也差一些后面第 5 章我會講它最容易踩的坑。3.3 評論去重與字段清洗兩個(gè)平臺的評論字段并不一致馬蜂窩沒有評分字段或者評分為空攜程的評論內(nèi)容里可能帶“發(fā)布于”之類的雜質(zhì)文字。這套系統(tǒng)在寫入數(shù)據(jù)庫之前做了一層清洗和去重。清洗邏輯是去掉空白字符和 HTML 標(biāo)簽按長度過濾掉低于 5 個(gè)字的評論去重邏輯是對評論內(nèi)容做 MD5 哈希存入數(shù)據(jù)庫時(shí)加唯一索引重復(fù)評論直接忽略。采集字段最終落庫的結(jié)構(gòu)如下字段名類型說明idINT 自增主鍵scenic_nameVARCHAR(64)景點(diǎn)名稱sourceVARCHAR(16)來源平臺ctrip / mafengwouser_nameVARCHAR(64)用戶昵稱contentTEXT清洗后的評論文本scoreFLOAT評分?jǐn)y程有值馬蜂窩可能為 0comment_timeDATETIME評論時(shí)間content_hashCHAR(32)內(nèi)容 MD5用于去重這個(gè)表結(jié)構(gòu)是這套系統(tǒng)里比較有價(jià)值的工程設(shè)計(jì)。content_hash字段配合數(shù)據(jù)庫唯一索引能從源頭杜絕重復(fù)數(shù)據(jù)污染后續(xù)的情感分析結(jié)果。4. 情感分析核心分詞、詞表打分與統(tǒng)計(jì)接口的實(shí)現(xiàn)思路4.1 jieba 分詞與自定義詞典的作用情感分析模塊的第一步是分詞。這套系統(tǒng)用的是 jieba 分詞庫默認(rèn)詞典對通用文本效果不錯(cuò)但旅游評論里有大量景點(diǎn)名、地名、口語化表達(dá)比如“迪士尼”“外灘”“打卡”默認(rèn)分詞經(jīng)常會切成“迪斯 尼”或者“打 卡”影響后續(xù)情感詞的匹配。# analyzer.py 中的分詞與清洗 import jieba import re STOP_WORDS {的, 了, 是, 在, 就, 都, 也, 很, 有, 這, 那} def clean_and_tokenize(text): # 去 HTML 標(biāo)簽和特殊符號 text re.sub(r.*?, , text) text re.sub(r[^\u4e00-\u9fa5a-zA-Z0-9], , text) words jieba.lcut(text) # 過濾停用詞和單字 return [w for w in words if w not in STOP_WORDS and len(w.strip()) 1]這里的核心參數(shù)是STOP_WORDS集合它直接決定情感分析的準(zhǔn)確率。如果停用詞太少“不算差”“不太行”里的“不”會被抽走變成正向情感停用詞太多又會把“不錯(cuò)”里的“不”誤殺。常見的做法是維護(hù)一個(gè)針對旅游評論場景的停用詞表把“確實(shí)”“真的”“簡直”這類程度副詞保留下來——它們雖然在停用詞名單里但在情感分析里起著語氣強(qiáng)化作用一般不建議過濾。實(shí)戰(zhàn)中我一般會把“沒”“不”“別”這幾個(gè)否定詞單獨(dú)處理因?yàn)樗鼈兊某霈F(xiàn)會讓整句情感反轉(zhuǎn)。4.2 正負(fù)向詞表打分機(jī)制這套系統(tǒng)的情感判定沒有用復(fù)雜的深度學(xué)習(xí)模型而是采用基于情感詞典的極性打分。原理是構(gòu)建一個(gè)正面詞表和一個(gè)負(fù)面詞表每個(gè)詞帶一個(gè)權(quán)重分詞結(jié)果逐一匹配詞表累計(jì)得分。得分大于閾值判定為正向小于負(fù)閾值判定為負(fù)向中間歸為中性。# analyzer.py 的情感打分核心 class SentimentAnalyzer: def __init__(self): self.positive_words {好評: 2, 漂亮: 1.5, 值得: 1.5, 推薦: 2, 滿意: 2} self.negative_words {差評: 2, 失望: 2, 一般: 0.5, 后悔: 2, 坑: 1.5} self.negation_words {不, 沒, 別, 不太} def analyze_batch(self, reviews): results {positive: 0, negative: 0, neutral: 0} details [] for review in reviews: words clean_and_tokenize(review[content]) score 0 for idx, word in enumerate(words): if word in self.positive_words: score self.positive_words[word] elif word in self.negative_words: score - self.negative_words[word] # 否定詞反轉(zhuǎn)不 正面詞 負(fù)面 if idx 0 and words[idx-1] in self.negation_words: score -score if score 0.5: results[positive] 1 details.append((review[content], 正面, score)) elif score -0.5: results[negative] 1 details.append((review[content], 負(fù)面, score)) else: results[neutral] 1 details.append((review[content], 中性, score)) return {stats: results, details: details}這里有個(gè)細(xì)節(jié)值得展開否定詞反轉(zhuǎn)用的是“看前一個(gè)詞”的笨辦法遇到“不太滿意”這種雙重否定就會判錯(cuò)——“不”和“太”都是否定詞按這個(gè)邏輯會反轉(zhuǎn)兩次回到正面而實(shí)際語義是負(fù)面。要改進(jìn)就把negation_words設(shè)計(jì)成窗口掃描統(tǒng)計(jì)一句話里否定詞出現(xiàn)次數(shù)奇數(shù)次反轉(zhuǎn)、偶數(shù)次不反轉(zhuǎn)。但從畢設(shè)展示角度現(xiàn)有邏輯已經(jīng)能覆蓋絕大多數(shù)簡單評論尤其是“景點(diǎn)不錯(cuò)”“服務(wù)很差”這類直白表達(dá)。4.3 統(tǒng)計(jì)結(jié)果如何喂給前端圖表情感分析模塊輸出的stats字典包含了正、負(fù)、中三個(gè)類別的評論數(shù)量后端把這個(gè)字典連同樣例評論一起打包成 JSON 返回。前端拿到數(shù)據(jù)后用 ECharts 的餅圖展示情感分布用列表展示各情感類別下的代表性評論。這個(gè)接口的返回格式是一個(gè)約定前端result.html頁面對應(yīng)的渲染邏輯// frontend/src/pages/Result.vue 中的核心請求節(jié)選 async function loadResult() { const res await fetch(/api/analyze, { method: POST, headers: {Content-Type: application/json}, body: JSON.stringify({ scenic_id: selectedScenicId }) }) const json await res.json() if (json.code 0) { renderChart(json.data.stats) renderCommentList(json.data.details) } }selectedScenicId是用戶在前一個(gè)頁面選中的景點(diǎn) ID這個(gè)值從景點(diǎn)列表接口來。整條鏈路到這里就閉合了爬蟲負(fù)責(zé)把外部評論搬進(jìn)數(shù)據(jù)庫情感分析模塊把評論變成可量化的情感分?jǐn)?shù)前端把分?jǐn)?shù)變成圖表。從工程實(shí)現(xiàn)角度看這套系統(tǒng)最有學(xué)習(xí)價(jià)值的地方不是某個(gè)算法有多牛而是數(shù)據(jù)完整地在三個(gè)層級之間流轉(zhuǎn)沒有斷點(diǎn)。5. 避坑記錄封 IP、跨域攔截與中文亂碼四連5.1 爬蟲請求頻繁導(dǎo)致 IP 被封現(xiàn)象攜程爬蟲跑到第 30 頁左右后續(xù)所有請求返回 403頁面提示訪問異常連手動打開網(wǎng)頁都受限。原因請求頻率太高沒有設(shè)置延時(shí)攜程的反爬機(jī)制識別到同一 IP 的密集訪問后觸發(fā)了臨時(shí)封禁持續(xù)時(shí)間大約 10 到 20 分鐘。解決在爬蟲的fetch_comments里加入隨機(jī)延時(shí)用time.sleep(random.uniform(1, 3))并且把每頁的抓取間隔和總頁數(shù)關(guān)聯(lián)起來。另外把請求頭里的Accept-Language補(bǔ)上降低被識別為腳本的概率。這套系統(tǒng)原始代碼里沒有延時(shí)我拆包時(shí)第一輪復(fù)現(xiàn)就是在這個(gè)位置踩的坑加延時(shí)后連續(xù)跑 200 頁都沒再觸發(fā)封禁。5.2 前端頁面打開后所有接口報(bào)跨域錯(cuò)誤現(xiàn)象Quasar 前端跑在 8080 端口后端 Flask 跑在 5000 端口瀏覽器里請求/api/analyze直接報(bào)CORS error接口一個(gè)都調(diào)不通。原因這是一個(gè)標(biāo)準(zhǔn)的前后端分離跨域問題瀏覽器默認(rèn)禁止不同端口之間的 XHR 請求。項(xiàng)目里雖然引了flask-cors但如果你沒在 Flask 實(shí)例上正確注冊 CORS跨域照樣攔。解決后端的 Flask 入口里加一行配置# app.py 中的跨域配置 from flask_cors import CORS CORS(app, resources{r/*: {origins: *}})resources{r/*: {origins: *}}表示所有路由都允許任意來源訪問畢設(shè)本地調(diào)試夠用了。如果將來部署到服務(wù)器把origins改成前端的實(shí)際域名不要用通配符否則等于向后端開放了所有跨域權(quán)限。5.3 評論寫入 MySQL 后中文亂碼現(xiàn)象爬蟲打印的評論內(nèi)容是正常的但存進(jìn)數(shù)據(jù)庫后變成了???或者繁體亂碼。原因MySQL 數(shù)據(jù)庫表默認(rèn)字符集是latin1不支持中文。Python 的 MySQL 連接串里也沒指定charset參數(shù)導(dǎo)致寫入時(shí) UTF-8 編碼被強(qiáng)制轉(zhuǎn)成了 latin1。解決建表時(shí)指定字符集連接時(shí)也指定# db.py 中的連接串修改 engine create_engine( mysqlpymysql://root:passwordlocalhost:3306/travel_sentiment?charsetutf8mb4, echoTrue )charsetutf8mb4是關(guān)鍵參數(shù)utf8mb4是完整的 UTF-8 實(shí)現(xiàn)支持四字節(jié)的 emoji 字符。評論內(nèi)容里經(jīng)常有 emoji用utf8會報(bào)編碼錯(cuò)誤用utf8mb4才能完整存儲。5.4 馬蜂窩爬蟲采到的評論數(shù)量明顯比頁面顯示少現(xiàn)象頁面上下拉能看到四五十條評論爬蟲只抓到七八條。原因馬蜂窩的window.__INITIAL_STATE__只預(yù)埋了前兩頁數(shù)據(jù)后續(xù)內(nèi)容全部靠滾動觸發(fā)接口動態(tài)加載而網(wǎng)絡(luò)請求拿到的 HTML 里根本不含這些動態(tài)內(nèi)容。解決接受現(xiàn)實(shí)——用預(yù)埋數(shù)據(jù)抓取就是只能抓到兩頁的量。如果確實(shí)需要更多直接在爬蟲里再請求馬蜂窩內(nèi)部的評論分頁接口但這個(gè)接口的簽名參數(shù)是加密的調(diào)試成本比較高。畢設(shè)答辯場景下能抓到二三十條有效評論做情感分析展示就足夠了重點(diǎn)是把清洗和分析鏈路講清楚評審老師不會糾結(jié)樣本量。6. 答辯前的最后一道工序換景點(diǎn)重跑全流程的檢查清單這套系統(tǒng)默認(rèn)帶了幾個(gè)演示景點(diǎn)但答辯時(shí)最出彩的動作是現(xiàn)場換一個(gè)完全沒跑過的景點(diǎn)從爬蟲到情感分析全鏈路走一遍。換景點(diǎn)不需要動代碼只需要改一個(gè)參數(shù)景點(diǎn) ID。攜程的景點(diǎn) ID 去景點(diǎn)頁 URL 里找馬蜂窩的景點(diǎn) ID 去poi/后面的數(shù)字串里找。我自己的習(xí)慣是答辯前強(qiáng)制走一遍完整的驗(yàn)證流程按順序確認(rèn)五件事第一確認(rèn)后端服務(wù)活著curl http://localhost:5000/api/ping返回值正常第二確認(rèn)前端頁面能打開登錄后能看到景點(diǎn)列表第三執(zhí)行一次新景點(diǎn)的爬蟲確認(rèn)數(shù)據(jù)庫里新增了對應(yīng)評論第四在前端頁面選擇這個(gè)新景點(diǎn)確認(rèn)情感分布圖和評論列表渲染出來了第五抽查三條評論人工判斷情感傾向是否和分析結(jié)果一致。# 一鍵驗(yàn)證腳本 check_pipeline.sh #!/bin/bash # 檢查后端 curl -s http://localhost:5000/api/ping | grep -q pong echo [OK] 后端存活 || echo [FAIL] 后端未啟動 # 檢查數(shù)據(jù)庫評論數(shù) mysql -uroot -p123456 -e SELECT COUNT(*) FROM reviews WHERE scenic_name東方明珠; # 檢查情感分析接口 curl -s -X POST http://localhost:5000/api/analyze -H Content-Type: application/json -d {scenic_id:124} | python -m json.tool | head -20這個(gè)腳本看起來簡單但實(shí)際能擋住大部分低級的答辯事故后端忘了啟動、數(shù)據(jù)庫沒建表、景點(diǎn) ID 選錯(cuò)導(dǎo)致接口返回空數(shù)據(jù)。每次換新景點(diǎn)我會先把要換的 ID 記下來跑完爬蟲后立刻查一下數(shù)據(jù)庫的寫入量確認(rèn)沒有因?yàn)榉磁?IP 封禁導(dǎo)致零數(shù)據(jù)入庫。還有一個(gè)細(xì)節(jié)容易被忽略爬蟲抓下來的是實(shí)時(shí)評論但情感分析的結(jié)果只對當(dāng)前數(shù)據(jù)庫里的數(shù)據(jù)有意義。答辯前不要反復(fù)跑同一個(gè)景點(diǎn)的爬蟲因?yàn)橹貜?fù)評論會被content_hash唯一索引攔掉但接口的響應(yīng)時(shí)間會變長——評審老師看到頁面轉(zhuǎn)圈超過三秒整個(gè)演示的流暢度就打折了。從那以后我每次做類似的項(xiàng)目演示都會強(qiáng)制把“換數(shù)據(jù)源重跑全鏈路”這一步放進(jìn)檢查清單先確認(rèn)數(shù)據(jù)能進(jìn)來再確認(rèn)分析能算完最后才點(diǎn)開前端頁面。這套流程看著笨但能幫你篩掉八成現(xiàn)場翻車的情況。希望幫到你。本文還有配套的精品資源點(diǎn)擊獲取