何艷,張寧
西安郵電大學 通信與信息工程學院,陜西 西安 710121
通過互聯網得到科學準確的醫療服務與人們的幸福生活密切相關,智能問答平臺有助于快速篩選搜索信息。自動聊天機器人可分為以信息提取為基礎的專家系統和自主生產學習式的開放領域問答平臺系統[1]。垂直領域的專家系統大大壓縮了數據規模,適用于醫療領域的應用開發[2]。語義分析是實現智能問答的基本途徑。在傳統TextRank算法和Word2Vec基礎上,Python以MySQL+Flask web +vue分級架構實現了知識自動問答[3]。醫療數據包含大量冗余文本數據。聯合標注策略的實體關系抽取模型使用NoSQL數據庫Neo4j存儲知識數據,獲得較高檢索效率[4]。Java語言的MVC(Model、View、Controller)架構將后臺運算與前端顯示分離[5-6]。利用多源異構數據構建醫療相關知識庫,聯合中文分詞和醫療詞典,準確識別醫療相關領域詞匯[7]。不同數據庫的知識存儲會影響問答效率。MySQL體積小、速度快,在靈活性上遠超SQL Sever和Oracle數據庫[8]。利用Redis數據庫緩存,可提高系統處理高并發場景時的效率[9]。ANSJ實現分詞,且標注分詞后詞性,在內存中分詞速率100萬字/s,準確度達96%以上[10-11]。Spring作為JavaWeb框架,集成了控制翻轉和面向切面編程的特點[12-13]。布隆過濾器利用錯誤率換取更小的空間占用,其操作時間復雜度為O(1)[14-15]。本文旨在設計實現一款智能問答系統,通過用戶對自身病情癥狀的描述,系統通過語義解析得到合理準確的醫療指導,進而給人們提供日常的健康醫療咨詢。
本醫療問答系統設計框圖如圖1所示,系統采用分級架構,使得數據庫、邏輯層、展示層分開,便于分層開發維護。

圖1 系統設計框圖
后端代碼結構大致分為Controller、Dao、Pojo、Service、Test五部分。其中Controller層負責與前端代碼的交互,接收或發送數據到前端。Pojo層存儲項目對應的數據模型類。Service層負責處理項目的主要邏輯。Test負責代碼的調試與測試功能。圖2展示了后端項目代碼結構。

圖2 后端項目代碼結構
在數據庫連接的部分,采用基于JDBC的Java數據庫連接工具Mybatis進行Java程序與MySQL數據庫的連接。使用注解的方式完成連接,并將SQL語句卸載至xml文件中,便于維護管理[16]。同時項目采用了Mybatis自帶的SQL預處理方式,避免了SQL注入的風險。
醫療問答系統的數據模型包括用戶集合、疾病集合和用戶患病集合。用戶集合用于存儲普通用戶在平臺進行登錄、注冊、問答咨詢所需的基本信息;疾病集合用于存儲爬取的醫療相關信息;用戶患病集合用于存儲疾病與用戶之間的對應關系,形成用戶表與疾病表之間多對多的表間關系。各表間關系繪制成實體聯系圖如圖3所示。

圖3 系統數據庫實體聯系圖
由于項目前后端分離的設計,在本機測試時兩端會分別占用不同端口,前端Vue部分占用8080端口,后端占用8081端口。前后端的數據交互采用JSON(JavaScript Object Notation)數據格式。依照JSON將后端Java實體類序列化成字符串的格式發送至前端解析,同時前端也能發送JSON至后端,經由后端轉換為實體類。在Java中,可以將JSON還原為HashMap結構或者一個基本對象。
本系統在多個角度進行了并發設計,確保了程序的穩定性(圖4)。系統設計將Tomcat服務器默認提供的BIO模式改配置為NIO模式。BIO模式下,每次請求會新建一個線程去處理,線程的創建與銷毀極大地浪費了系統資源,改為NIO模式后不用每次阻塞線程,提高了系統效率。在編寫Java代碼時,內部使用了HashMap作為緩存暫時存儲數據庫查詢結果,避免每次處理時對數據庫的反復查詢。利用WebMagic的多線程爬蟲特性爬取醫療數據,開啟5個線程同時爬取,提高了系統速度。

