DBLP資料集python解析

shuaishuai3409發表於2017-01-10

DBLP是計算機領域內對研究的成果以作者為核心的一個計算機類英文文獻的整合資料庫系統,按年代列出了作者的科研成果。包括國際期刊和會議等公開發表的論文。DBLP沒有提供對中文文獻的收錄和檢索功能,國內類似的權威期刊及重要會議論文整合檢索系統有C-DBLP。其並沒有把資料儲存在資料庫中,而是儲存在了XML檔案中。DBLP在學術界聲譽很高,而且很多論文及實驗都是基於DBLP的。所收錄的期刊和會議論文質量較高,也比較全面。能很好地反應了國外學術研究的前沿方向。DBLP資料下載地址

XML 指可擴充套件標記語言(eXtensible Markup Language),XML 被設計用來傳輸和儲存資料。XML是一套定義語義標記的規則,這些標記將文件分成許多部件並對這些部件加以標識。它也是元標記語言,即定義了用於定義其他與特定領域有關的、語義的、結構化的標記語言的句法語言。

本文介紹了python三種常見的xml解析方法,分別是SAX,DOM,ElementTree。以DBLP的xml資料為例,用SAX的方式對xml資料進行解析,並對解析後的資料儲存到了txt檔案中。


python對XML的解析

常見的XML程式設計介面有DOM和SAX,這兩種介面處理XML檔案的方式不同,當然使用場合也不同。python有三種方法解析XML,SAX,DOM,以及ElementTree:

1.SAX (simple API for XML )

python 標準庫包含SAX解析器,SAX用事件驅動模型,通過在解析XML的過程中觸發一個個的事件並呼叫使用者定義的回撥函式來處理XML檔案。

2.DOM(Document Object Model)

將XML資料在記憶體中解析成一個樹,通過對樹的操作來操作XML。

3.ElementTree(元素樹)

ElementTree就像一個輕量級的DOM,具有方便友好的API。程式碼可用性好,速度快,消耗記憶體少。

PS:因DOM需要將XML資料對映到記憶體中的樹,一是比較慢,二是比較耗記憶體,而SAX流式讀取XML檔案,比較快,佔用記憶體少,但需要使用者實現回撥函式(handler)。


python 解析DBLP資料的方式

DBLP資料的格式如下圖,紅色框部分是資料集的某個完整屬性。每份資料以屬性article開頭,子屬性共有9個,分別是(author,title,pages,year,volume,journal,number,url,ee)。注意作者author這個屬性可能不止一個,因為每篇論文的作者可以有多個。

這裡寫圖片描述

程式碼,gogo帥提供:

# -*- coding: utf-8 -*-
"""
Created on Tue Jan 10 14:10:12 2017
@author: Administrator
"""
#!/usr/bin/python
# -*- coding: UTF-8 -*-
from __future__ import print_function
import xml.sax
import sys  
import io
import traceback 
sys.stdout = io.TextIOWrapper(sys.stdout.buffer,encoding='utf8') #改變標準輸出的預設編碼  
class MovieHandler( xml.sax.ContentHandler ):
   res=''
   def __init__(self):
      self.CurrentData = ""
      self.author = ""
      self.title = ""
      self.pages = ""
      self.year = ""
      self.volume = ""
      self.journal = ""
      self.number = ""
      self.url = ""
      self.ee = ""
   # 元素開始事件處理
   def startElement(self, tag, attributes):
      self.CurrentData = tag
      if tag == "article":
         print("self.__class__.res=",self.__class__.res)
         try:
           ww.write(self.__class__.res+'\n')//資料集中有不良資料,捕獲一下
         except:
             traceback.print_exc()
         self.__class__.res=''
        # print ("*****article*****")
         mdate = attributes["mdate"]
         #print ("mdate:", mdate)
         key=attributes["key"]
         #print ("key:",key)
         self.__class__.res=self.__class__.res+mdate+';,;'+key+';,;'
         #print ('res_init:',self.__class__.res)

   # 元素結束事件處理
   def endElement(self, tag):
      if self.CurrentData == "author":
         #print ("author:", self.author)
         self.__class__.res=self.__class__.res+self.author+';,;'
      elif self.CurrentData == "title":
         #print ("title:", self.title)
         self.__class__.res=self.__class__.res+self.title+';,;'
      elif self.CurrentData == "pages":
         #print ("pages:", self.pages)
         self.__class__.res=self.__class__.res+self.pages+';,;'
      elif self.CurrentData == "year":
         #print ("year:", self.year)
         self.__class__.res=self.__class__.res+self.year+';,;'
      elif self.CurrentData == "volume":
         #print ("volume:", self.volume)
         self.__class__.res=self.__class__.res+self.volume+';,;'
      elif self.CurrentData == "journal":
         #print ("journal:", self.journal)
         self.__class__.res=self.__class__.res+self.journal+';,;'
      elif self.CurrentData == "number":
         #print ("number:", self.number)
         self.__class__.res=self.__class__.res+self.number+';,;'
      elif self.CurrentData == "url":
         #print ("url:", self.url)
         self.__class__.res=self.__class__.res+self.url+';,;'
      elif self.CurrentData == "ee":
         #print ("ee:", self.ee)
         self.__class__.res=self.__class__.res+self.ee+';,;'
      self.CurrentData = ""


   # 內容事件處理
   def characters(self, content):
      if self.CurrentData == "author":
         self.author = content+'####'
      elif self.CurrentData == "title":
         self.title = content
      elif self.CurrentData == "pages":
         self.pages = content
      elif self.CurrentData == "year":
         self.year = content
      elif self.CurrentData == "volume":
         self.volume = content
      elif self.CurrentData == "journal":
         self.journal = content
      elif self.CurrentData == "number":
         self.number = content
      elif self.CurrentData == "url":
         self.url = content
      elif self.CurrentData == "ee":
         self.ee = content
if ( __name__ == "__main__"):

   parser = xml.sax.make_parser()
   parser.setFeature(xml.sax.handler.feature_namespaces, 0)
   Handler = MovieHandler()
   parser.setContentHandler( Handler )
   ww=open('dblp_parse_result.txt','w+')
   parser.parse("dblp.xml")
   ww.close()

注意:只需下載dblp.dtd和dblp.xml.gz兩個檔案,紅色框圈住的,而且讀取資料的時候,兩個檔案要放在同一個目錄下面。

這裡寫圖片描述

參考資料:http://www.runoob.com/python/python-xml.html

相關文章