由於經常要查詢C++相關的資料,翻書太麻煩,MSDN太大,去網上查詢又太慢。於是決定將www.cplusplus.com整個打包成CHM,以便查詢用。
將網站down下來之後,發現要做成CHM還是有不少後期工作要做,比如:應該把頁面右上方的Login去掉。。。
正好學了Python一直沒有派上大的用場,咱露它一小手吧。
第一個問題就是遍曆目錄的問題,網站下面有好幾十個目錄,以前寫C++的經驗告訴我,這得用一個遞迴函式來遍曆。但在Python中,一個walk函數搞定一切,Fantastic!
舉個例子:
E盤根目錄下有檔案夾a
a
├──aa
│ ├──aaa
│ ├──aa.txt
│ └──ab.txt
├──ab
│ ├──aba
│ └──ab.txt
├──a.txt
└──b.txt
在Python中對目錄a進行walk後:
>>> import os<br />>>> a=os.walk(r'e:/a')<br />>>> for i in a:<br />... print i<br />...<br />('e://a', ['aa', 'ab'], ['a.txt', 'b.txt'])<br />('e://a//aa', ['aaa'], ['aa.txt', 'ab.txt'])<br />('e://a//aa//aaa', [], [])<br />('e://a//ab', ['aba'], ['ab.txt'])<br />('e://a//ab//aba', [], [])
其傳回值是一個Generator,每次迭代的結果是一個Tuple t,由三個元素組成,
t[0]為當前所遍曆的目錄名
t[1]為目前的目錄下的所有子目錄
t[2]為目前的目錄下的所有檔案名稱
這使得遍曆目錄相當輕鬆。
修改頁面內容的指令碼如下:(略去了實現細節)
def deco_NeedTempFile(func):<br /> '''decorate the func which need a temporary file<br /> 其實這裡完全可以不用裝飾器,只是為了體驗一下<br /> 如何向被裝飾函數中添加參數<br /> '''<br /> import os<br /> import tempfile<br /> tmpf = tempfile.NamedTemporaryFile(delete=False)<br /> tmpf.close()<br /> def new_func(*args, **argkw):<br /> '''append tmpf to the parameter tuple then call it<br /> 這裡又是Python的一個新穎的文法知識,變參<br /> C++中操縱變參那叫一個複雜,而Python中用<br /> *args表示一個Tuple,其中是非關鍵字參數<br /> **argkw表示一個Dictionary,其中是關鍵字參數</p><p> 例如我定義一個def f(kw=-1,*args, **argskw)<br /> 那麼調用f(1,2,ar=2)將會使得<br />kw=1, args=(2,), argskw={'ar':2}<br /> 調用f(1,(2,3),ar=2)將會使得args=((2,3),)<br /> 要想使(2,3)解包,得調用f(1,*(2,3),ar=2),則args=(2,3)<br /> 同理若f(1,*(2,3),**{'a':1,'b':3}),則argskw={'a':1,'b':3}<br /> '''<br /> arg=list(args)<br /> arg.append(tmpf)<br /> return func(*tuple(arg), **argkw)<br /> new_func.func_name = func.func_name<br /> new_func.__doc = func.__doc__<br /> return new_func</p><p>def RemoveLogin(origin):<br /> '''Remove the 'InitJS()' from the string origin<br /> '''<br /> LOGIN = 'onLoad="InitJS()"'<br /> if LOGIN in origin:<br /> origin=origin.replace(LOGIN, '')<br /> return origin;</p><p>def MakeOutsideLinkRed(origin):<br /> '''Make hypertext which link outside<br /> '''<br /> kw = ('Articles', 'Forums')<br /> for s in kw:<br /> if s in origin and '<tr><td><a href="' in origin:<br /> re = '<tr><td><span class=outside><a href="http://www.cplusplus.com/'/<br /> +s.lower()+'/" mce_href="http://www.cplusplus.com/'/<br /> +s.lower()+'/"><b>' + s + '</b></a></span></td></tr>/n'<br /> return re<br /> return origin</p><p>def AddTipAfterHead(origin):<br /> '''Point out whether it is Local page<br /> '''<br /> H1 = '<h1>'<br /> XXLARGE = '<span style="font-size:xx-large" mce_style="font-size:xx-large">'<br /> if XXLARGE in origin: split = origin.find('</b>')<br /> elif H1 in origin: split = origin.find('</h1>')<br /> else: return origin</p><p> re = origin[0:split] + ' <font color=red>[in CHM]</font><font color=white> by thy38</font>'/<br /> + origin[split:]<br /> return re</p><p>def MakeSearchEngineOutside(origin):<br /> if 'action="/query/search.cgi"' in origin:<br /> split = origin.find('/query/search.cgi')<br /> re = origin[0:split] + 'http://www.cplusplus.com' + origin[split:]<br /> return re<br /> return origin</p><p>@deco_NeedTempFile<br />def ModifyAllDefault(d, tmpf):<br /> '''Find all default.htm in directory d and remove it LOGIN<br /> '''<br /> DEFAULT = 'default.htm'<br /> import os<br />#由於迭代器遍曆一次就回不了頭了,所以我將它轉換成tuple<br />#這樣就可以多次遍曆了<br /> allfiles=tuple(os.walk(d))<br /> totalFileNum = sum(len(a[-1]) for a in allfiles)<br /> current=0<br /> for i in allfiles:<br /> if DEFAULT in i[-1]:<br /> fo = open(i[0]+'//'+DEFAULT, 'r')<br />#以'w'開啟檔案相當於清空內容<br /> tmpf = open(tmpf.name, 'w')<br /> firstTime=True<br /> willBeBox=False<br /> for x in fo:<br /> x=RemoveLogin(x)<br /> x=MakeOutsideLinkRed(x)<br /> x=AddTipAfterHead(x)<br /> x=MakeSearchEngineOutside(x)</p><p> tmpf.write(x)</p><p> fo.close()<br /> os.remove(fo.name)<br />#tmpf如果不想close,則必須調用flush,將緩衝區的內容<br />#立即寫入檔案,否則下面copyfile的內容將不完整<br /> tmpf.close()</p><p>## import shutil<br />## shutil.copyfile(tmpf.name, fo.name)<br />##通過學習知道,上面shutil的copyfile比較慢<br />##現改成用os.rename<br /> os.rename(tmpf.name, fo.name)</p><p> current += 1<br /> print current,'/',totalFileNum,'-->"'+fo.name+'" is done!'</p><p>def main():<br /> ModifyAllDefault(r'e:/CppReference')<br /> #ModifyAllDefault('e:/a')</p><p>if __name__ == '__main__':<br /> main()
輸出結果:
Command line: D:/programs/Python26/python.exe D:/Projects/Python/MODIFY~1.PY
Working directory: D:/Projects/Python
Timeout: 0 ms
1 / 2135 -->"e:/CppReference/www.cplusplus.com/default.htm" is done!
2 / 2135 -->"e:/CppReference/www.cplusplus.com/articles/default.htm" is done!
3 / 2135 -->"e:/CppReference/www.cplusplus.com/doc/default.htm" is done!
......
1194 / 2135 -->"e:/CppReference/www.cplusplus.com/reference/string/string/swap/default.htm" is done!
1195 / 2135 -->"e:/CppReference/www.cplusplus.com/reference/string/swap/default.htm" is done!
1196 / 2135 -->"e:/CppReference/www.cplusplus.com/src/default.htm" is done!
Process "Python Interpreter" terminated, ExitCode: 00000000
一個小程式讓我學到了很多東西,由於是自用的,也沒有錯誤處理,也沒有異常。所以
我一定會回來的!