圖4 醫療問答系統的并發設計圖
考慮到系統各模塊間耦合度高,本系統在架構設計上采用MVC模式解耦合。將系統拆分為View(前端視圖層)、Controller(邏輯控制層)、Model(中間數據邏輯層),分別對應后端代碼中的Controller、Service、Pojo三個文件夾。其中Controller文件夾中主要編寫基于SpringMVC的相關代碼,負責通過http協議完成前后端數據交互。Service文件夾中主要編寫問答系統的主要邏輯,即接收到問題后對問題處理并回復的過程。Pojo文件夾中則存放系統用到的實體類,包括用戶類、醫療信息類。三層分離編寫,互不干擾。三層間通過數據接口交互,方便分模塊糾錯。
問答模塊是系統的主要邏輯模塊,具體流程是前端接收用戶輸入的語句傳輸至后端,隨后進入Service層。通過Ansj對語句進行分詞處理,并按照詞性摘取出語句中的動詞、名詞等作重點處理,并將其存入HashMap標記為InfoMap。依次遍歷InfoMap中的所有詞,并在MySQL數據庫中查找相關疾病的癥狀,并記錄疾病名稱和出現次數至Disease Map中,最后通過SpringMVC反饋給前端。
用戶信息處理模塊包含對用戶注冊信息的數據庫寫入以及對登錄用戶信息的查庫校驗。項目中的User類對應MySQL中的User表,分別設置Uid、UName、Password三個字段,簡單地實現了登錄注冊功能所需要的所有信息。用戶通過/login進入登錄模塊前端頁面,輸入用戶名密碼后發送至后端,在通過MySQL查詢登錄信息完成校驗,校驗成功后自動轉入問答模塊。注冊功能則是在數據庫中存入用戶的注冊信息,注冊完成后返回登錄頁面。
信息獲取模塊負責自動獲取醫療網站內醫療相關的信息,醫療數據內容爬取后重新存儲,見圖5。借助WebMagic提供的爬蟲接口,使用Java線程池技術配置多個線程同時爬蟲,考慮到本電腦使用四核CPU,確定開啟五個線程,理論上獲得了五倍速度的爬蟲效率。通過爬蟲獲取疾病名稱、疾病描述、病因、癥狀、治療手段、診斷鑒別等多種信息,對應創建其Java類用于存儲,最后通過Mybatis的持久化技術將醫療數據存儲至MySQL數據庫中。

圖5 爬取獲得的醫療數據內容
網絡爬蟲策略包括借助棧結構實現的深度優先搜索、借助隊列實現的廣度優先搜索以及最佳優先搜索。
最佳優先搜索比深度優先策略和廣度優先搜索策略更加復雜,但在面對大量網頁爬取的任務時,能更好地過濾掉30%以上的無關網頁。它的邏輯是在爬取之前先對候選URL進行一系列的相似度分析,并最終選擇爬取與主題相關度更高的網頁,節省計算機資源。
WebMagic是一個基于Java的開源爬蟲框架,其整體 結 構 包 括 Downloader、PageProcessor、Scheduler和Pipeline四個組件,分別對應爬蟲生命周期中的下載、清洗、時間管理和持久化。需要將這些組件結合并完成多線程任務以提高爬蟲效率,同時使用容器spider將組件組織起來協作完成任務。圖6展示了Web Magic各模塊協作工作流程。

圖6 WebMagic運行流程圖
數據庫技術主要研究目標是數據,實現數據高效存儲與快速獲取。目前的主流數據庫分為關系型數據庫與非關系型數據庫兩種。關系型數據庫指采用行列表格形式組織數據,其主要模塊是二維的表格。如圖7所示分為表頭和內容,多個數據表組成了數據庫。為了避免數據重復存儲,按照最小關系表的形式存儲,采用SQL對數據庫進行增刪改查等操作。

