python基礎(chǔ)教程項目三之萬能的XML
這個項目的名稱與其叫做萬能的XML不如叫做自動構(gòu)建網(wǎng)站,根據(jù)一份XML文件,生成對應(yīng)目錄結(jié)構(gòu)的網(wǎng)站,不過只有html還是太過于簡單了,如果要是可以連帶生成css那就比較強大了。這個有待后續(xù)研發(fā),先來研究下怎么html網(wǎng)站結(jié)構(gòu)。 既然是通過XML結(jié)構(gòu)生成網(wǎng)站,那所有的事情都應(yīng)該由這個XML文件來。先來看下這個XML文件,website.xml:
<website> <page name="index" title="Home page"> <h1>Welcome to my Home page</h1> <p>Hi, there. My name is Mr.gumby,and this is my home page,here are some of my int:</p> <ul> <li><a href="interests/shouting.html" rel="external nofollow" >Shouting</a></li> <li><a href="interests/sleeping.html" rel="external nofollow" >Sleeping</a></li> <li><a href="interests/eating.html" rel="external nofollow" >Eating</a></li> </ul> </page> <directory name="interests"> <page name="shouting" title="Shouting"> <h1>shouting page</h1> <p>....</p> </page> <page name="sleeping" title="Sleeping"> <h1>sleeping page</h1> <p>...</p> </page> <page name="eating" title="Eating"> <h1>Eating page</h1> <p>....</p> </page> </directory> </website>
有了這個文件,下面應(yīng)該來看怎么通過這個文件生成網(wǎng)站。
首先我們要解析這個xml文件,python解析xml和在java中一樣,有兩種方式,SAX和DOM,兩種處理方式不同點在于速度和范圍,前者講究的是效率,每次只處理文檔的一小部分,快速而能有效的利用內(nèi)存,后者是相反的處理方式,先把所有的文檔載入到內(nèi)存,然后再進行處理,速度比較慢,也比較消耗內(nèi)存,唯一的好處就是可以操作整個文檔。
在python中使用sax方式處理xml要先引入xml.sax中的parse函數(shù),還有xml.sax.handler中的ContentHandler,后面的這個類是要和parse函數(shù)來配合使用的。使用方式如下: parse('xxx.xml',xxxHandler),這里面的xxxHandler要繼承上面的ContentHandler,不過只要繼承就行,不需要有所作為。 然后這個parse函數(shù)在處理xml文件的時候,會調(diào)用xxxHandler中的startElement函數(shù)和endElement函數(shù)來一個xml中的標(biāo)簽的開始和結(jié)束,中間的過程使用一個名為characters的函數(shù)來處理標(biāo)簽內(nèi)部的所有字符串。
有了上面的這些認識,我們已經(jīng)知道如何處理xml文件了,然后再來看那個罪惡的源頭website.xml文件,分析其結(jié)構(gòu),只有兩個節(jié)點:page和directory,很明顯page表示一個頁面,directory表示一個目錄。
所以處理這個xml文件的思路就變的清晰了。讀取xml文件的每一個節(jié)點,然后判斷是page還是directory如果是page則創(chuàng)建html頁面,然后把節(jié)點中的內(nèi)容寫到文件里。如果遇到directory就創(chuàng)建一個文件夾,然后再處理其內(nèi)部的page節(jié)點(如果存在的話)。
下面來看這部分代碼,書中的實現(xiàn)比較復(fù)雜,比較靈活。先來看,然后在分析。
from xml.sax.handler import ContentHandler from xml.sax import parse import os class Dispatcher: def dispatch(self, prefix, name, attrs=None): mname = prefix + name.capitalize() dname = 'default' + prefix.capitalize() method = getattr(self, mname, None) if callable(method): args = () else: method = getattr(self, dname, None) args = name, if prefix == 'start': args += attrs, if callable(method): method(*args) def startElement(self, name, attrs): self.dispatch('start', name, attrs) def endElement(self, name): self.dispatch('end', name) class WebsiteConstructor(Dispatcher, ContentHandler): passthrough = False def __init__(self, directory): self.directory = [directory] self.ensureDirectory() def ensureDirectory(self): path = os.path.join(*self.directory) print path print '----' if not os.path.isdir(path): os.makedirs(path) def characters(self, chars): if self.passthrough: self.out.write(chars) def defaultStart(self, name, attrs): if self.passthrough: self.out.write('<' + name) for key, val in attrs.items(): self.out.write(' %s="%s"' %(key, val)) self.out.write('>') def defaultEnd(self, name): if self.passthrough: self.out.write('</%s>' % name) def startDirectory(self, attrs): self.directory.append(attrs['name']) self.ensureDirectory() def endDirectory(self): print 'endDirectory' self.directory.pop() def startPage(self, attrs): print 'startPage' filename = os.path.join(*self.directory + [attrs['name']+'.html']) self.out = open(filename, 'w') self.writeHeader(attrs['title']) self.passthrough = True def endPage(self): print 'endPage' self.passthrough = False self.writeFooter() self.out.close() def writeHeader(self, title): self.out.write('<html>\n <head>\n <title>') self.out.write(title) self.out.write('</title>\n </head>\n <body>\n') def writeFooter(self): self.out.write('\n </body>\n</html>\n') parse('website.xml',WebsiteConstructor('public_html'))
看起來這個程序上面分析的復(fù)雜了一些,不過偉人毛毛說過,任何復(fù)雜的程序都是紙老虎。那我們再來分析一下這個程序。
首先看到這個程序是有兩個類,其實完全可以當(dāng)作一個類,因為有了繼承。
然后再來看它多了些什么,除了我們分析出來的startElement和endElement以及characters,多出來了startPage,endPage;startDirectory,endDirectory;defaultStart,defaultEnd;ensureDirectory;writeHeader,writeFooter;和dispatch,這些個函數(shù)。除了dispatch,前面的函數(shù)都很好理解,每一對函數(shù)都是單純的處理對應(yīng)的html標(biāo)簽以及xml節(jié)點。而dispatch比較復(fù)雜,復(fù)雜之處在于他是用來動態(tài)拼合函數(shù)并且進行執(zhí)行的。
dispatch的處理思路是,首先根據(jù)傳遞的參數(shù)(就是操作名稱以及節(jié)點名稱)判斷是否存在對應(yīng)的函數(shù)如startPage,如果不存在則執(zhí)行default+操作名稱:如defaultStart。
一個函數(shù)一個函數(shù)搞清楚之后,就知道整個處理流程是什么樣了。首先創(chuàng)建一個public_html的文件,存放整個網(wǎng)站,然后讀xml的節(jié)點,通過startElement和endElement調(diào)用dispatch進行處理。然后就是dispatch怎么調(diào)用具體的處理函數(shù)了。 到此為止,這個項目算是分析完了。
主要掌握的內(nèi)容一個是python中使用SAX處理XML,另一個就是python中的函數(shù)的使用,比如getattr,傳參數(shù)時的星號……
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- python基礎(chǔ)教程之?dāng)?shù)字處理(math)模塊詳解
- python基礎(chǔ)教程之popen函數(shù)操作其它程序的輸入和輸出示例
- python基礎(chǔ)教程之類class定義使用方法
- python基礎(chǔ)教程之基本數(shù)據(jù)類型和變量聲明介紹
- python基礎(chǔ)教程之lambda表達式使用方法
- Python安裝使用命令行交互模塊pexpect的基礎(chǔ)教程
- python基礎(chǔ)教程之實現(xiàn)石頭剪刀布游戲示例
- python基礎(chǔ)教程項目四之新聞聚合
- python基礎(chǔ)教程項目二之畫幅好畫
- python基礎(chǔ)教程項目五之虛擬茶話會
相關(guān)文章
基于python實現(xiàn)鼠標(biāo)實時坐標(biāo)監(jiān)測
這篇文章主要給大家介紹了如何基于python實現(xiàn)鼠標(biāo)實時坐標(biāo)監(jiān)測,文章通過代碼示例介紹的非常詳細,對大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下2023-11-11python神經(jīng)網(wǎng)絡(luò)Densenet模型復(fù)現(xiàn)詳解
這篇文章主要為大家介紹了python神經(jīng)網(wǎng)絡(luò)Densenet模型復(fù)現(xiàn)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-05-05Python中schedule模塊關(guān)于定時任務(wù)使用方法
這篇文章主要介紹了Python中schedule模塊關(guān)于定時任務(wù)使用方法,文章圍繞主題展開詳細的內(nèi)容介紹,具有一定的參考價值,需要的小伙伴可以參考一下2022-05-05Ubuntu下使用python讀取doc和docx文檔的內(nèi)容方法
今天小編就為大家分享一篇Ubuntu下使用python讀取doc和docx文檔的內(nèi)容方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-05-05Python爬蟲入門案例之爬取去哪兒旅游景點攻略以及可視化分析
讀萬卷書不如行萬里路,學(xué)的扎不扎實要通過實戰(zhàn)才能看出來,本篇文章手把手帶你爬取去哪兒平臺的旅游景點攻略并進行可視化分析,大家可以在過程中查缺補漏,看看自己掌握程度怎么樣2021-10-10Python函數(shù)調(diào)用的幾種方式(類里面,類之間,類外面)
本文主要介紹了Python函數(shù)調(diào)用的幾種方式(類里面,類之間,類外面),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-07-07