方 煒
(安徽師范大學(xué)圖書館 安徽蕪湖 241003)
圖書采購查重是指對(duì)海量的館藏文獻(xiàn)資源與計(jì)劃采購的文獻(xiàn)列表進(jìn)行篩選、去重,避免因重復(fù)采購而造成資源的浪費(fèi)。這在圖書館資源建設(shè)過程中是非常重要的一環(huán),但也是圖書館采訪人員長期以來面臨的難點(diǎn)。因?yàn)閳D書查重是一種勞力密集的重復(fù)性工作,既簡(jiǎn)單又枯燥,必須耗費(fèi)大量的人力和時(shí)間,同時(shí)采訪人員長時(shí)間進(jìn)行重復(fù)單調(diào)的工作,很容易產(chǎn)生漏檢和錯(cuò)檢[1]。目前業(yè)界出現(xiàn)了多種查重方法和查重系統(tǒng),各有優(yōu)劣。筆者通過分析現(xiàn)有查重方法和系統(tǒng)的使用效果,針對(duì)其不足之處,設(shè)計(jì)了一套基于Python語言以及PyQt工具包的圖書采購查重系統(tǒng)。
采訪工作中的查重,實(shí)際上是將兩個(gè)書目信息列表進(jìn)行比對(duì)的過程,現(xiàn)有館藏書目(以下簡(jiǎn)稱“源書目”)信息一般存儲(chǔ)在各圖書館數(shù)據(jù)庫中,而計(jì)劃采購書目(以下簡(jiǎn)稱“目標(biāo)書目”)信息一般為圖書館自搜集的書目清單,或由書商提供的書目清單。從技術(shù)層面來看,目前常見的查重方式有以下3種:①圖書管理系統(tǒng)。圖書館在文獻(xiàn)資源建設(shè)時(shí)一定會(huì)使用圖書管理系統(tǒng),而大多數(shù)管理系統(tǒng)如ILAS、ALEPH 500中已經(jīng)集成了采訪查重功能,因此部分圖書館直接通過其正在使用的圖書管理系統(tǒng)進(jìn)行查重。②工具系統(tǒng)。在圖書管理系統(tǒng)無法充分滿足自身查重需求時(shí),部分圖書館采用內(nèi)部開發(fā)或購買獨(dú)立的查重工具系統(tǒng)的方式進(jìn)行查重。③人工比對(duì)。早期,在圖書館數(shù)字化建設(shè)還不夠成熟的時(shí)候,人工比對(duì)是唯一的查重方式,但是隨著館藏資源數(shù)量的劇增,純粹意義上的人工比對(duì)方法已經(jīng)無法實(shí)施。但是針對(duì)某些信息不規(guī)范或殘缺的特殊文獻(xiàn),采訪人員需進(jìn)行人工主觀鑒別,再進(jìn)行查重。
以上提到的3種查重方式仍然廣泛應(yīng)用在圖書館的采訪工作中,其使用環(huán)境和查重效率方面各有優(yōu)劣。
1.2.1 圖書管理系統(tǒng)
圖書管理系統(tǒng)工作過程是圖書管理系統(tǒng)自動(dòng)分析采訪人員上傳的目標(biāo)書目文件,進(jìn)行數(shù)據(jù)庫比對(duì),并由管理系統(tǒng)自動(dòng)輸出結(jié)果。這種方法要求目標(biāo)書目文件格式規(guī)范,滿足系統(tǒng)輸入要求,且比對(duì)項(xiàng)符合系統(tǒng)規(guī)則,可以被系統(tǒng)正常識(shí)別。
圖書管理系統(tǒng)查重的優(yōu)點(diǎn)為:實(shí)時(shí)準(zhǔn)確。因?yàn)槭侵苯釉L問源數(shù)據(jù)庫,其信息都是實(shí)時(shí)的,不會(huì)出現(xiàn)信息滯后,查詢結(jié)果準(zhǔn)確。其缺點(diǎn)為:①依賴網(wǎng)絡(luò)。無論采訪人員在館內(nèi)還是館外,都必須具有網(wǎng)絡(luò)訪問權(quán)限,且要求網(wǎng)絡(luò)快速穩(wěn)定,否則將造成無法訪問或查重效率低下等問題。②靈活性差。系統(tǒng)對(duì)目標(biāo)書目文件的格式有著嚴(yán)格的要求,且查重字段也必須完全相同,但工作人員從各種渠道獲得的目標(biāo)書目文件格式各異,所以需先進(jìn)行整理和轉(zhuǎn)換后才能進(jìn)行查重。③可維護(hù)性差。常見的系統(tǒng)都是商業(yè)公司的產(chǎn)品,如果采訪人員需要根據(jù)特定的場(chǎng)景自定義查重方法,很難單獨(dú)要求其修改功能,即便進(jìn)行了修改,在升級(jí)系統(tǒng)時(shí)也難免會(huì)影響到其他功能的正常使用。
1.2.2 工具系統(tǒng)
目前常用的工具系統(tǒng)主要分為B/S架構(gòu)和C/S架構(gòu)。如果圖書管理系統(tǒng)提供了對(duì)外訪問接口,兩種架構(gòu)都可以進(jìn)行遠(yuǎn)程實(shí)時(shí)查重,區(qū)別不大。但在沒有訪問接口時(shí),B/S架構(gòu)的系統(tǒng)一般是先將源數(shù)據(jù)庫導(dǎo)出備份到服務(wù)器上,再連接查詢備份的數(shù)據(jù)庫。而C/S架構(gòu)的系統(tǒng)則是從源數(shù)據(jù)庫中導(dǎo)出Excel、MARC等格式的備份文件,然后再利用讀取文件信息的方式解析其中包含的書目信息,進(jìn)行比對(duì)后輸出結(jié)果。
工具系統(tǒng)查重的優(yōu)點(diǎn)為:①靈活性高。工具系統(tǒng)在研發(fā)設(shè)計(jì)時(shí)針對(duì)性較強(qiáng),完全為采訪查重工作服務(wù),可以充分滿足采訪人員的查重需求。②易維護(hù)。因?yàn)槭仟?dú)立的工具系統(tǒng),所以易于修改和擴(kuò)展,及時(shí)滿足采訪人員的工作需求,具有更多的靈活性,而且不用擔(dān)心會(huì)影響到圖書管理系統(tǒng)。其缺點(diǎn)為:①實(shí)時(shí)性受限。如果圖書管理系統(tǒng)提供了接口,查詢結(jié)果具有實(shí)時(shí)性。反之,因?yàn)槭莻浞輸?shù)據(jù),所查詢出的結(jié)果具有滯后性。②需要技術(shù)支持。無論是導(dǎo)出到備份數(shù)據(jù)庫或是本地文件,都需要相關(guān)技術(shù)人員的操作,后期的擴(kuò)展和維護(hù)更是需要技術(shù)支持。
1.2.3 人工比對(duì)
針對(duì)某些特定文獻(xiàn)或特殊場(chǎng)景,人工查重是一個(gè)更加主觀準(zhǔn)確的查重方式。采訪人員首先利用自身專業(yè)知識(shí)和工作經(jīng)驗(yàn)對(duì)目標(biāo)書目進(jìn)行信息提取和分類,再逐條輸入到圖書管理系統(tǒng)中查詢,并對(duì)最終的查重結(jié)果做出修改和確認(rèn)。
人工比對(duì)查重的優(yōu)點(diǎn)為:靈活性高。采訪人員可以主觀分辨出相似的書目,也可以根據(jù)經(jīng)驗(yàn)對(duì)記錄有誤的信息進(jìn)行人工糾錯(cuò)等。其缺點(diǎn)為:①效率低。在目標(biāo)書目數(shù)量較為龐大的情況下,人工比對(duì)的速度慢,需要耗費(fèi)大量時(shí)間完成。②易產(chǎn)生誤差。因?yàn)槭侨斯け葘?duì),難免會(huì)因?yàn)楣ぷ髌诨蚴韬龆鴮?dǎo)致結(jié)果出現(xiàn)偏差。
通過上面的優(yōu)劣對(duì)比,筆者認(rèn)為工具系統(tǒng)查重是三者中最為方便、靈活的查重方式。不僅可以在不影響源數(shù)據(jù)庫的情況下進(jìn)行操作,還可以利用其可擴(kuò)展性充分滿足采訪人員的工作需求,其效率和準(zhǔn)確度上也為最優(yōu)。其中,C/S架構(gòu)的系統(tǒng)比B/S架構(gòu)的系統(tǒng)更為合適,理由如下:①易于安裝部署。B/S架構(gòu)的系統(tǒng)必須安裝數(shù)據(jù)庫軟件,而數(shù)據(jù)庫軟件本身又比較龐大,不便于安裝,而且需要進(jìn)行配置部署后才能訪問。相反,C/S架構(gòu)的系統(tǒng)安裝程序體積小,無需配置部署,直接操作交互界面即可使用。②適用場(chǎng)景廣泛。B/S架構(gòu)的系統(tǒng)一般都部署在固定的服務(wù)器上,必須通過網(wǎng)絡(luò)遠(yuǎn)程訪問。而C/S架構(gòu)的系統(tǒng)則不僅可以通過網(wǎng)絡(luò)訪問遠(yuǎn)程數(shù)據(jù)庫,也可以在無網(wǎng)絡(luò)的環(huán)境下直接操作本地備份文件,適用于館內(nèi)館外的各種場(chǎng)景。
Python是一門應(yīng)用廣泛的通用編程語言,易于學(xué)習(xí)使用且功能強(qiáng)大,適合各種規(guī)模的軟件編寫[2]。其文件處理功能也非常強(qiáng)大。例如,可以使用xlrd、xlwt模塊對(duì)Excel文件進(jìn)行讀寫;利用xml.dom模塊對(duì)XML文件進(jìn)行讀寫等。此外,針對(duì)超大文件,Python還可以進(jìn)行分塊讀取,很好地解決了內(nèi)存不足等問題。
Qt庫是目前最強(qiáng)大的GUI庫之一,而PyQt作為一個(gè)強(qiáng)大的工具包,成功地將腳本語言Python和Qt庫融合到了一起,利用它可以很方便地創(chuàng)建GUI應(yīng)用程序[3]。這是實(shí)現(xiàn)查重系統(tǒng)中用戶交互界面模塊最佳的方案。
因此,本查重系統(tǒng)是基于Python語言,再結(jié)合PyQt工具包進(jìn)行開發(fā),最終生成了一個(gè)Windows環(huán)境下的安裝程序,采訪人員直接進(jìn)行單機(jī)安裝即可投入使用。
采訪人員在查重時(shí)的工作流程一般分為4個(gè)步驟:①輸入源書目信息以及目標(biāo)書目信息。這些信息一般以文件的形式呈現(xiàn),如Excel文件、MARC格式的.marc文件或.iso文件等。②選定需要進(jìn)行比對(duì)的字段。書目信息一般包含多個(gè)字段,但因存儲(chǔ)方式不同,各字段又無法一一對(duì)應(yīng),因此要人工選取合適的字段進(jìn)行比對(duì)。③執(zhí)行查重。查重系統(tǒng)根據(jù)輸入的文件信息,以及采訪人員選定的字段進(jìn)行自動(dòng)比對(duì)。④輸出結(jié)果。待查重系統(tǒng)運(yùn)算完畢之后,根據(jù)采訪人員指定的結(jié)果存儲(chǔ)方式,將結(jié)果輸出到本地文件中。
2.3.1 文件讀取
通過調(diào)查采訪人員的工作過程發(fā)現(xiàn),采訪人員存儲(chǔ)書目信息的文件格式一般為Excel文件或者M(jìn)ARC格式的.marc文件和.iso文件,其中MARC作為機(jī)讀目錄格式的大統(tǒng)一,借其數(shù)據(jù)格式的標(biāo)準(zhǔn)化及細(xì)分化優(yōu)勢(shì),廣泛應(yīng)用于各類圖書館的編目工作中,在采訪工作中也是主流文件[4]。因此,查重系統(tǒng)中應(yīng)該具備讀取并解析這些文件格式的功能模塊。此外,還需要考慮到源書目文件較大,可能是GB級(jí)別的文件,而一般的計(jì)算機(jī)閑置內(nèi)存可能只有幾百M(fèi)B,如果全部直接加載到內(nèi)存,系統(tǒng)可能會(huì)因?yàn)閮?nèi)存耗盡而無響應(yīng)等問題,需要確保此功能模塊可以處理大文件。
2.3.2 解析字段
常見的查重比對(duì)都是只比較ISBN字段,但是為了讓采訪人員可以更靈活地比對(duì)書目信息,本系統(tǒng)將提供字段解析模塊,首先應(yīng)分析文件的類型,再用不同的方式獲取其字段信息。例如,Excel文件中,其字段信息一般為每個(gè)Sheet中第一行的數(shù)據(jù);而MARC格式的字段則是和數(shù)據(jù)一起存放在每個(gè)條目中。
因?yàn)榇嬖诙喾N文件格式,所以對(duì)應(yīng)字段的存儲(chǔ)方式存在差異。例如,MARC字段中代表出版社的字段為“010”,子字段“b”,而在Excel文件中,字段名稱直接存儲(chǔ)為字符串“出版社”,無法直接進(jìn)行比較。因此本模塊將采用配置文檔的方式,使得用戶可以自定義MARC字段表示的名稱,從而實(shí)現(xiàn)不同類型文件之間的查重。
2.3.3 比對(duì)查重
根據(jù)采訪人員選擇需要比對(duì)的字段信息,采用遍歷的方式,提取源書目和目標(biāo)書目中被選字段對(duì)應(yīng)的數(shù)據(jù),最后再通過字符串比對(duì)的方式進(jìn)行查重。但是如果直接字符串比對(duì),又無法兼容一些可能存在的問題。例如,2007年起使用的新版ISBN號(hào)是13位,而在此之前都是使用10位來表示,對(duì)于同一本書的新舊表示方法,必須在比對(duì)時(shí)要考慮到兼容性[5]。此外還有字符串中存在多余空格、大小寫等問題也將在本模塊中考慮到。
2.3.4 輸出結(jié)果
對(duì)于采訪工作人員來說,最終的查重結(jié)果一般為方便存儲(chǔ)、閱讀的本地文件。因此,本系統(tǒng)擬將結(jié)果寫入到新創(chuàng)建的Excel文件中,并分成重復(fù)列表和非重復(fù)列表兩個(gè)工作Sheet,采訪人員可以直接用Office軟件打開查看。其中重新創(chuàng)建Excel文件的方式可以保證原始文件不會(huì)被損壞。
本系統(tǒng)的開發(fā)IDE選為PyCharm。PyCharm是一款功能強(qiáng)大的Python編輯器,帶有一整套可以幫助用戶在使用Python語言開發(fā)時(shí)提高其效率的工具,且具有跨平臺(tái)性[6]。
文件讀取功能的實(shí)現(xiàn)主要使用的是I/O函數(shù)、xlrd和xml.dom模塊:
# Read and parse MARC file
class MARCHelper(object):
def __init__(self,file_path):
self._file = open(file_path,'rb')
… …
# Read and parse Excel file
class ExcelHelper(object):
def __init__(self,file_path):
self._ file_data = xlrd.open_workbook(_file_path,use_mmap=0,on_demand=True)
… …
# Read and parse config file(.xml)
class MARCFiledManager:
def __init__(self,file_path):
self.file_dom = xml.dom.minidom.parse(file_path)
… …
Excel文件讀取字段的方式為直接讀取第一張工作Sheet的第一行內(nèi)容:
… …
def get_column_names(self):
column_names = self.get_row_value(0,0)
return column_names
… …
針對(duì)MARC文件的方式則為解析字段以及子字段標(biāo)識(shí)符,再通過比對(duì)XML格式配置文檔里的信息,找到對(duì)應(yīng)的字段名稱[7]。其中配置文件的格式如下:
… …
… …
采訪人員可以根據(jù)需求自行修改配置文件中的字段名稱,以便更靈活地進(jìn)行字段比對(duì)。
比對(duì)方面,設(shè)計(jì)時(shí)采用了面向?qū)ο笾卸鄳B(tài)的概念,在處理Excel文件的ExcelHelper類,以及處理MARC文件的MARCHelper類中,定義了相同的check_row_exist函數(shù):
def check_row_exist(self,compared_columns_index,tar_value,tar_columns_index):
除此之外,還定義了一個(gè)遍歷書目信息的迭代器,可以循環(huán)讀取數(shù)據(jù):
… …
def set_iter_begin(self):
… …
def get_iter(self):
… …
def next_iter(self):
… …
查重時(shí)迭代器的使用方法如下:
self.__instance_tar_file_helper.set_iter_begin()
iter_not_end = self.__instance_tar_file_helper.next_iter()
while iter_not_end:
… …
iter_not_end = self.__instance_tar_file_helper.next_iter()
其中,Excel數(shù)據(jù)以讀到最后一張工作Sheet的最后一行作為結(jié)束,MARC文件則是讀到空行作為結(jié)束。
由于數(shù)據(jù)量可能較大,比對(duì)過程將需要很長的時(shí)間,所以必須采用多線程的方式進(jìn)行比對(duì)操作,否則主交互界面將會(huì)卡死,導(dǎo)致程序崩潰,用戶交互也不夠友好。因此在實(shí)現(xiàn)此功能時(shí)繼承了QThread類,并采用Signal與Slots的方式讓數(shù)據(jù)處理層和UI層進(jìn)行通訊:
… …
class GetDuplicateColumnNamesThread(QtCore.QThread):
GetDuplicateColumnNames_Finished_Signal= QtCore.pyqtSignal(list)
… …
class CheckAndSaveThread(QtCore.QThread):
CheckAndSave_Finished_Signal = QtCore.pyqtSignal()
… …
為了方便閱讀,最終的結(jié)果是存儲(chǔ)到Excel文件中,所以采用的是xlwt模塊,為此代碼中專門定義了一個(gè)ExcelSaver類,并新建一個(gè)文件:
class ExcelSaver(object):
def __init__(self):
self._work_book = xlwt.Workbook()
進(jìn)行比對(duì)之前會(huì)先建立兩個(gè)工作Sheet,即重復(fù)的和非重復(fù)的,并寫入列名:
… …
excel_saver = ExcelSaver()
excel_saver.add_sheet(u'非重復(fù)')
excel_saver.add_sheet(u'重復(fù)')
column_names = self.__instance_tar_file_helper.get_column_names()
excel_saver.insert_row(u'重復(fù)',0,column_names)
excel_saver.insert_row(u'非重復(fù)',0,column_names)
… …
比對(duì)過程中會(huì)自動(dòng)插入數(shù)據(jù),在結(jié)束時(shí)進(jìn)行保存:
… …
if duplicate:
excel_saver.append_row(u'重復(fù)',tar_value)
else:
excel_saver.append_row(u'非重復(fù)',tar_value)
… …
excel_saver.save(result_file_path)
… …
本系統(tǒng)的UI界面是先使用Qt Designer創(chuàng)建并設(shè)置好所有控件,再轉(zhuǎn)換為Python文件,效果如圖1所示。
圖1 UI界面效果圖
UI上用兩個(gè)QLineEdit分別表示源書目和目標(biāo)書目的文件路徑,并提供QFileDialog方便用戶選擇文件。
在用戶設(shè)置完路徑并點(diǎn)擊顯示列名后,UI下方采用QTableWidget來顯示可以進(jìn)行比對(duì)的字段,以及可以讓用戶勾選的CheckBox。
用戶選擇完畢后直接點(diǎn)擊QPushButton實(shí)現(xiàn)的查重按鈕,會(huì)出現(xiàn)讓用戶選擇保存結(jié)果文件的對(duì)話框,然后即開始進(jìn)行查重。查重的同時(shí)UI界面的中間會(huì)出現(xiàn)一個(gè)模態(tài)等待對(duì)話框。
… …
class WaitingDialog(QtWidgets.QDialog):
def __init__(self,parent=None):
QtWidgets.QDialog.__init__(self,parent)
self.setWindowTitle('Please wait...')
self.setWindowFlag(QtCore.Qt.SplashScreen)
… …
待查重完畢之后,會(huì)有對(duì)話框提示用戶操作完成,此時(shí)用戶可以打開保存的文件,閱讀查重結(jié)果。
在進(jìn)行UI界面的設(shè)計(jì)時(shí),也考慮到了采訪人員所用系統(tǒng)語言環(huán)境的問題,將要顯示的文字都進(jìn)行了國際化處理,程序可以自動(dòng)識(shí)別當(dāng)前系統(tǒng)的語言,顯示對(duì)應(yīng)的語言文字:
… …
def translate_ui(self,BookListCheckerClass):
_translate = QtCore.QCoreApplication.translate
BookListCheckerClass.setWindowTitle(_trans late("BookListCheckerClass","圖書查重系統(tǒng)"))
self.label_source_books.setText(_translate("BookListCheckerClass","現(xiàn)有圖書:"))
… …
本系統(tǒng)的設(shè)計(jì)和實(shí)現(xiàn)采用了目前較為前沿的Python語言和Qt框架,充分發(fā)揮了其文件處理功能和GUI搭建功能,為后來圖書采購查重系統(tǒng)的開發(fā)選擇提供了參考,推動(dòng)了圖書采購查重自動(dòng)化的發(fā)展??傮w來看,具有以下優(yōu)點(diǎn):①易安裝使用。系統(tǒng)的安裝程序大小在35MB以內(nèi),易于攜帶和安裝。采訪人員無需網(wǎng)絡(luò),無需配置數(shù)據(jù)庫等操作,即可隨時(shí)使用。對(duì)于經(jīng)常在外采購圖書的工作人員非常適用。②支持文件類型豐富。為了充分滿足查重需求,本系統(tǒng)在文件類型的支持上涵蓋了常用的.xls、.xlsx、.iso、.marc等書目信息格式。③比對(duì)靈活。不僅可以讓用戶復(fù)選比對(duì)字段,還考慮到了ISBN的兼容性問題、Excel字段和MARC字段不對(duì)應(yīng)的問題,并允許用戶進(jìn)行自定義字段,使得系統(tǒng)可以更靈活地滿足查重需求。④系統(tǒng)可移植性高。本系統(tǒng)所采用技術(shù),無論是Python還是Qt都是跨平臺(tái)的,其可移植性高,可以不僅僅依賴于Windows操作系統(tǒng)。
本系統(tǒng)依然存在不足之處。例如,文件類型的支持雖然已經(jīng)滿足常用的需求,但是還可以進(jìn)一步擴(kuò)大,如.txt和.cvs等格式的文件。另外,本系統(tǒng)雖然在設(shè)計(jì)上已經(jīng)預(yù)留了網(wǎng)絡(luò)查詢接口,但在實(shí)現(xiàn)上還沒有全部完成,暫時(shí)沒能彌補(bǔ)其實(shí)時(shí)性差的缺點(diǎn)。希望在后續(xù)的工作中可以繼續(xù)完善該系統(tǒng),更好地為查重工作提供自動(dòng)化服務(wù)。