圖7 關系型數據庫的數據表
非關系型數據庫也被叫作NoSQL(不適于SQL語句的意思),其速度優勢得益于Hash數據結構,其預先準備適當長度的存儲空間,并做線性標記。當有數據存入空間時,采用特定哈希算法計算數據位置后存入,在后續查詢過程中,只需要將查詢詞再次進行哈希計算,就能在01的復雜度內完成查詢操作,同比使用了B+樹的MySQL數據庫,查詢的時間復雜度遠遠超過01。
分詞技術將連續詞語組成的句子重新分割成各個詞語,便于計算機分治處理。中文分詞算法大致分為基于詞典的分詞算法與基于人工智能統計的分詞算法。Java語言提供了盤古分詞、NLPIR、IKAnalyzer、PaodingAnalyzer等分詞工具。由于AnsjSeg提供便捷的分詞接口,分詞處理后,框架將會返回句子中所有詞語與其所對應的詞性,因此本文將采用AnsjSeg分詞工具。
Mybatis是源于Apache的一個開源項目,完成了對底層JDBC的封裝,簡化了后端連接數據庫的步驟,對外提供簡便的接口。其解除了SQL語句與程序代碼的耦合,將業務層與數據訪問分離使系統結構更加清晰。
用戶自主輸入隨意用戶名密碼即可完成注冊,注冊成功后系統自動跳轉到登錄頁。用戶在輸入自身癥狀后,系統會反饋可能性病癥以及其可能性權值。用戶登錄成功后,頁面將自動跳轉到/work路徑展示問答頁面,用戶向第一個輸入框內輸入疾病癥狀(不需要特殊格式),點擊提交按鈕后,前端自動將內容提交至后臺分析,隨后Java后臺經過分詞處理后向數據庫查詢結果,結果集將封裝在TreeMap中暫存,由于TreeMap可以將key值排序,所以得到疾病可能性權值將從小到大展示。
數據庫中的醫療數據均由數據獲取模塊提供,首先對被爬取網頁進行分析,確保其Robot協議允許用戶爬蟲。隨后分析其頁面結構尋找需要爬取的頁面特性,通過WebMagic對頁面進行解析,獲取其中關鍵標簽所包含的有用信息,在遇到多種冗余信息存儲于同一標簽下時,則采用CSS選擇器篩選出符合條件的數據。并將其保存至Java的Static靜態類中(靜態類保證了在類中字段填滿之前,爬蟲的重復執行并不會刷新對象中內容),等到類的其他字段通過爬蟲填滿后統一寫入數據庫,完成一組數據的爬取。
項目測試環境為Windows 10 PC一臺,Java8編譯環境,Firefox瀏覽器。使用Java首先啟動graduationdesign項目,查看SpringBoot啟動日志,確定8081端口打開無誤后再啟動前端VUE代碼。項目啟動效果如圖8~9所示。

圖8 后端項目啟動頁面

圖9 前端項目啟動頁面
問答模塊測試使用用戶組織的語言對系統進行提問,系統將自動反饋可能性病癥,并以JASON的數據格式發送至前端,包括疾病的名稱及可能性權值,癥狀描述越多越準確。可以在瀏覽器中查詢到前后端數據交互的情況如圖10所示。在數據爬蟲測試中,后端提前綁定MySQL服務器,啟動后自動查找尋醫問藥網中關于呼吸科的疾病信息,同一疾病分別爬取疾病的名稱、癥狀、治療方法、病因、簡介五個信息后,進行數據庫查詢校驗,如果與庫中數據不重復,統一存入數據庫。

圖10 問答功能數據交互詳情
醫學領域的信息化和智慧化建設是當前迫切需要解決的難題。在信息技術發展的同時,人們也逐步由初始的單純對速度與信息量的追求,進而發展為對信息準確性和高效性的追求。目前市面上的各類搜索引擎所提供的信息檢索服務大都趨向于百科全書式的大雜燴,用戶搜索關鍵知識時,往往會檢索出許多冗余的“垃圾”數據,浪費人們的時間。還有一些搜索引擎在返回正常搜索數據的同時還會夾雜一些廣告,使得用戶的搜索效率大幅降低。傳統搜索引擎在醫療領域的使用,有助于獲取互聯網上全面的信息資源,但如何篩選信息成為難題。
本文開發設計的基于JavaEE的醫療問答系統,通過網絡爬蟲爬取醫療相關數據,并將其存儲至MySQL數據庫中。用戶注冊系統后,后臺數據庫保存其個人信息,登錄系統后顯示提問頁面。用戶發問后利用分詞技術分析問題,快速將反饋結果發送至前端,實現用戶注冊、登錄、注銷、查詢等基本功能。
由于醫療領域的專業性和需求迫切性,各種不同形式的醫療問答系統被推向市場,如騰訊醫典、平安好醫生以及丁香醫生等。區別于傳統搜索引擎,本文開發的醫療問答系統將目標聚焦于垂直醫療領域,通過對用戶語句的語義分析進行模糊匹配,確保搜索的結果信息控制在一個較小的維度,為患者提供準確、高效的醫療咨詢服務。利用基于JavaEE的醫療問答系統可以實現用戶對于自身癥狀的初步判斷,系統通過分析用戶提供的癥狀描述,取得用戶描述內容的關鍵詞,將關鍵詞與醫療數據庫中內容匹配,通過規則推理和本體描述實現問答功能。本文開發實現的基于Java的醫療問答系統,其注冊登錄流程簡潔,界面層級清晰,通過分詞技術和關系型數據庫的聯合使用,結合爬蟲策略,實現了醫療垂直領域的問答,能便捷、及時解決用戶健康需求。本系統采用了高擴展性系統架構,未來可以進一步擴充性能,以提供更智慧快捷的醫療服務。
與此同時,本系統也有許多需要優化改進的地方。前端頁面的UI以功能實用為主,沒有考慮到美學設計理念。此外,目前系統只是爬取了呼吸內科相關疾病,后臺數據庫中醫療數據的爬取不夠全面。在問答過程中問答信息偏學術化,略顯機械,后續需改進該系統的人性化。